2

我有两个模型:

class Wine
  belongs_to :region
end

class Region
  has_many :wines
end

我正在尝试将#where 方法与通过将参数哈希中的某些元素转换为查询哈希而构建的哈希一起使用,例如{ :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_idregion_id

问题如下:

是否有一种 rails-y 方法来使用方法中的Wine特定查询对象?根据我知道我能做的,我在下面列出了一些选项。regionsid#where

选项 1:我可以更改构建查询哈希的方式,以便每个字段都具有_id{ :region_id => '1234', :varietal_id => '1515' }但不是所有的关联来自Wineare belongs_to,因此在 wines 中没有条目 for _id,使得逻辑更复杂的连接和什么不是。

选项 2:构建一个 SQL where 子句,再次使用一些逻辑来确定是使用 id 还是连接另一个表……再次,逻辑会稍微复杂一些,深入研究 SQL 会让它感觉不那么 Rails-y。或者我在这方面可能是错的。

选项 3..n:我没有想到的事情......你的意见在这里 :)

4

2 回答 2

8

您可以在 Wine 模型中设置一个范围,使其更符合 Rails-y ...

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')
于 2012-11-29T15:12:54.373 回答
0

感谢所有回复的人。我得到的答案非常适合单一条件查询,但我需要一些可以处理不同数量条件的东西。

我最终实现了我的选项 #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

这样该方法将采用从这样的参数构建的哈希:

{ region => '1235', varietal => '1551', product_attribute => '9' }

并将 a_id放到每个键的末尾并将值更改为整数:

{ region_id => 1235, varietal_id => 1551, product_attribute_id => 9 }

我们将看到这是多么可持续,但这是我现在所做的。

于 2012-12-05T03:48:53.187 回答