简单的has_many:通过关联

问题描述:

非常简单的设置。我想确保我对ORM的理解是正确的。简单的has_many:通过关联

class User < ActiveRecord::Base 
    has_many :memberships 
    has_many :groups, through => memberships 
end 

class Group < ActiveRecord::Base 
    has_many :memberships 
    has_many :users, through => memberships 
end 

class Membership < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :group 
end 

现在,当用户创建一个组时,我希望链接表中的成员记录得到填充。它应该是一个原子(交易)。

class GroupsController < ApplicationController 
    def create 

    @group = current_user.groups.build(params[:group]) 

    if @group.save 
     flash[:notice] = "Group has been created." 
     redirect_to @group 
    else 
     flash[:alert] = "Group has not been created." 
     render :action => "new" 
    end 
    end 
end 

这不起作用。该组被保存,但没有在链接表中创建成员记录。然而使用创建vs构建工程。这是它应该如何工作?

这里最好的办法是什么?

+0

你在@ group.save行中有一个错字,(if在开始时不应该有@) – bruno077 2012-02-20 02:19:59

+0

是的,这只是一个粘贴它的错误。问题依然存在。 – 2012-02-20 02:25:11

+0

你能粘贴你的视图的代码吗? – bruno077 2012-02-20 02:31:05

此行为是设计使然。正如你所提到的,你可以做@group = current_user.groups.create(params[:group])

或者你可以添加一个额外的语句来创建的连接模型的表中的记录为:

@group = current_user.groups.build(params[:group]) 
if @group.save 
    @group.memberships.create(:user_id => current_user) 
    # redirect and notify 

好,原因是简单地建立@group并保存它不连接表中增加一个额外的记录。

事实上,在这种情况下,@group = current_user.groups.build(params[:group])有点类似于@group = Group.new(params[:group])。不同之处在于,在前一种情况下,current_user.groups将包含@group(您可以在重定向之前尝试在Groups#create之前),但在做current_user.reload后跟current_user.groups将产生[]

做到这一点的最好方法有点类似于你的方法。有一个简单的创建行动:

def create 
    @group = Group.new(params[:group]) 
    # if else for save and redirect 

然而,这个工作提交Groups#create params哈希表应包括user_ids为:

"group"=>{"name"=>"new group", "user_ids"=>["1", "2", "3"]}, "commit"=>"Create Group" 

可能这就是为什么@ bruno077是问你的理由粘贴你的视图的代码,以获得关于传递的user_ids参数的想法。因此,如果新的组表单包含选择多个用户的字段,那么其简单的创建操作就像上面所示(因为user_ids参数)。但是如果有一个没有选择用户选项的新组表单,那么最好使用第一个选项(一个使用create)。

+0

只有传递参数是group [name]&group [description]。问题的症结在于,如果社团在建立和创造方面存在固有的不对称性, if @ group.save; #创建成员资格; 是,它不是原子的,如果成员资格失败,你离开孤立组。 – 2012-02-20 07:31:14

+0

即使有多个用户的表单,因为关联从来不会被使用,所以用Group.new创建也不会有任何帮助。它永远不会像上面那样简单的创建操作。 – 2012-02-20 07:53:10

+0

是的,创建组然后创建成员资格的问题是原子性,因为它们是两个完全不同的事务。但是,我认为使用create,即'current_user.groups.create(params [:group])'作为一个单独的事务不应该有这样的问题。如果连接模型验证导致无法在连接表中创建记录,则事务将回滚。所以,不应该有一个与会员关系不密切的团体。 – prasvin 2012-02-20 07:59:45