There are a lot of similar topics, but it doesn't help me. There is a Account model
class Account < ActiveRecord::Base
belongs_to :user
belongs_to :currency
attr_accessible :currency
accepts_nested_attributes_for :currency
end
I added attr_accessible and accepts_nested_attributes_for , but actually i don't know they needed or not. Another model Currency that that has 3 items - USD, EUR, RUR
class Currency < ActiveRecord::Base
has_many :accounts
attr_accessible :id
accepts_nested_attributes_for :accounts
end
So in account form I have a selectbox with currency:
<%= 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 %>
And when i'm trying to crate Account error occurred:
ActiveRecord::AssociationTypeMismatch in AccountsController#create
Currency(#52889580) expected, got ActiveSupport::HashWithIndifferentAccess(#28841960)
Request parameters:
{"utf8"=>"✓",
"authenticity_token"=>"VfCshuGyldoI5Q5DThT/RDpwewCh91apgsnmxyppWqI=",
"account"=>{"name"=>"Основной наличный счет",
"currency"=>{"id"=>"3"}},
"commit"=>"Save"}开发者_如何学运维
If I try to find Currency from Id manually:
param = params[:account]
param[:currency] = Currency.find(param[:currency][:id])
@account = Account.new(param)
There are a new error by witch Name doesn't exists. And I don't like that i should manually set :id => "account_currency_id", :name => "account[currency][id]"
because by default they both "currency".
Rails 3.1
In your case I think you are right when you question the necessity of accepts_attributes_for
. I think there is a much easier way to accomplish this.
First thing, remove the accepts_nested_attributes_for
in both of the models you listed. Also remove the attr_accesible
from both of your models, it's not needed. That is actually the cause for why the name is not set, the Account model only accepts hash assignments for the currency variable.
Second, in your form you should use the attribute currency_id
instead of currency[id]
. That way you never have to go through another model. Here is how I would have done it:
<%= f.select(:currency_id,
options_from_collection_for_select(Currency.all, :id, :name),
:prompt => "Выберите валюту...") %>
Note that I changed from select_tag
to f.select
. That way you don't need to specify the :id or the :name manually. The form_for in combination with the select helper will take care of that for you.
To summarize, the use of accepts_nested_attributes_for
is mainly useful when you need to alter some values in an associated model or create/destroy instances of it. In your case, you are only linking to an existing currency model without making any changes in it.
You don't need :attr_accessible or :accepts_nested_attributes_for unless it is a nested resource. attr_accessible is used for mass assignment and accepts_nested_attributes_for defines an attributes writer for the specified association.
Change the select_tag to something like this:
<%= f.select(:currency_id, options_from_collection_for_select(Currency.all, :id, :name), :prompt => "Выберите валюту...") %>
精彩评论