我是Active Record的新手,尽管阅读了很多文档,但我还是找不到办法。我知道这不是处理事情的正确方法,理想情况下,下面的映射逻辑应该存在于另一个表中,但是现在这似乎是处理它的最简单方法。
我在数据库中有以下信息,我想以特殊方式检索它。我有:
| locations | value |
|----------------|-------|
| brazil | 20 |
| europe | 30 |
| restoftheworld | 35 |
我想要一个自定义的getter方法或范围,用于检查和查找相应的条目。在伪代码中有类似的东西:
def findbylocation(location)
if location exists
return row
elsif location.in_eu?
return row of 'europe'
else
return row of 'restoftheworld'
end
写这个的最好方法是什么?它是范围还是方法?
注意:我使用https://github.com/hexorx/countries进行欧盟检查,因此没有问题。
答案 0 :(得分:1)
这取决于。如果你想在内存中进行区域验证,当你在问题的伪代码中写入时,你必须使用class method
(或instance method
,具体取决于你将如何使用它)。例如,如果对where子句进行区域验证,则应使用scope
方法。
这是因为scope
会返回ActiveRecord::Relation
,因此您可以链接更多“范围”方法。如果更改范围的返回类型对象,则会失去链的能力,这是毫无意义的。
我对如何使用findbylocation
方法以及它的行为方式感到有些困惑。无论如何,我强烈建议您阅读this article,这很好地解释了rails中scopes
和methods
之间的区别。
答案 1 :(得分:-1)
首先,范围是方法。
它们基本上只是Rails方法的简写。
我是activerecord的新手
好的,所以我认为您遇到了问题,因为您的表结构不正确。
ActiveRecord为我们提供associations的力量。这是一个抽象层,可用于在表中创建关系,允许您执行查找而无需调用100个查询。
#app/models/location.rb
class Location < ActiveRecord::Base
has_many :cities #-> you can replace "city" with anything here
scope :findbylocation, ->(continent) { find_by(name: continent) }
end
#app/models/city.rb
class City < ActiveRecord::Base
#columns id | location_id | name | etc | created_at | updated_at
belongs_to :location
end
这使您能够调用以下内容:
@location = Location.find_by name: "europe"
或
@location = Location.findbylocation "europe"
这将填充@location
对象,然后您可以调用以下内容:
@location.cities.each do |city|
city.name #-> Bangalore
您必须了解关系数据库的强大功能,尤其是当您构建多个对象时:
我相信您遇到的问题是您没有正确地模块化您的数据。 IE,你把它全部放在一个&#34;位置&#34;数据表,当真的,你应该将 locations 作为一个表,并将 cities (或其他)放在另一个表中。
这样,你就不会试图直接看一切;您正在查找所需的特定位置记录,并通过ActiveRecord将相关数据提取出来。
答案 2 :(得分:-1)
好的,我解决了。我不确定这是不是最好的方法。如果您知道更好的解决方案,请随意改进或提出其他建议。我创建了以下方法:
def self.by_location(location)
if LocationValue.exists?(:location => location)
where(location: location)
elsif location.in_eu?
where(location: 'europe')
else
where(location: 'restoftheworld')
end
end