开发者

Using data from associated model in form, Rails 3

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 => "Выберите валюту...") %>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜