Как заставить fields_for создавать новые объекты и отношения «многие ко многим» одновременно?

Я следил за этими Railscasts и пытался изменить код, чтобы он работал с Rails 3:

http://railscasts.com/episodes/73-complex-forms-part- 1

http://railscasts.com/episodes/73-complex-forms-part- 2

http://railscasts.com/episodes/73-complex-forms-part- 3

Я пытаюсь создать группы, пользователей и членство (отношения «многие ко многим») одновременно. Люди могут добавлять пользователей в группу по мере ее создания, а затем я хочу, чтобы она направлялась к представлению группы со всеми участниками. Я могу создать членство, но у меня проблемы с созданием пользователей и их привязкой к группе. Мой код в настоящее время выглядит так:

Группа.рб

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

  attr_accessible :group_name

  def user_attributes=(user_attributes)
    user_attributes.each do |attributes|
      users.build(attributes)
    end
  end
end

Членство.рб

class Membership < ActiveRecord::Base
  belongs_to :groups
  belongs_to :users
end

Пользователь.rb

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

groups_controller.rb

class GroupsController < ApplicationController
  def create #todo test for number of groups they're already in before creation
    @group = Group.new(params[:group])
    @group.memberships.build(:user_id => current_user.id)
    #@group..build

    respond_to do |format|
      if @group.save
        format.html { redirect_to(@group, :notice => 'Group was successfully created and user added...?') }
      else
        format.html { render :action => "new" }
      end
    end
  end
end

Моя форма выглядит так:

Создатель формы

Который создан:

просмотры/группы/new.html.rb

<h1>New group</h1>

<%= form_for(@group) do |f| %>
<fieldset>
  <legend>Create a new group</legend>
  <%= render 'shared/group_error_messages', :object => f.object %>  
  <div class="clearfix">
    <%= f.label :group_name %>
    <div class="input">
      <%= f.text_field :group_name %>
    </div>
  </div>

  <div id="users">
    <%= render :partial => 'user', :collection => @group.users %>
  </div>

</div>
<p><%= add_user_link "Add a member" %></p>


<div class="actions">
  <%= f.submit :value => 'Create your group', :class => 'btn success'%>

  <!-- todo test for if they already have a group...-->
</div>
</fieldset>
<% end %>

представления/группы/_user.html.rb

<div class="user">
  <%= fields_for :user do |f| %>
    <div class="clearfix">
    <%= f.label :name %>
    <div class="input">
      <%= f.text_field :name %>
    </div>
  </div>
  <div class="clearfix">
    <%= f.label :number %>  
    <div class="input">
      <%= f.text_field :number %>
    </div>
  </div>
  <%= link_to_function "remove", "$(this).up('.user').remove()" %>
  <% end %>
</div>

Заранее большое спасибо :)


person Richard Burton    schedule 31.08.2011    source источник


Ответы (1)


Кажется, вы наткнулись на довольно устаревший Railscast. Некоторые стареют очень хорошо... этот не так сильно. То, что вы ищете, это accepts_nested_attributes_for, который был представлен в rails 2.3. .

Групповая модель:

#app/models/group.rb
class Group < ActiveRecord::Base
  has_many :memberships
  has_many :users, :through => :memberships

  accepts_nested_atrributes_for :users
end

Групповой контроллер:

#app/controllers/groups_controller.rb
Class GroupsController < ApplicationController
  def create
    @group = Group.new(params[:group)
    @group.save ? redirect_to(@group) : render("new")
  end
end

Новое групповое действие:

  <!-- Giving you the important changes only -->
  <div id="users">
    <%= render :partial => 'user', :collection => @group.users, :locals => { :form => f } %>
  </div>

Часть пользователя:

<div class="user">
  <%= form.fields_for :user do |f| %>

Как правило, вы должны использовать более описательные имена для ваших переменных блока формы, особенно с вложенными формами.

person Patrick Robertson    schedule 31.08.2011
comment
Привет, Патрик. Большое спасибо за ваш ответ. Я изменил имя переменных блока и перенес партиал в основную форму для целей тестирования. Я получаю сообщение об ошибке: Обработка с помощью GroupsController#create as HTML. }}, commit=>Создайте свою группу} ВНИМАНИЕ: Невозможно массово назначить защищенные атрибуты: пользователь AREL (0,4 мс) ВСТАВИТЬ В группы (group_name, cre - person Richard Burton; 31.08.2011
comment
Возможно, вам придется пойти по пути внесения в черный список определенных полей в app/models/group.rb с атрибутом attr_protected вместо внесения в белый список с атрибутом attr_accessible. Вложенные атрибуты кажутся защищенными случайно. - person Patrick Robertson; 06.09.2011