【问题标题】:Easiest way to edit associations in Rails在 Rails 中编辑关联的最简单方法
【发布时间】:2012-01-12 11:27:03
【问题描述】:

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

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

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,即将库存记录链接到不同的产品记录。

目前,我已经在 stock 模型中定义了各种方法,例如 prod_code= 来实现这项工作。但正如我所提到的,实际上有多个模型可以参考我的产品表。有什么方法可以在 Product 模型中定义一些东西吗?

例如类似于 referenced_by 方法,它会告诉所有链接模型通过在 products 表中查找来处理 prod_code 参数?

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

【问题讨论】:

  • 我不确定您如何处理嵌套的产品代码;它以文本字段的形式显示在表单中 - 这是否意味着它是手动输入的?无论如何,我认为accepts_nested_attributes 是您正在寻找的,尽管我认为您必须建立从Stock 到Product api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/… 的has_one 关系
  • 在我看来嵌套属性是用于例如从库存屏幕编辑产品代码数据库。这不是我想做的——我只是想让用户在库存编辑屏幕上输入新的产品代码。
  • 我的想法是我可以进入脚手架视图,例如在 _form.html.erb 中,将 :product_id 更改为 :prod_code,一切正常。编辑屏幕会显示当前的产品代码,用户可以输入一个新的。
  • 回答第二条评论 - 这就是我的想象,但我不太明白。库存属于产品,您希望能够分配或更新哪个产品,在我看来,您可能最好将选择列表作为表单的一部分,其中向用户显示产品名称但表单提交Stock 的 product_id 字段。我想令人困惑的是 prod_code 是什么?
  • 对不起,prod_code 只是识别产品的唯一代码(它在所有库存单位的条形码中,因此用户只需扫描即可)。在某些情况下,下拉菜单确实很有意义——这正是我处理质量代码等的方式,但是有 200,000 种产品。我不想让客户端从友好名称映射到 id,而是在服务器上进行。

标签: ruby-on-rails ruby activemodel


【解决方案1】:

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

首先你可以告诉你的模型接受嵌套属性(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]”,同时,由于 accept_nested_attributes_for,您的 stock 模型准备将 product_attributes 传递给关联的产品。

更新(见 cmets):

您想象的 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

【讨论】:

  • 感谢您的回复,但这并不是我想要的。这样做是允许更改产品记录上的 prod_code。我想要做的是使用 prod_code 更改股票记录链接到的 product_id。我会修改这个问题,因为我认为它可能解释得不太好!
  • 但是您不想为 product_id 使用选择字段,而是有一个文本字段供用户输入 prod_code/
  • 这看起来很不错,它是我目前得到的更简洁的版本 - before_validation 看起来是一个非常方便的技巧。我仍然希望找到一种方法将此代码放入 Product 模型中
  • 您将无法将其放在产品模型上。库存表单被发布到库存控制器,库存模型需要将自己与产品相关联。如果你有代码的工作版本(我绝对不保证我的代码没有任何进一步的问题),你可以把它放在一个模块中,所以你只需要在 Stock 和其他模块中包含一行。
【解决方案2】:

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

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

或者你可以在产品上设置:

class Product
  has_many :stocks, :foreign_key => "prod_code"
  has_many :images, :foreign_key => "prod_code"
  has_many :sizes,  :foreign_key => "prod_code"
end

【讨论】:

    猜你喜欢
    • 2016-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-17
    • 2017-12-31
    • 1970-01-01
    • 2013-06-21
    • 1970-01-01
    相关资源
    最近更新 更多