(轨道)如何在 Rails 中从一个嵌套表单插入创建友谊的双方?

(Rails) How to create both sides of a friendship from one nested form insert in Rails?

提问人:Tony Moritz 提问时间:9/21/2023 最后编辑:Tony Moritz 更新时间:9/22/2023 访问量:31

问:

基本上,我有一个用户模型,以及一个友谊加入表,使用户彼此成为朋友。

class User < ApplicationRecord
  has_many :friendships
  has_many :friends, through: :friendships, class_name: 'User'
class Friendship < ApplicationRecord
  belongs_to :user
  belongs_to :friend, class_name: 'User'

很简单,对吧?现在,我为每个用户的编辑页面设置了一个集合复选框,用于决定谁是他们的朋友:

<%= f.collection_check_boxes( :friend_ids, @other_users, :id, :full_name) do |b| %>
  <%= b.label(class:"form-check-label") { b.check_box(class: 'form-check') + b.text } %>
<% end %>

当我在 Timmy 的编辑页面上勾选 John 时,我希望创建两个连接表,一个将用户 (Timmy) 链接到朋友 (John),另一个将朋友链接到用户。目前,只创建一个表:

Friendship Create (0.7ms)  INSERT INTO `friendships` (`user_id`, `friend_id`, `created_at`, `updated_at`) VALUES (48, 49, '2023-09-21 14:24:36', '2023-09-21 14:24:36')

我尝试向友谊模型添加回调

  after_create do |ship|
    friend_friendship = Friendship.create(user_id: ship.friend_id, friend_id: ship.user_id)
  end

但显然这失败了,造成了一个无休止的循环!

如何轻松创建好友到用户加入?谢谢

Ruby-On-Rails 表单 模型 Ruby-On-Rails-5 相互友谊

评论

1赞 max 9/22/2023
以这种方式建模的最大缺点是,您会得到非常尴尬的查询,因为您不知道用户是在user_id列还是在friend_id列中。如果你有一个友情表和一个user_friendships联接表,那么你可以避免这个问题。
0赞 max 9/22/2023
通过尴尬的查询,我的意思是:检查相互的友谊。User.joins(:friendships).where("friendships.friend_id = :a OR friendships.user_id = :a AND friendships.friend_id = :b OR friendships.user_id = :b")
0赞 Tony Moritz 9/22/2023
@max 好的,我会调查的。

答:

-1赞 Milind 9/22/2023 #1

accept_nested_attributes是可以解决问题的东西。 您还需要创建一个连接模型。

让我们看一个例子,来理解基本的 -

#==== 3 model associations here===
class User < ActiveRecord::Base
  has_many :friends
  accepts_nested_attributes_for :friends
  has_many :friendships, through: :friends
end

class Friend < ActiveRecord::Base
  belongs_to :users
  belongs_to :Friendship
end

class Friendship < ActiveRecord::Base
  has_many :friends
  has_many :users, through: :lines
end


#===== View ====== 
<%= nested_form_for @user do |f| %>
...#user attributes
<%= f.fields_for :friends do |friend| %>
<%= friend.label :name %>
<%= friend.collection_select(:friendship_id, Friendship.all, :id, :name , {include_blank: 'Select friends'} ) %>

关联类 Friend 将通过friendship_id加入用户和 Friendship,并user_id:

评论

0赞 max 9/22/2023
你一开始的想法很好,有一个连接表的想法,但后来一切都分崩离析了。 不会在表中创建所需的 和 两行。命名也非常笨拙,因为获取的是属于该用户的联接表行,而不是您可能期望的其他用户。accepts_nested_attributes_forFriendshipfriendsuser.friends
0赞 max 9/22/2023
如果我必须在模型层上执行此操作,我将创建一个 setter,该 setter 获取用户 ID 列表并创建友谊和两个需要的连接表行。
0赞 Milind 9/22/2023
@max - 我不是来写精确的可运行代码的,我是来给人一个关于如何完成的想法,其余的事情可以在精确的代码编辑器上处理。