在Rails中编辑关联的最简单方法

时间:2012-01-12 11:27:04

标签: ruby-on-rails ruby activemodel

我的想象一定是常见的情况,但可能无法找到解决问题的方法来获得解决方案......

我的应用程序中有几个链接模型:

class Product < ActiveRecord::Base
  validates_uniqueness_of :prod_code
end

class Stock < ActiveRecord::Base
  belongs_to :product
end

事实上,还有许多其他型号也属于Product。默认情况下,在库存记录中,我只看到product_id字段,这是一个自动递增的数字,对用户没什么帮助。产品具有独特的prod_code条形码等,是产品数据库的自然关键。

我想要的是股票和其他链接模型的创建/编辑屏幕,以显示prod_code的文本字段,并能够以合理的方式响应stock[prod_code]形式的参数(例如,查找prod_code,并根据结果设置prod_id),并自动(例如Stock.new(params[:stock])应该有效。

为了澄清,设置stock [prod_code]不会改变产品数据库中的任何内容;它会改变相关库存记录的product_id,即将库存记录链接到不同的产品记录。

目前,我已经在库存模型中定义了各种方法,例如prod_code=。但正如我所提到的,实际上有多个模型会引用我的产品表。有什么方法可以在Product模型中定义一些东西吗?

e.g。类似于referenced_by方法的东西会通过在products表中查找来告诉所有链接模型处理prod_code参数?

class Product < ActiveRecord::Base
  validates_uniqueness_of :prod_code
  referenced_by :prod_code
end

2 个答案:

答案 0 :(得分:2)

您可能想要使用的是嵌套表单。

首先,您可以告诉您的模型接受嵌套属性(api for nested attributes),例如

accepts_nested_attributes_for :product

在你的股票模型中。

然后在表单中,您可以使用fields_for(api for fields_for)将产品字段嵌套到库存表单中。 想象一下:

= form_for(@stock) do |form|
  = form.text_field :some_stock_attribute
  = form.fields_for(@stock.product) do |product_form|
     = product_form.text_field :prod_code

这基本上将您的prod_code表单字段的名称嵌套到“stock [product_attributes] [prod_code]”,而由于accepted_nested_attributes_for,您的库存模型准备将product_attributes传递给相关产品。

更新(见评论):

您想象的referenced_by方法不存在。此外,您还需要处理更多,然后只需更改相关产品。如果prod_code不存在,我仍然想要显示错误,我假设。

粗略地说,您可以为库存添加虚拟属性,这样您的库存表单就可以有一个text_field:prod_code(将attr:prod_code添加到库存模型中)。

其次,在验证之前,您可能需要一个方法,为prod_code查找产品,并更改关联,或在:prod_code上添加错误。

这可能看起来像这样:

class Stock
  attr :prod_code

  before_validation :associate_product_from_prod_code

  def associate_product_from_prod_code
    unless self.product = Product.where(:prod_code => prod_code)
      errors[:prod_code] << "Product Code is not valid"
    end
  end

end

答案 1 :(得分:0)

您可以使用prod_code而不是product_id作为foreign_key:

class Stock
  belongs_to :product, :foreign_key => "prod_code"
end

或者您可以在Product:

上进行设置
class Product
  has_many :stocks, :foreign_key => "prod_code"
  has_many :images, :foreign_key => "prod_code"
  has_many :sizes,  :foreign_key => "prod_code"
end