2012-02-20 11 views
0

かなりシンプルなセットアップ。 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 

これは機能しません。グループは保存されますが、リンクテーブルに作成されたメンバーシップレコードはありません。ただし、create vs buildを使用すると動作します。それはどうやって動作するのでしょうか?

ここで最善のアプローチは何ですか?

+0

@ group.save行に入力ミスがあります(先頭に@を付けてはいけません)。 – bruno077

+0

はい、それは貼り付けエラーです。まだ問題は残っています。 –

+0

あなたのビューのコードを貼り付けることができますか? – bruno077

答えて

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を実行すると[]が得られます。

これを行う最善の方法は、あなたのアプローチに多少似ています。これはとしてuser_idsを含める必要がありGroups#createに提出paramsハッシュを動作させるために、

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

しかし::などの簡単な作成の作用を有する

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

ことがbruno077 @あなたを求めていた理由だったかもしれませビューのコードを貼り付けることで、渡されるuser_idsパラメータのアイデアを得ることができます。

したがって、新しいグループフォームに複数のユーザーを選択するフィールドが含まれている場合は、(user_idsパラメータのために)上記のような簡単な作成アクションがあります。しかし、ユーザーを選択するオプションを持たない新しいグループフォームを使用している場合は、最初のオプション(createを使用したもの)を使用する方がよいでしょう。

+0

渡されるパラメータのみがグループ[名前]とグループ[説明]です。疑問の要点は、ビルドとビルドの間に固有のアシンメトリーがあるかどうかです。 @ group.saveの問題点は次のとおりです。 #会員登録する。 メンバーシップが失敗した場合、それはアトミックではないということです。孤立したグループが残っています。 –

+0

また、Group.newでの作成は、関連が全く使用されないため、複数のユーザーがいるフォームがあっても、まったく役に立ちません。それは、上記のような簡単な作成アクションではありません。 –

+0

さて、グループを作成してからメンバーシップを作成する際の問題は、2つの全く異なるトランザクションであるため、アトミック性です。しかし、私は、そのような問題は、create、つまり 'current_user.groups.create(params [:group])'を単一のトランザクションとして使用しないと仮定します。ジョイン・モデルの検証によって結合表にレコードが作成されなかった場合、トランザクションはロールバックされます。したがって、メンバーシップに関係のないグループは存在しません。 – prasvin