Rails-y查询具有belongs_to关联的模型的方法
我有两个型号:
class Wine belongs_to :region end class Region has_many :wines end
我试图使用#where方法,通过将params哈希中的某些元素转换为查询哈希来构建哈希,例如{ :region => '2452' }
def index ... @wines = Wine.where(hash) ... end
但是我得到的只是在执行查询时列不存在错误:
ActiveRecord::StatementInvalid: PGError: ERROR: column wines.region does not exist LINE 1: SELECT "wines".* FROM "wines" WHERE "wines"."region" =...
当然,表wines
有region_id
所以如果我查询region_id
而不是我不会得到错误。
问题如下:
是否有一种rails-y方式使用#where
方法中的id
查询Wine
对象的特定regions
? 我根据我所知道的可以做的,列出了以下一些选项。
选项1:我可以改变构建查询哈希的方式,以便每个字段都有_id
(如{ :region_id => '1234', :varietal_id => '1515' }
但不是Wine
所有关联都是belongs_to
和因此没有为_id
葡萄酒的条目,使得逻辑更加复杂,加入什么不是。
选项2:构建一个SQL where子句,再次使用一些逻辑来确定是否使用id或连接另一个表…再次逻辑会稍微复杂一些,并且深入研究SQL会让它感觉更少rails-y。 或者我在那方面可能是错的。
选项3..n:我没想过的事情……你的输入就在这里:)
您可以在Wine模型中设置一个范围,使其更具轨道性…
class Wine < ActiveRecord::Base belongs_to :region attr_accessible :name, :region_id scope :from_region, lambda { |region| joins(:region).where(:region_id => region.id) } end
那么你可以这样做:
region = Region.find_by_name('France') wine = Wine.from_region(region)
编辑1:
或者如果你想真正想要你可以为多个地区做一个范围:
scope :from_regions, lambda { |regions| joins(:region).where("region_id in (?)", regions.select(:id)) } regions = Region.where("name in (?)", ['France','Spain']) # or however you want to select them wines = Wine.from_regions(regions)
编辑2:
如果需要,您还可以链接范围和where子句:
regions = Region.where("name in (?)", ['France','Spain']) wines = Wine.from_regions(regions).where(:varietal_id => '1515')
感谢所有回复的人。 我得到的答案对于单个条件查询非常有用,但我需要能够处理不同条件的东西。
我最终实现了我的选项#1,它通过迭代并将_id
连接到值来构建条件哈希:
def query_conditions_hash(conditions) conditions.inject({}) do |hash, (k,v)| k = (k.to_s + "_id").to_sym hash[k] = v.to_i hash end end
因此该方法将采用由params构建的散列,如下所示:
{ region => '1235', varietal => '1551', product_attribute => '9' }
并将_id
拖放到每个键的末尾并将值更改为整数:
{ region_id => 1235, varietal_id => 1551, product_attribute_id => 9 }
我们会看到这是多么可持续,但这就是我现在所用的。