【发布时间】:2016-10-06 01:14:19
【问题描述】:
我正在开发一个产品模型,它与自身具有 has_one 关联,包括原材料记录。模型通过 REST API 返回数据。我正在使用 Active Model Serializer 而不是 JBuilder。
产品型号有一个“代码”字段,其中包含字符串中的产品代码:
'001-000-01-01' (This is a product.)
'001-000-00-01' (This is a material.)
两个代码之间的唯一区别是右起第三个数字。 “1”是产品。 “0”是物质。我想在检索产品记录时包含“raw_material”记录。因此,我尝试设置 has_one 与具有“where”子句的范围的关联(稍后我可以编写查询以从产品代码中获取材料)。现在我只需在 lambda 中传递“产品”对象并在 where 中使用它。
首先我在 def raw_material 中写,这行得通。但是,我不知道如何将对象传递给 def 并在 where 子句中使用它。因此,我在 has_one 中提出了范围模式,但是即使它生成与 def 模式完全相同的 SELECT,它也会返回错误。我得到的是“NoMethodError”。
class Product < ActiveRecord::Base
has_many :supplies, ->{order('row_order ASC') }, primary_key: :code, foreign_key: :product_code
#This Works!
#has_one :raw_material, class_name: 'Product', primary_key: :code, foreign_key: :code
#This Works!
#has_one :raw_material
#Does not work. Why?
has_one :raw_material, ->(product) { where('code = ?', product.code).take }, class_name: 'Product'
accepts_nested_attributes_for :supplies, allow_destroy: true
#def raw_material
# Product.where('code = ?', '001-000-01-01').take
#end
end
“def”模式有效:
Started GET "/products/1.json" for ::1 at 2016-10-05 21:48:15 +0900
Processing by ProductsController#show as JSON
Parameters: {"id"=>"1"}
Product Load (0.3ms) SELECT "products".* FROM "products" WHERE "products"."id" = ? LIMIT 1 [["id", 1]]
[active_model_serializers] Supply Load (0.1ms) SELECT "supplies".* FROM "supplies" WHERE "supplies"."product_code" = ? ORDER BY row_order ASC [["product_code", "031-052-00-01"]]
[active_model_serializers] Product Load (0.1ms) SELECT "products".* FROM "products" WHERE (code = '001-000-01-01') LIMIT 1
[active_model_serializers] Rendered ProductSerializer with ActiveModelSerializers::Adapter::Attributes (6.71ms)
Completed 200 OK in 24ms (Views: 9.2ms | ActiveRecord: 1.4ms)
但是,范围模式不起作用:
Started GET "/products/1.json" for ::1 at 2016-10-06 08:19:13 +0900
Processing by ProductsController#show as JSON
Parameters: {"id"=>"1"}
Product Load (0.1ms) SELECT "products".* FROM "products" WHERE "products"."id" = ? LIMIT 1 [["id", 1]]
[active_model_serializers] Supply Load (0.1ms) SELECT "supplies".* FROM "supplies" WHERE "supplies"."product_code" = ? ORDER BY row_order ASC [["product_code", "031-052-00-01"]]
[active_model_serializers] Product Load (0.1ms) SELECT "products".* FROM "products" WHERE (code = '031-052-00-01') LIMIT 1
[active_model_serializers] Rendered ProductSerializer with ActiveModelSerializers::Adapter::Attributes (10.6ms)
Completed 500 Internal Server Error in 27ms (ActiveRecord: 1.2ms)
NoMethodError (undefined method `except' for #<Product:0x007fe97b090418>):
app/controllers/products_controller.rb:17:in `block (2 levels) in show'
app/controllers/products_controller.rb:14:in `show'
Rendered vendor/bundle/ruby/2.2.0/gems/actionpack-4.2.5/lib/action_dispatch/middleware/templates/rescues/_source.erb (8.8ms)
产品控制器简单地定义显示如下:
# GET /products/1
# GET /products/1.json
def show
respond_to do |format|
format.html
format.json do
render json: @product, include: ['raw_material']
end
end
end
product_serializer.rb 是:
class ProductSerializer < ActiveModel::Serializer
attributes(*Product.attribute_names.map(&:to_sym))
has_one :raw_material
end
非常感谢任何帮助。
谢谢
更新:
我自己解决了这个问题。请在下面查看我的答案。感谢所有编写解决方案的人。
【问题讨论】:
标签: ruby-on-rails ruby-on-rails-4 scope associations has-one