Использование данных из связанной модели в форме, Rails 3 - PullRequest
1 голос
/ 19 сентября 2011

Есть много похожих тем, но это мне не помогает. Есть модель аккаунта

class Account < ActiveRecord::Base
  belongs_to :user
  belongs_to :currency

  attr_accessible :currency
  accepts_nested_attributes_for :currency
end

Я добавил attr_accessible и accepts_nested_attributes_for, но на самом деле я не знаю, нужны они или нет. Другая модель валюты, которая имеет 3 пункта - USD, EUR, RUR

class Currency < ActiveRecord::Base
  has_many :accounts
  attr_accessible :id

  accepts_nested_attributes_for :accounts
end

Итак, в форме аккаунта у меня есть поле выбора с валютой:

<%= form_for @account do |f| %>

  <div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
  </div>

  <div class="field">
<%= f.label :currency %><br />
<%= select_tag(:currency, options_from_collection_for_select(Currency.all, :id, :name),\
      :id => "account_currency_id", :name => "account[currency][id]", :prompt => "Выберите валюту...")%>
  </div>

<div class="actions">
<%= f.submit "Сохранить" %>
  </div>

<% end %>

И когда я пытаюсь создать ящик, произошла ошибка аккаунта:

 ActiveRecord::AssociationTypeMismatch in AccountsController#create
 Currency(#52889580) expected, got ActiveSupport::HashWithIndifferentAccess(#28841960)

Параметры запроса:

{"utf8"=>"✓",
  "authenticity_token"=>"VfCshuGyldoI5Q5DThT/RDpwewCh91apgsnmxyppWqI=",
  "account"=>{"name"=>"Основной наличный счет",
  "currency"=>{"id"=>"3"}},
  "commit"=>"Save"}

Если я пытаюсь найти валюту из Id вручную:

param = params[:account]
param[:currency] = Currency.find(param[:currency][:id])
@account = Account.new(param)

Произошла новая ошибка, ведьма Имя не существует. И мне не нравится, что я должен вручную установить :id => "account_currency_id", :name => "account[currency][id]", потому что по умолчанию они оба "валюта". Рельсы 3.1

Ответы [ 2 ]

3 голосов
/ 19 сентября 2011

В вашем случае, я думаю, вы правы, когда сомневаетесь в необходимости accepts_attributes_for. Я думаю, что есть гораздо более простой способ сделать это.

Прежде всего, удалите accepts_nested_attributes_for в обеих перечисленных вами моделях. Также удалите attr_accesible с обеих ваших моделей, это не нужно. На самом деле это причина того, почему имя не задано, модель Account принимает только хэш-присвоения для валютной переменной.

Во-вторых, в вашей форме вы должны использовать атрибут currency_id вместо currency[id]. Таким образом, вам никогда не придется проходить через другую модель. Вот как бы я это сделал:

<%= f.select(:currency_id, 
             options_from_collection_for_select(Currency.all, :id, :name),
             :prompt => "Выберите валюту...") %>

Обратите внимание, что я изменился с select_tag на f.select. Таким образом, вам не нужно указывать: id или: name вручную. Form_for в сочетании с помощником выбора позаботится об этом за вас.

Подводя итог, можно сказать, что использование accepts_nested_attributes_for в основном полезно, когда вам нужно изменить некоторые значения в связанной модели или создать / уничтожить ее экземпляры. В вашем случае вы ссылаетесь только на существующую модель валюты, не внося в нее никаких изменений.

1 голос
/ 19 сентября 2011

Вам не нужно: attr_accessible или: accepts_nested_attributes_for, если это не вложенный ресурс. attr_accessible используется для массового назначения , а accepts_nested_attributes_for определяет средство записи атрибутов для указанной ассоциации.

Измените select_tag на что-то вроде этого:

<%= f.select(:currency_id, options_from_collection_for_select(Currency.all, :id, :name), :prompt => "Выберите валюту...") %>
...