Ruby on rails 范围或实例变量

Ruby on rails 范围或实例变量,ruby-on-rails,activerecord,ruby-on-rails-4,named-scope,Ruby On Rails,Activerecord,Ruby On Rails 4,Named Scope,据我所知,在Rails中使用作用域更有效,因为您直接查询模型,而不是通过控制器查询模型的实例变量(我就是这么看的?) 所以我的控制器中有这个查询 @animal_location = User.select(:town).map(&:town).uniq ["Cardiff", "Newport"] 然后这个范围在我的模型中 scope :uniq_towns, ->() { select("town").group("town") } #<ActiveRecord::R

据我所知,在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\u location=User.uniq\u towns
,在我看来,我会使用

<% @animal_location.each do |loc| %>
  <%= loc.town %>
<% end %>

我的第一个问题是,在这种情况下,我的作用域会更快吗?第二个问题是,我的作用域是否正确,因为我将用户id:nil作为哈希的一部分


谢谢

这取决于你的消息来源所说的“高效”是什么意思。作用域的设计是为了保持代码的干性,即“不要重复自己”,并为ActiveRecord(AR)查询实现“提取方法”重构模式。它们易于维护

为什么要用它?如果在多个地方使用相同的查询,请考虑在需要更改的情况下的情况。您必须查找并替换所有引用。这种方式容易出错,并导致版本控制中更难跟踪的差异

将此查询提取到方法中似乎是一个合乎逻辑的解决方案类方法?,但是简单地说,作用域就是它的作用域。通过使用作用域,您将:

  • 获取一个位置来构造具有特定含义的查询(并在整个应用程序中使用)
  • 请确保作用域的结果是可链接的,因为结果是有效的AR关系(并且可以在其上应用作用域)
  • 提供查询的含义—一个良好的可读名称,以保持控制器代码的可读性(在视图中使用作用域是有效的,但与Rails遵循的MVC相反)
你有:

@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

还有其他方法可以解决这种情况,比如过滤前的
,但这超出了问题的范围。

我不认为范围查询比常规查询更有效。他们只需要较少的打字就可以在需要的时候打电话。谢谢你的深入回答,当然为我清理了范围。
@animal_location = User.uniq_towns