2014-10-28 64 views
0

从我读过的使用范围在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.each do |loc| %> 
    <%= loc %> 
<% end %> 

,或者如果我使用的范围,并与@animal_location = User.uniq_towns去,在我看来,我会用

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

我的第一个问题是将我的范围是在这种情况更快,其次是我的范围正确的,因为我得到用户名:无作为哈希的一部分

感谢

+1

我不认为范围化查询比普通查询更有效率。需要时他们只需要较少的打字就可以打电话。 – zwippie 2014-10-28 15:33:18

回答

2

这取决于你的来源由“高效”的意思。范围旨在保持DRY代码,意思是“不要重复自己”,并为ActiveRecord(AR)查询实现“提取方法”重构模式。他们很容易维护。

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

将此查询提取到方法中似乎是一种合理的解决方案。 类方法?No, maybe you shouldn't,但简单地说,范围只是。通过使用范围,你会:

  • 找一个地方来构造具有一定意义的查询(并用它在整个应用程序)
  • 相当肯定一个范围的结果是可链接的,因为结果是一个有效的AR关系(你可以在它上面的应用范围)
  • 要提供查询的意思是一个很好的可读名称保持控制代码的可读性(使用范围的意见是正确的,但是对MVC Rails所遵循)

您有:

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

首先,我不明白为什么需要mapgroup,这个工作也没关系,并使用SQL DISTINCT

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

这看起来shourt足以成为可读。但让我们在这里演示范围。在你的型号问题上:

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

...所以你可以在你的CONTROLER这样写:

@animal_location = User.uniq_towns 

也有其他的方法来解决这种情况,如before_filter,但它超越了问题的范围。

+0

谢谢你的深入解答,肯定会为我清除范围。 – Richlewis 2014-10-28 20:05:42