0

私は最初の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

私の目標は、スコープ/クエリを作成することです。

リージョン(およびそのサブリージョン)内のすべてのアイテムを検索する

祖先の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] 

配列に要素が1つしかない場合、次のように機能します

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を手動で編集して実行すると、期待どおりの結果が得られます。

したがって、2つの質問:

  1. 単一値の場合の私のアプローチは正しいですか?
  2. SQL生成はバグですか、それとも正しく構成されていませんか?

ありがとうアラン

4

4 に答える 4

3
.where('regions.id' => array)

1つの値または複数の値を指定するかどうかに関係なく、すべての場合に機能するはずです。

元のクエリが機能しない理由は、実際に有効なSQLを指定する必要があるためです。だから代わりにあなたはすることができます

.where('region_id IN (?)', [1,2,3,4])
于 2011-04-12T21:55:15.083 に答える
1

他のレスポンダーは条件ハッシュの使用に関して正しいですが、その後に遭遇する特定の問題は、フィールドの特異性に関係しています:Mysql :: Error:Unknown column'items.region_id' in'whereclause'

「region_id」に基づいて条件を描画しようとしていますが、テーブルを明示的に指定していないため、デフォルトで「items」が使用されます。あなたの列は実際には「item_regions」テーブルにあるようです。これを試して:

where("item_regions.region_id IN (?)", [1,2,3,4])

または代わりに:

where(:item_regions => {:region_id => [1,2,3,4]})
于 2011-04-18T23:33:39.787 に答える
0

やってみましたか

.where('region_id IN (?)', [1,2,3,4])

形?()が有効である必要があります。

于 2011-04-18T23:27:10.480 に答える
0

Arelでこれを行う最もクリーンで慣用的な方法は、文字列リテラル(およびHABTM結合テーブルへの直接参照)を回避するネストされたハッシュ構文だと思います。

Item.joins(:regions).where(regions: { id: [1,2,3,4] })
于 2014-06-29T21:10:16.083 に答える