I have many multi-line ActiveRelation query methods in our app, and I'm unsure about the most idiomatic way to write these methods. Take a look at this example:
我的应用程序中有许多多行ActiveRelation查询方法,我不确定编写这些方法的最惯用方法。看看这个例子:
def postal_code_ids_within(miles)
nearby_postal_codes = PostalCode.where("latitude > :min_lat and latitude < :max_lat",
min_lat: (latitude - (miles.to_f / MILES_PER_DEGREE_LATITUDE.to_f / 2.to_f)),
max_lat: (latitude + (miles.to_f / MILES_PER_DEGREE_LATITUDE.to_f / 2.to_f)))
nearby_postal_codes = nearby_postal_codes.where("longitude > :min_lon and longitude < :max_lon",
min_lon: (longitude - (miles.to_f / MILES_PER_DEGREE_LONGITUDE.to_f / 2.to_f)),
max_lon: (longitude + (miles.to_f / MILES_PER_DEGREE_LONGITUDE.to_f / 2.to_f)))
nearby_postal_codes.pluck(:id)
end
It feels a bit off to me. A block from which an ActiveRelation object is returned seems idiomatic, but I haven't seen that approach around.
对我来说感觉有点不对劲。从中返回ActiveRelation对象的块似乎是惯用的,但我还没有看到这种方法。
What is standard?
什么是标准?
2 个解决方案
#1
11
Building on Brian's suggestion, this is much more legible and works well.
在Brian的建议的基础上,这更加清晰,效果也很好。
scope :near, lambda { |postal_code, miles|
degree_offset = miles / MILES_PER_DEGREE / 2
where("latitude > :min_lat and latitude < :max_lat and longitude > :min_lon and longitude < :max_lon",
min_lat: postal_code.latitude - degree_offset,
max_lat: postal_code.latitude + degree_offset,
min_lon: postal_code.longitude - degree_offset,
max_lon: postal_code.longitude + degree_offset)
}
def postal_code_ids_within(miles)
self.class.near(self, miles).pluck(:id)
end
#2
0
Breaking up into scopes is a good suggestion. In contrast to another answer I prefer defining complicated scopes as a function instead of messing with lambdas, blocks and precedence rules:
分解范围是一个很好的建议。与另一个答案相反,我更喜欢将复杂的范围定义为函数,而不是弄乱lambdas,块和优先级规则:
def self.near(postal_code, miles)
degree_offset = miles / MILES_PER_DEGREE / 2
where("latitude > :min_lat and latitude < :max_lat and longitude > :min_lon and longitude < :max_lon",
min_lat: postal_code.latitude - degree_offset,
max_lat: postal_code.latitude + degree_offset,
min_lon: postal_code.longitude - degree_offset,
max_lon: postal_code.longitude + degree_offset)
end
def postal_code_ids_within(miles)
self.class.near(self, miles).pluck(:id)
end
#1
11
Building on Brian's suggestion, this is much more legible and works well.
在Brian的建议的基础上,这更加清晰,效果也很好。
scope :near, lambda { |postal_code, miles|
degree_offset = miles / MILES_PER_DEGREE / 2
where("latitude > :min_lat and latitude < :max_lat and longitude > :min_lon and longitude < :max_lon",
min_lat: postal_code.latitude - degree_offset,
max_lat: postal_code.latitude + degree_offset,
min_lon: postal_code.longitude - degree_offset,
max_lon: postal_code.longitude + degree_offset)
}
def postal_code_ids_within(miles)
self.class.near(self, miles).pluck(:id)
end
#2
0
Breaking up into scopes is a good suggestion. In contrast to another answer I prefer defining complicated scopes as a function instead of messing with lambdas, blocks and precedence rules:
分解范围是一个很好的建议。与另一个答案相反,我更喜欢将复杂的范围定义为函数,而不是弄乱lambdas,块和优先级规则:
def self.near(postal_code, miles)
degree_offset = miles / MILES_PER_DEGREE / 2
where("latitude > :min_lat and latitude < :max_lat and longitude > :min_lon and longitude < :max_lon",
min_lat: postal_code.latitude - degree_offset,
max_lat: postal_code.latitude + degree_offset,
min_lon: postal_code.longitude - degree_offset,
max_lon: postal_code.longitude + degree_offset)
end
def postal_code_ids_within(miles)
self.class.near(self, miles).pluck(:id)
end