Dar*_*isa 1 ruby ruby-on-rails
我有一个简单的控制器方法:
products = Product.where(name: name, color: color, size: size, available: true)
Run Code Online (Sandbox Code Playgroud)
它返回一个 Product::ActiveRecord_Relation 对象。我想取出第一个物体并拉出一个字段,例如products.first.product_code
但是这个和我尝试过的其他一些方法重新查询数据库。我试过了:
products[0].product_code
products.take.product_code
Run Code Online (Sandbox Code Playgroud)
所有这些都重新查询数据库,两次命中数据库。一次为哪里和一个上场。有没有一个不会影响数据库的简单解决方案?
有效的是将 ActiveRecord 转换为数组 ( products.to_a.[0].product_code) 但这似乎效率低下。
以下是显示两个单独命中的服务器日志:
这是我的控制器方法供参考:
def update_selection
size = params[:size]
color = params[:color]
name = params[:product_name]
products = Product.where(name: name, color: color, size: size, available: true)
product_code = products.empty? ? 'sold out' : products.first.product_code
respond_to do |format|
format.json { render json: { count: products.length, code: product_code}}
end
end
Run Code Online (Sandbox Code Playgroud)
我最好的猜测是,在分配给products. ActiveRecord 关系是惰性的,这意味着它们直到需要该查询的结果时才查询数据库。
就您的问题而言 - 这一行:
products = Product.where(name: name, color: color, size: size, available: true)
不需要从数据库中实际提取任何数据,因此不执行查询。
products.first.product_code,另一方面,将导致查询触发。
编辑:
我相信问题来自使用.exists?(这是一个总是触发查询的 ActiveRecord 方法)。如果您要检查查询是否返回任何结果,请尝试使用.present?或.any?代替.exists?。
编辑2:
好的,感谢发布代码。你有几个选择。
.to_a:products = Product.where(name: name, color: color, size: size, available: true).to_a
这会将所有内容加载products到内存中,如果您希望有少量产品,这很有意义。这只会触发一个查询。
product_code = products.first.try(:product_code) || 'sold out'
这更节省内存(因为您最多将一个加载product到内存中),但使用两个查询 ( products.count is the other one)。
| 归档时间: |
|
| 查看次数: |
186 次 |
| 最近记录: |