【问题标题】:How do I incorporate allow_destroy option into a custom nested attribute writer in Rails如何将 allow_destroy 选项合并到 Rails 中的自定义嵌套属性编写器中
【发布时间】:2016-09-13 16:42:28
【问题描述】:

在 Rails 中工作时,我正在合并 cocoon gem 以在我的食谱表单中动态生成成分字段。我可以使用accepts_nested_attributes_for 使其工作,但不能使用自定义嵌套属性编写器。例如,在合并 cocoon 之前,我的代码如下所示:

#recipe.rb
class Recipe
# name:string
  has many :ingredients
  # accepts_nested_attributes_for :ingredients

  # the method below should do exactly the same thing as accepts_nested_attributes_for

  def ingredients_attributes=(attributes)
    attributes.each do |i, ingredient_hash|
      self.ingredients.build(ingredient_hash)
    end
  end

end


#ingredient.rb
class Ingredient
  # name:string, price:integer
  belongs_to :recipe
end



#recipes_controller.rb (just the params part)
def recipe_params
  params.require(:recipe).permit(:name, ingredients_attributes: [:name, :price])
end 

为了使用茧宝石,我需要修改我的成分属性的强参数,并重构我的配方表单和配方模型,这是给我带来问题的最后一部分。我可以让它与这条线一起工作

accepts_nested_attributes_for :ingredients, reject_if: :all_blank, allow_destroy: true

但我想知道如何将选项合并到我的自定义属性编写器中。如果查看重构的控制器和表单代码会有所帮助,我也可以发布它。谢谢。

【问题讨论】:

  • 我能问一下你为什么要这样做吗?如果你放入控制器而不是模型中,那就更麻烦了..
  • 我不明白你的问题。我没有在控制器中放任何东西。在我的控制器中唯一改变的是强大的参数。其他所有内容都在recipe.rb 文件中
  • 好吧,如果你从 rails 重写嵌套属性处理,一个好的起点是实际的 rails-code:github.com/rails/rails/blob/…

标签: ruby-on-rails nested-attributes cocoon-gem


【解决方案1】:

我不确定您在定义自己的 ingredients_attributes= 方法时的用例,而不是使用更强大的 accepts_nested_attributes_for 为您定义 rails 方法。

但如果您必须为某些用例定义自己的ingredients_attributes=,您可以通过以下方式实现allow_destroy

class RecipesController < ApplicationController
  def recipe_params
    params.require(:recipe).permit(:name, ingredients_attributes: [:name, :price, :_destroy])
  end
end

class Recipe < ActiveRecord::Base
  def ingredients_attributes=(attributes)
    attributes.each do |i, ingredient_hash|
      if ingredient_hash[:_destroy].present?
        #include logic to destroy the associated record
        #both for new records and existing records
      else
        #you also need to make sure you address the
        #case for existing records and don't just build
        self.ingredients.build(ingredient_hash)
      end
    end
  end
end

正如上面ingredients_attributes=的cmets中提到的,如果你要实现自己的ingredients_attributes=而不是使用accepts_nested_attributes_for,你需要处理包括现有记录在内的所有用例(包括标记为删除的记录)与否),新记录(标记为删除或不删除的记录)等。

【讨论】:

  • 在这个特定示例中,除了简单地学习如何在自定义编写器中实现该选项之外,没有理由不使用 accepts_nested_attributes_for
  • 感谢您的帮助。仍然没有运气使该方法起作用,但我会继续尝试。我认为我需要更好地了解 cocoon 在后台正在做什么才能使其正常工作。此外,在这个特定示例中,除了简单地学习如何在自定义编写器中实现该选项之外,没有理由不使用 accepts_nested_attributes_for。我的一位 Rails 讲师认为,编写自己的嵌套属性编写器几乎总是更好,因为这样您就可以确切地知道它在做什么以及如何在需要时对其进行更多自定义,现在测试该理论!
  • 恕我直言,使用已被成千上万的开发人员使用、接触和改进的代码有很大的好处。想象一下已经发现的所有错误。您最初的实现非常简单,直到, owwwww ...删除现有项目。下一步:检查项目是新的(创建)还是现有的(更新)。下一步:忽略空白项。 Next:当特定字段未填写时忽略。 Next:处理一对一关系。更不用说:使用其他 gem 所依赖的已知标准。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-11
  • 1970-01-01
  • 2018-11-08
  • 2012-02-01
相关资源
最近更新 更多