可以在没有连接表的情况下使用accepts_nested_attributes_for吗?

时间:2017-08-04 20:47:19

标签: ruby-on-rails

我有以下型号:

class Club < ApplicationRecord
  has_many :users
  accepts_nested_attributes_for :users
end

class Users < ApplicationRecord
  belongs_to :club
end

我的理解是我应该能够将这个用户添加到俱乐部:

c = Club.first
p = { :users_attributes => [{:id => 1, :club_id => 2}] }
c.update(p)

当我这样做时,收到以下错误:

2.4.1 :003 > c.update(p)
(0.3ms)  BEGIN
User Load (0.8ms)  SELECT "users".* FROM "users" WHERE "users"."club_id" = $1 AND "users"."id" = 1  [["club_id", 2]]
(0.2ms)  ROLLBACK
ActiveRecord::RecordNotFound: Couldn't find User with ID=1 for Club with ID=2

Rails似乎在允许我更新用户之前检查用户是否已经是俱乐部的成员。

如果我尝试将已经在俱乐部中的用户修改为另一个俱乐部,那就有效。

我想我可以通过创建连接表来解决这个问题,但我宁愿不这样做。救命啊!

1 个答案:

答案 0 :(得分:0)

当您想要通过父模型同时/通过相同的表单保存多个对象时,使用

accept_nested_attributes。我甚至不知道为什么你需要在俱乐部上has_many :users,因为没有用户实际上是从俱乐部建立的。通过简单地执行以下操作,用户属于俱乐部就可以简单地进行迭代:

clubs/show.html.erb 

<% Users.all.where(:club_id => @club.id).each do |user| %> 

并且您将获得所有俱乐部成员的用户。

由于你想要做的就是更新用户的club_id,你甚至不需要accept_nested_attributes,更不用说创建一个连接表了。 (除非您希望同时更新它们)。但是从我所看到的,在这种情况下你所要做的就是创建一个传递@ club.id的form_for @user,如下所示:

假设您正在俱乐部的展示页面上,或者通过可以访问@ club.id的俱乐部对象进行迭代:

 <%= simple_form_for(current_user, as: current_user, url: update_user_path(current_user), html: { method: :patch}) do |f| %>
    <%= hidden_field :club_id, :value => @club.id %>
    <%= f.button :submit, "Join Club!" %>
<% end %>

瞧瞧。用户现在拥有所需的club_id。

如果您希望通过控制台执行此操作,请执行以下操作:

x = User.find(1)
x.update(club_id: 1)

如果您想添加/删除多个用户,请执行以下操作:

x = User.find(1,2,3,4,5,6,7)
x.update(club_id: 1)

如果您希望为多个不同的用户使用不同的club_ids,您可以执行以下操作:

x = { 1 => { "club_id" => 1 }, 2 => { "club_id" => 2 } }
User.update(x.keys, x.values)

http://api.rubyonrails.org/v3.2.0/classes/ActiveRecord/Relation.html#method-i-update