accepts_nested_attributes_for链接到现有记录,而不是创建新记录

Man*_*rer 15 ruby-on-rails nested-forms nested-attributes

我有以下型号

class Order < AR::Base
  has_many :products

  accepts_nested_attributes_for :products
end

class Product < AR::Base
  belongs_to :order
  has_and_belongs_to_many :stores

  accepts_nested_attributes_for :stores
end

class Store < AR::Base
  has_and_belongs_to_many :products
end
Run Code Online (Sandbox Code Playgroud)

现在我有一个订单视图,我想更新产品的商店.问题是我只想将产品连接到我的数据库中的现有商店,而不是创建新商店.

我在订单视图中的表单看起来像这样(使用Formtastic):

= semantic_form_for @order do |f|
  = f.inputs :for => :live_products do |live_products_form|
    = live_products_form.inputs :for => :stores do |stores_form|
      = stores_form.input :name, :as => :select, :collection => Store.all.map(&:name)
Run Code Online (Sandbox Code Playgroud)

虽然它嵌套它工作正常.问题是,当我选择商店并尝试更新订单(以及产品和商店)时,Rails会尝试创建一个具有该名称的新商店.我希望它只使用现有商店并将产品连接到该商店.

任何帮助赞赏!

编辑1:

最后,我以一种非常粗暴的方式解决了这个问题:

# ProductsController

def update
  [...]

  # Filter out stores
  stores_attributes = params[:product].delete(:stores_attributes)

  @product.attributes = params[:product]

  if stores_attributes.present?
    # Set stores
    @product.stores = stores_attributes.map do |store_attributes|
      # This will raise RecordNotFound exception if a store with that name doesn't exist
      Store.find_by_name!(store_attributes[:name])
    end
  end

  @order.save

  [...]
end
Run Code Online (Sandbox Code Playgroud)

编辑2:

Pablo的解决方案更加优雅,应该优于我的解决方案.

Pab*_*blo 23

尝试实现:reject_if检查Store是否已存在然后使用它:

class Product < AR::Base
  belongs_to :order
  has_and_belongs_to_many :stores

  accepts_nested_attributes_for :stores, :reject_if => :check_store

  protected

    def check_store(store_attr)
      if _store = Store.find(store_attr['id'])
        self.store = _store
        return true
      end
      return false
    end
end
Run Code Online (Sandbox Code Playgroud)

我有这个代码在当前项目中正常工作.

如果您找到了更好的解决方案,请告诉我.

  • 这对我来说没有意义.`check_store`中的`self`是Product ...而且Product没有`store`关系(HABTM:stores).那么这段代码实际上做了什么?此外,它似乎不会更新找到的商店. (10认同)