带有accepts_nested_attributes_for和belongs_to的RecordNotFound

时间:2012-03-25 22:03:51

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

我得到了

  

ActiveRecord :: RecordNotFound:对于ID为

的订单,找不到ID = 3的客户端

尝试为现有客户提交订单表单时。这通过键入以下内容通过表单或控制台发生:

Order.new(:client_attributes => { :id => 3 })

payment_form.html.erb

<%= semantic_form_for @order, :url => checkout_purchase_url(:secure => true) do |f| %>

        <%= f.inputs "Personal Information" do %>

            <%= f.semantic_fields_for :client do |ff| %>
                <%= ff.input :first_name %>
                <%= ff.input :last_name %>              
                <!-- looks like semantic_fields_for auto-inserts a hidden field for client ID -->
            <% end %>

        <% end %>
<% end %>

Order.rb

class Order < ActiveRecord::Base
  belongs_to :client
  accepts_nested_attributes_for :client, :reject_if => :check_client

  def check_client(client_attr)
    if _client = Client.find(client_attr['id'])
      self.client = _client
      return true
    else
      return false
    end    
  end
end

reject_if想法来自here,但我记录了该方法,甚至没有被调用!它的名字是什么并不重要!

4 个答案:

答案 0 :(得分:7)

通过重载client_attributes =方法解决了问题,如here所述:

  def client_attributes=(client_attrs)    
    self.client = Client.find_or_initialize_by_id(client_attrs.delete(:id))
    self.client.attributes = client_attrs
  end

答案 1 :(得分:0)

如果您只想要一个具有现有客户端的新订单,而无需修改客户端,则需要分配该ID。

Order.new(client_id: 3)

这是另一种方法,可以在不重载client_attributes=方法和最简洁

的情况下执行此操作

新订单现在拥有ID为3的客户

如果您还想更新ant客户端的属性,则必须添加client_attributes,例如:

Order.new(client_id: 3, client_attributes: { id: 3, last_order_at: Time.current })

答案 2 :(得分:0)

使用 has_many belongs_to 关系为现有模型创建新Thing时出现同样的错误。

通过为表单添加现有模型的id(例如User)的隐藏字段来修复它。

= form.input :user_id, as: :hidden

然后创建了新的Thing而没有错误。

答案 3 :(得分:0)

如果您具有has_many关系,则此方法有效。在Rails 6.0.2上测试

  def clients_attributes =(attributes)
    # Get IDs for any clients that already exist.
    client_ids = attributes.values.map { |a| a[:id] }.compact

    # Now find them all and move them to this section.
    clients << Client.find(client_ids)

    # Update them with standard `accepts_nested_attributes_for` behaviour.
    super attributes
  end