Rails中单个模型的双向has_and_belongs_to_many

时间:2016-12-24 20:37:35

标签: ruby-on-rails activerecord associations has-and-belongs-to-many has-many

我有用户模型,我想在用户之间建立友谊。我已经使用has_and_belongs_to_many

实现了这个目标
has_and_belongs_to_many :friends, class_name: 'User', foreign_key: :friend_id

我有这个协会的表格:

create_table :users_users do |t|
  t.uuid :user_id, null: false
  t.uuid :friend_id, null: false
  t.timestamps
end

当我通过user.friends获得朋友时,我需要有当前用户在user_id列或friend_id中的关联。我当前的解决方案只返回用户在friend_id表中的记录。

我有两个解决方案:

  1. 重复记录[{user_id:1,friend_id:2},{user_id:2,friend_id:1}]
  2. 覆盖user.friends方法并返回我的自定义查询
  3. 这两种解决方案都不优雅和优化。

    我已经阅读了article,但本文的解决方案非常复杂。

    这个问题还有其他解决方案吗?我正在使用rails 5.

2 个答案:

答案 0 :(得分:0)

  

首先,我宁愿使用该文章解决方案或一个查询来获取   所有记录而不是此。

执行此操作的有效记录方式是:

  1. 创建has_many关系而不是HABTM关系
  2. 查询users_users表,查找与user_id=my_user.idfriend_id=my_user.id
  3. 匹配的所有记录
  4. 展平结果
  5. 独一无二的
  6. 从阵列中删除当前用户
  7. 所以我建议将此方法放在用户模型中:

    def all_friends
        UserFriend.includes(:user, :friend).where("user_id=? OR friend_id=?", id , id).map {|rel| [rel.user, rel.friend] }.flatten.uniq{|u| u.id}.reject{|u| u.id == self.id}
    end
    

    UserFriend型号:

    class CreateUserFriends < ActiveRecord::Migration[5.0]
      def change
        create_table :user_friends do |t|
          t.belongs_to :user, foreign_key: true
          t.belongs_to :friend, foreign_key: 'friend_id', class: 'User'
    
          t.timestamps
        end
      end
    end
    

答案 1 :(得分:0)

不是100%确定这会起作用,但仍然想让你在我得到一些急需的睡眠之前尝试一下;) 为您的关联指定自定义查询方法:

has_and_belongs_to_many :friends, -> {
  where("friend_id = :user_id OR user_id = :user_id", user_id: id)
}, class_name: 'User', foreign_key: friend_id