我正在实施我的第一个HABTM关系,并且遇到了我的查询问题。
我希望验证我的方法,看看我是否在AREL(或Rails的其他部分)代码中发现了一个错误。
我有以下型号
class Item < ActiveRecord::Base
belongs_to :user
belongs_to :category
has_and_belongs_to_many :regions
end
class Region < ActiveRecord::Base
has_ancestry
has_and_belongs_to_many :items
end
我有关联的items_regions表:
class CreateItemsRegionsTable < ActiveRecord::Migration
def self.up
create_table :items_regions, :id => false do |t|
t.references :item, :null => false
t.references :region, :null => false
end
add_index(:items_regions, [:item_id, :region_id], :unique => true)
end
def self.down
drop_table :items_regions
end
end
我的目标是创建一个范围/查询如下:
查找区域(及其子区域)中的所有项目
ancestory gem提供了一种方法,可以将Region的后代类别作为数组进行检索。在这种情况下,
ruby-1.9.2-p180 :167 > a = Region.find(4)
=> #<Region id: 4, name: "All", created_at: "2011-04-12 01:14:00", updated_at: "2011-04-12 01:14:00", ancestry: nil, cached_slug: "all">
ruby-1.9.2-p180 :168 > region_list = a.subtree_ids
=> [1, 2, 3, 4]
如果数组中只有一个元素,则以下工作
items = Item.joins(:regions).where(["region_id = ?", [1]])
生成的sql是
"SELECT `items`.* FROM `items` INNER JOIN `items_regions` ON `items_regions`.`item_id` = `items`.`id` INNER JOIN `regions` ON `regions`.`id` = `items_regions`.`region_id` WHERE (region_id = 1)"
但是,如果数组中有多个项目,我尝试使用IN
Item.joins(:regions).where(["region_id IN ?", [1,2,3,4]])
ActiveRecord::StatementInvalid: Mysql::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1,2,3,4)' at line 1: SELECT `items`.* FROM `items` INNER JOIN `items_regions` ON `items_regions`.`item_id` = `items`.`id` INNER JOIN `regions` ON `regions`.`id` = `items_regions`.`region_id` WHERE (region_id IN 1,2,3,4)
生成的sql在最后有错误
"SELECT `items`.* FROM `items` INNER JOIN `items_regions` ON `items_regions`.`item_id` = `items`.`id` INNER JOIN `regions` ON `regions`.`id` = `items_regions`.`region_id` WHERE (region_id IN 1,2,3,4)"
生成的代码的最后一部分应该是 (region_id IN(“1,2,3,4”))
如果我手动编辑sql并运行它,我会得到我期望的结果。
所以,有两个问题:
由于 艾伦
答案 0 :(得分:3)
.where('regions.id' => array)
无论是否指定一个值或多个值,都应该适用于所有情况。
原始查询不起作用的原因是您实际需要指定有效的SQL。所以你也可以这样做
.where('region_id IN (?)', [1,2,3,4])
答案 1 :(得分:1)
其他响应者在使用条件哈希时是正确的,但是之后遇到的具体问题与字段特异性有关: Mysql ::错误:'where子句'
中的未知列'items.region_id'您正在尝试根据“region_id”绘制条件,但由于您没有明确指定表格,因此默认使用“items”。听起来您的列实际上位于“item_regions”表中。试试这个:
where("item_regions.region_id IN (?)", [1,2,3,4])
或者:
where(:item_regions => {:region_id => [1,2,3,4]})
答案 2 :(得分:0)
你试过
吗?.where('region_id IN (?)', [1,2,3,4])
形式?你需要()有效。
答案 3 :(得分:0)
我认为Arel中最干净,最惯用的方法是嵌套的哈希语法,它避免了字符串文字(以及对HABTM连接表的任何直接引用):
Item.joins(:regions).where(regions: { id: [1,2,3,4] })