范围或实例变量

时间:2014-10-28 15:15:08

标签: 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::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作为哈希的一部分

由于

1 个答案:

答案 0 :(得分:2)

这取决于“有效”的来源意味着什么。范围旨在保持代码DRY,在“不要重复自己”的意义上,并为ActiveRecord(AR)查询实现“提取方法”重构模式。它们易于维护。

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

将此查询提取到方法中似乎是一种逻辑解决方案。 类方法? No, maybe you shouldn't,但只是将范围放在。通过使用范围,您将:

  • 获取一个地方来构建具有特定含义的查询(并在整个应用程序中使用它)
  • 请确保范围的结果是可链接的,因为结果是有效的AR关系(并且您可以在其上应用范围)
  • 提供您的查询意味着一个良好的可读名称,以保持控制器代码可读(使用视图中的范围是有效的,但对Rails遵循的MVC)

你有:

@animal_location = User.select(:town).map(&:town).uniq

首先,我不明白为什么需要mapgroup,这也可以正常使用SQL DISTINCT

@animal_location = User.select(:town).uniq

这看起来足够可读。但是,让我们在这里展示范围。在你的模型中发出这个:

scope :uniq_towns, ->() {
 select("town").uniq
}

...所以你可以在你的控制器中写下这个:

@animal_location = User.uniq_towns

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