2012-02-20 5 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 и сохранение его не добавляет дополнительную запись в соединительной таблице ,

Infact, в данном случае @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 

Однако для этого, чтобы работать Params хэш, представленный Groups#create должен включать user_ids как:

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

Может быть, что было причиной, почему @ bruno077 просит вас для вставки кода вашего представления, чтобы получить представление о параметрах user_ids.

Итак, если новая групповая форма содержит поля для выбора нескольких пользователей, то это простое действие create, как показано выше (из-за параметров user_ids). Но если у вас есть новая групповая форма без параметров для выбора пользователей, тогда вам лучше использовать первый вариант (один из которых использует create).

+0

только передаваемые параметры являются группой [name] и group [description]. Суть вопроса заключается в том, что есть встроенная асимметрия в build vs, чтобы создать насколько ассоциации идут. Проблема с if @ group.save; #create membership; заключается в том, что он не является атомарным, если членство терпит неудачу, вы остаетесь с сиротой. –

+0

Также создание с Group.new вообще не поможет, даже если есть форма с несколькими пользователями, потому что ассоциация никогда не используется вообще. Это никогда не будет простым действием для создания, подобным выше. –

+0

Да, проблема создания группы, создающей членство, является атомарностью, так как это две совершенно разные транзакции.Однако, я полагаю, не будет такой проблемы, используя create, т. Е. 'Current_user.groups.create (params [: group])' как свою единственную транзакцию. Если проверка модели соединения приводит к сбою в создании записи в таблице соединений, тогда откат транзакций. Таким образом, не будет группы, не связанной с членством. – prasvin

Смежные вопросы