简单的has_many:通过关联

时间:2012-02-20 01:26:09

标签: ruby-on-rails-3 activerecord

非常简单的设置。我想确保我对ORM的理解是正确的。

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

这不起作用。该组将被保存,但链接表中没有创建成员资格记录。但是使用create vs build有效。它是如何工作的?

这里最好的方法是什么?

1 个答案:

答案 0 :(得分:0)

此行为是设计使然。如您所述,您可以@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)。