Сложные формы - Управление несколькими моделями в одной форме - (безумие 3-й степени)

StackOverflow https://stackoverflow.com/questions/2258797

Вопрос

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

  1. Модель учетной записи has_many :Пользователи

  2. Пользовательская модель has_and_belongs_to_many :роли, принадлежит к :учетные записи

  3. Модель для подражания has_and_belongs_to_many :Пользователи

просмотры/ учетные записи/new.html.erb

<% for user in @account.users %>
 <% fields_for "account[user_attributes][]", user do |account_fields| %>
      <p>Login  : <%= account_fields.text_field :login %>
      <p>Email  : <%= account_fields.text_field :email %>
      <p>Password  : <%= account_fields.password_field :password %>
      <p>Confirm Password  : <%= account_fields.password_field :password_confirmation %>
      <%= account_fields.hidden_field :account_id, :value => :id %>

    <% end %>
<% end %>

<% for role in @account.users.first.roles %>
<% fields_for "account[role_attributes]]", role do |role_fields| %>
  <%= role_fields.hidden_field :role_ids, :value => '[1]' %>
 <% end %>
<% end%>

Связанные методы настройки в модели account.rb:используя stacktrace, я выделил проблему в "неопределенный метод `roles' для #" в строке 34, отмеченной ниже:

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

def role_attributes=(role_attributes)
    role_attributes.each do |attributes|
    users.roles.build(attributes)   #error here (stacktrace)
  end
end

наконец, в контроллере учетных записей я создаю пользователей и роли в памяти:

 def new
    @account = Account.new
    1.times { @account.users.build }
    1.times { @account.users.first.roles.build }

@accounts.users.first.roles.создайте доказательство из консоли:

>> account
=> #<Account id: 1, subdomain: "justinzollars", created_at: "2010-02-08 14:41:13", updated_at: "2010-02-08 14:41:13">
>> account.users
=> [#<User id: 13, login: "jayz", email: "jz@jz.com", crypted_password: "f9a3d618fc650d285a90f9775508c13784891b97", salt: "f497a7dd909b695caff1f6310e710245615d55b6", created_at: "2010-02-08 20:25:48", updated_at: "2010-02-08 20:25:48", remember_token: nil, remember_token_expires_at: nil, account_id: 1>, #<User id: 16, login: "jasonwade23", email: "jasonwade@gmail.com", crypted_password: "06581b47cfac7a529773d61dc0b1d5d6c0da6c08", salt: "93f8b99cd9da60b904d553fcc7843bfb66352c3e", created_at: "2010-02-13 07:46:14", updated_at: "2010-02-13 07:46:14", remember_token: nil, remember_token_expires_at: nil, account_id: 1>]
>> account.users.first
=> #<User id: 13, login: "jayz", email: "jz@jz.com", crypted_password: "f9a3d618fc650d285a90f9775508c13784891b97", salt: "f497a7dd909b695caff1f6310e710245615d55b6", created_at: "2010-02-08 20:25:48", updated_at: "2010-02-08 20:25:48", remember_token: nil, remember_token_expires_at: nil, account_id: 1>
>> account.users.first.roles
=> [#<Role id: 1, name: "admin">, #<Role id: 2, name: "alt">]
>> 
Это было полезно?

Решение

Вы должны использовать accepts_nested_attributes_for, так что в моделях:

# Account model
accepts_nested_attributes_for :users

# User model
accepts_nested_attributes_for :roles

Затем вы должны удалить user_attributes= и role_attributes= методы.
Ваша форма должна выглядеть примерно так:

<% form_for @account do |f| %>
   <% fields_for :users do |u| %>
      ... # user fields
      <% fields_for :roles do |r| %>
         ... # role fields
      <% end %>
   <% end %>
   <%= f.submit 'Save' %>
<% end %>

Он будет автоматически перебирать всех пользователей, связанных с учетной записью, и все роли, связанные с пользователем.

Для получения более подробной информации читайте здесь.

Редактировать:
Вы можете назначить роли пользователю в контроллере:

role = Roles.find(some_id)
@user.roles << role

или

@user.role_ids = [2, 4, 6]

Однако я не уверен, как добавить роли с has_and_belongs_to_many ассоциация.Вы используете @user.roles.build метод, который создаст новую роль и свяжет ее с пользователем.Если вы хотите добавить роль, вы должны сделать это с помощью одного из двух приведенных выше примеров.Но как создать из него?Я не знаю.Я бы добавил модель для users_roles таблица и добавление в пользовательскую модель:

has_many :users_roles
accepts_nested_attributes_for :users_roles # you should add here also some :reject_if

Затем вместо fields_for :roles Я бы добавил в форме:

<% fields_for :users_roles do |ur| %>
  <%= ur.select :role_id, Role.all.collect {|r| [r.name, r.id] }, {:include_blank => true} %>
<% end %>

Затем в вашем контроллере вы должны добавить что-то вроде 3.times { @user.users_roles.build }.Если вы хотите иметь красивые ссылки "Добавить" и "Удалить", которые создают для вас новую роль с помощью javascript, взгляните здесь - это действительно хороший пример того, как с этим справиться.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top