Model design: Users have friends which are users

匆匆过客 提交于 2019-12-04 07:50:12
Richard Peck

What you're looking for is something called a self referential join, which means that you can reference the same model with a different association:

#app/models/user.rb
class User < ActiveRecord::Base
   has_and_belongs_to_many :friendships,
      class_name: "User", 
      join_table:  :friendships, 
      foreign_key: :user_id, 
      association_foreign_key: :friend_user_id
end

You'd have to create a habtm join table to have a reference:

$ rails g migration CreateFriendshipsTable

#db/migrate/create_friendships_table____.rb
class CreateFriendShipsTable < ActiveRecord::Migration
   def change
      create_table :friendships, id: false do |t|
        t.integer :user_id
        t.integer :friend_user_id
      end

      add_index(:friendships, [:user_id, :friend_user_id], :unique => true)
      add_index(:friendships, [:friend_user_id, :user_id], :unique => true)
   end
end

$ rake db:migrate

There is a great reference here: Rails: self join scheme with has_and_belongs_to_many?


Is it prudent to have an additional model 'in case' additional requirements pop up later?

Only if you know you're going to have extra attributes. If not, you can get away with the habtm for as long as you want.

You can try this

--friendship.rb

class Friendship < ApplicationRecord
  belongs_to :user
  belongs_to :friend, :class_name => 'User'
end

--user.rb

class User < ApplicationRecord
  has_many :friendships
  has_many :friends, through: :friendships
end

--db migrate xxxx_create_friendship.rb

class CreateFriendships < ActiveRecord::Migration[5.0]
  def change
    create_table :friendships do |t|
      t.belongs_to :user
      t.belongs_to :friend, class: 'User'
      t.timestamps
    end
  end
end

Rich's answer was an excellent resource. I managed to subvert a few steps by following this convention:

# app/model/user.rb
has_and_belongs_to_many :friends,
  class_name: "User", 
  join_table: :friends_users, 
  foreign_key: :user_id, 
  association_foreign_key: :friend_id

This migration was sufficient (without modifying the resulting code):

rails g migration CreateFriendlyJoinTable users friends

The JoinTable syntax was found using rails generate migration -h

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!