从我在Rails中使用范围读取的内容更有效率,因为您直接查询模型而不是通过控制器进入模型的实例变量(这就是我如何看待它?)
所以我在我的控制器中有这个查询
@animal_location = User.select(:town).map(&:town).uniq
["Cardiff", "Newport"]
然后我的模型中的这个范围
scope :uniq_towns, ->() {
select("town").group("town")
}
#<ActiveRecord::Relation [#<User id: nil, town: "Cardiff">, #<User id: nil, town: "Newport">]>
在我看来使用@animal_location = User.select(:town).map(&:town).uniq
访问城镇价值时,我可以访问
<% @animal_location.each do |loc| %>
<%= loc %>
<% end %>
或者如果我使用了范围并与@animal_location = User.uniq_towns
一起使用,在我看来我会使用
<% @animal_location.each do |loc| %>
<%= loc.town %>
<% end %>
我的第一个问题是在这个实例中我的范围会更快,其次是我的范围正确,因为我得到用户ID:nil作为哈希的一部分
由于
答案 0 :(得分:2)
这取决于“有效”的来源意味着什么。范围旨在保持代码DRY,在“不要重复自己”的意义上,并为ActiveRecord(AR)查询实现“提取方法”重构模式。它们易于维护。
为什么要用它?如果您在多个地方使用相同的查询,请考虑需要在任何地方更改它的情况。你必须找到并替换所有出现的事件。这种方式容易出错,导致更难以跟踪的版本控制差异。
将此查询提取到方法中似乎是一种逻辑解决方案。 类方法? No, maybe you shouldn't,但只是将范围放在。通过使用范围,您将:
你有:
@animal_location = User.select(:town).map(&:town).uniq
首先,我不明白为什么需要map
和group
,这也可以正常使用SQL DISTINCT
:
@animal_location = User.select(:town).uniq
这看起来足够可读。但是,让我们在这里展示范围。在你的模型中发出这个:
scope :uniq_towns, ->() {
select("town").uniq
}
...所以你可以在你的控制器中写下这个:
@animal_location = User.uniq_towns
还有其他方法可以解决这种情况,例如before_filter
,但这超出了问题的范围。