使用来自表单中相关模型的数据,Rails 3

时间:2011-09-19 13:17:20

标签: ruby-on-rails-3 forms nested

有很多类似的主题,但它对我没有帮助。 有一个帐户模型

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个项目 - 美元,欧元,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]",因为默认情况下它们都是“货币”。 Rails 3.1

2 个答案:

答案 0 :(得分:3)

在你的情况下,当你质疑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与select helper结合使用将为您解决这个问题。

总而言之,当您需要更改关联模型中的某些值或创建/销毁它的实例时,accepts_nested_attributes_for的使用主要是有用的。在您的情况下,您只链接到现有货币模型而不对其进行任何更改。

答案 1 :(得分:1)

您不需要:attr_accessible或:accepts_nested_attributes_for,除非它是嵌套资源。 attr_accessible is used for mass assignmentaccepts_nested_attributes_for定义了指定关联的属性编写器。

将select_tag更改为以下内容:

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