【问题标题】:UnknownAttributeError using build for virtual attributeUnknownAttributeError 使用构建虚拟属性
【发布时间】:2012-10-31 23:03:55
【问题描述】:

我有一个包含虚拟属性:card_number 和 :card_verification 的嵌套表单。当我尝试在控制器更新操作中使用这些进行构建时,我得到 ActiveRecord::UnknownAttributeError。

模型有一个简单的 has_one 关系,其中约会 has_one 订单

#/models/appointment.rb
class Appointment < ActiveRecord::Base
  has_one :order
  accepts_nested_attributes_for :order

  attr_accessible (...)
end

#/models/order.rb
class Order < ActiveRecord::Base
  belongs_to :appointment

  attr_accessible :email, (...)
  attr_accessor :card_number, :card_verification
end

我正在生成这样的表单:

# /views/appointments/edit.html.erb
<%= form_for @appointment do |f| %>
  ...
  <%= f.fields_for @appointment.order do |builder| %>
    <%= builder.label :email %>
    <%= builder.text_field :email %> # works fine on its own
    ...
    <%= f.label :card_number %>
    <%= f.text_field :card_number %>

    <%= f.label :card_verification %>
    <%= f.text_field :card_verification %>
  <% end %>
  ...
<% end %>

并在控制器中构建:

# /controllers/appointments_controller.rb
def update
  @appointment = Appointment.find(params[:id])
  @order = @appointment.build_order(params[:appointment]['order']) # This line is failing

  if @appointment.update_attributes(params[:appointment].except('order'))
    # ... Success
  else
    # ... Failure
  end
end

有了这个,当我尝试提交更新时收到错误Can't mass-assign protected attributes: card_number, card_verification,带有参数:

{"utf8"=>"✓",
 "_method"=>"put",
 "authenticity_token"=>"KowchWLNmD9YtPhWhYfrNAOsDfhb7XHW5u4kdZ4MJ4=",
 "appointment"=>{"business_name"=>"Name",
 "contact_method"=>"Phone",
 "contact_id"=>"555-123-4567",
 "order"=>{"email"=>"user@example.com",
 "first_name"=>"John",
 "last_name"=>"Doe",
 "card_number"=>"4111111111111111", # normally [FILTERED]
 "card_verification"=>"123", # normally [FILTERED]
 "card_type"=>"visa",
 "card_expires_on(1i)"=>"2015",
 "card_expires_on(2i)"=>"11",
 "card_expires_on(3i)"=>"1",
 "address_line_1"=>"123 Main St",
 "address_line_2"=>"",
 "city"=>"Anywhere",
 "state"=>"CA",
 "country"=>"USA",
 "postal_code"=>"90210"}},
 "commit"=>"Submit",
 "id"=>"2"}

如果没有包含在表单中的 :card_number 和 :card_verification 值,一切正常。

有人知道这里出了什么问题吗?

编辑:

我可以解决这个问题:

@order = @appointment.build_order(params[:appointment]['order'].except('card_number', 'card_verification'))

但这似乎有点笨拙。有没有其他方法可以解决这个问题?

【问题讨论】:

    标签: ruby-on-rails-3 forms associations nested-attributes virtual-attribute


    【解决方案1】:

    错误消息“无法批量分配受保护的属性”是关于批量分配安全性的。您可以通过 without_protection 忽略批量分配检查。

    @order = @appointment.build_order(params[:appointment]['order'], without_protection: true)
    

    此链接说明什么是批量分配安全性。 Rails Internals: Mass Assignment Security

    如果您想指定大量可分配的属性,请使用 attr_accessible :one, :another 作为模型属性。 如果你需要其他非模型属性,使用 attr_accessor :card_number ,然后 attr_accessible :card_number 声明并暴露它。

    我看到您在 Order 模型中定义了 card_number 和 card_verfication,但是您使用 form_builder => f 在 html 中定义这两个字段。尝试改用 fields_for 构建器。

    【讨论】:

    • 感谢您的想法。如果可能的话,我宁愿不要养成绕过 Rails 安全措施的习惯;我希望有一种方法可以允许对我想要的属性(card_number 和 card_verification)进行批量分配,而不是对所有属性都忽略它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多