我一直想知道如何查询和获得不适合模型的结果。类似于使用LINQ和投影到匿名对象。
这是一个简单的模式:
# Product.rb
class Product < ActiveRecord::Base
has_many :product_views
# attributes: id, name, description, created_at, updated_at
end
# ProductView.rb
class ProductView < ActiveRecord::Base
belongs_to :product
# attributes: id, product_id, request_ip, created_at, updated_at
end
基本上,我需要获得一个product列表(最好只有id和名称)以及它所拥有的视图计数。
这是我想要得到的SQL:
select
p.id,
p.name,
count(pv.product_id) as views
from
product_views pv
inner join
products p on pv.product_id = p.id
group by
pv.product_id
order by
count(product_id) desc
我尝试了以下和类似的,但我得到ProductView对象,我想得到只是一个数组或任何东西。
ProductView.includes(:product)
.group('product_id')
.select("products.id, products.name, count(product_id)")
这类事情使用普通SQL或LINQ是微不足道的,但我发现自己在Rails中陷入了这种查询。也许我没有按照著名的"rails方式"思考,也许我错过了一些明显的东西。
如何在Rails 3中实现这种查询,特别是这个呢?欢迎提出任何改进我工作方式的建议。
谢谢
你可以用Arel来做你想做的:
products = Product.arel_table
product_views = ProductView.arel_table
# expanded for readability:
sql = products.join(product_views)
.on(product_views[:product_id].eq(product[:id]))
.group(product_views[:product_id])
.order('views DESC')
.project(products[:id],
products[:name],
product_views[:id].count.as('views'))
products_with_views = Product.connection.select_all(sql.to_sql) # or select_rows to just get the values
是的,它很长,但是Arel是处理创建复杂查询的一种非常聪明的方法,无论数据库类型如何,这些查询都可以重用。
在Product类的类方法中:
Product.includes(:product_views).all.map { |p| [p.id, p.name, p.product_views.size] }
我不知道是否有办法使用你的模型。我可能会使用:
Product.connection.select_rows(sql)
它会给你一个数组的数组。如果你想要一个哈希数组,你可以使用select_all
。
试试这个:
@product = Product.find(#product_id)
@product_views = @product.product_views.count
(来源- http://ar.rubyonrails.org/classes/ActiveRecord/Calculations/ClassMethods.html#M000292)
希望这对你有帮助!