Rails: self join scheme with has_and_belongs_to_many?

后端 未结 1 954
忘了有多久
忘了有多久 2020-11-29 10:10

I would like to create a structure of Users having many friends, also of class User:

class User < ActiveRecord::Bas         


        
相关标签:
1条回答
  • 2020-11-29 11:01

    Here are some resources which may be helpful:

    • RailsCasts episode #163 Self-Referential Association regarding self-referential many-to-many relationships
    • RailsCasts episode #47 Two Many-to-Many. This might be more relevant to what you're attempting to accomplish
    • A gist someone created for self-referential relationships using HABTM

    I'll summarize the information found in those links:

    Given that you're describing a self-referential many-to-many relationship, you will of course end up with a join table. Normally, the join table should be deliberately named in such a way that Rails will automatically figure out which models the table is joining, however the "self-referential" part makes this a tad awkward, but not difficult. You'll merely have to specify the name of the join table, as well as the joining columns.

    You'll need to create this table using a migration that will probably look something like this:

    class CreateFriendships < ActiveRecord::Migration
      def self.up
        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
    
      def self.down
          remove_index(:friendships, [:friend_user_id, :user_id])
          remove_index(:friendships, [:user_id, :friend_user_id])
          drop_table :friendships
      end
    end
    

    I'm not certain whether there is a shortcut way of creating this table, but bare minimum you can simply do rails g migration create_friendships, and fill in the self.up and self.down methods.

    And then finally in your user model, you simply add the name of the join table, like so:

    class User < ActiveRecord::Base
      has_and_belongs_to_many :friends, 
                  class_name: "User", 
                  join_table: :friendships, 
                  foreign_key: :user_id, 
                  association_foreign_key: :friend_user_id
    end
    

    As you can see, while you do have a join table in the database, there is no related join model.

    Please let me know whether this works for you.

    0 讨论(0)
提交回复
热议问题