0

こんにちはみんなここに私のコードがあります:

class Tailor < ActiveRecord::Base
    has_many    :tailor_items
    has_many    :order_items

    [:collars, :sexes, :sleeves].each do |attribute|
        has_many    attribute, through: :tailor_items, source: :item, source_type: attribute.to_s.classify

    end
 end

class TailorItem < ActiveRecord::Base
  belongs_to        :tailor
  belongs_to        :item, polymorphic: true
end

class Collar < ActiveRecord::Base
end

私がする必要があるのはこれです:与えられたシャツのために私は仕立て屋を選ぶ必要があります。シャツには、襟、男性/女性、または特定の種類の袖を付けることができます。いくつかの仕立て屋はすべての襟を作ることができますが、いくつかの袖だけを作ることができます、他の仕立て屋は男性のものだけを作ることができます、など。この例では優先順位は重要ではありません。アイデアは、私が1つの仕立て屋で終わるということです。

私はこれを試しました:

tailors = Tailor.joins(:tailor_items).where("(item_id = ? and item_type = ?)",1,"Collar")
if tailors.count > 1
  tailors.where("(item_id = ? and item_type = ?)",2,"Sleeve")
  if tailors.count > 1
     # and so forth.
  end
end

しかし、私は一列に戻ることはありません。私が言うなら:

Tailor.find(1).tailor_items 

2つの結果が得られます(簡単にするためのsudoコード)

<id: 1, item_type: "Collar"><id:2, item_type:"Sleeve"> 

そして2番目のテーラーのために:

Tailor.find(2).tailor_items 

2つの結果が得られます(簡単にするためのsudoコード)

<id: 1, item_type: "Collar"><id:3, item_type:"Sleeve"> 

しかし、クエリでそれらをチェーンしようとすると、機能しません...すべてを1つにまとめても、次のようになります。

Tailor.where("(item_id = 1 and item_type = 'Collar') and (item_id = 2 and item_type = 'Sleeve')")

私はまだ0の結果を取得します。

Tailor.where("item_id = 1 and item_type = 'Collar'") returns: Tailor #1
Tailor.where("item_id = 2 and item_type = 'Sleeve'") returns: Tailor #1

しかし、一緒に彼らは何も返しません。

Tailor Load (0.0ms) SELECT "tailors".* FROM "tailors" INNER
JOIN "tailor_items" ON "tailor_items"."tailor_id" = "tailors"."id" WHERE ((tailo
r_items.item_id = 1 and tailor_items.item_type = 'Collar') and (tailor_items.ite
m_id = 2 and tailor_items.item_type = 'Sleeve'))

私は混乱しています..

ご協力いただきありがとうございます。

私は実行します:Win XP Postgresql Rails 3.2.2

PS:ポリモーフィック結合の後でこれを完了するために欠けているのは、少しのXMLだけです。:Pそれ以外の場合は、エンタープライズではありません-十分です。

編集:Rob di Marcosスコープを実装すると、次のSQLが得られます:

SELECT "tailors".* FROM "tailors" WHERE 
(EXISTS(SELECT * FROM tailor_items WHERE tailor_items.item_id = 1 and tailor_items.item_type = 'Collar')) 
AND (exists(select * from tailor_items where tailor_items.item_id = 2 and tailor_items.item_type = 'Sleeve'))

これにより、両方を実行できるテーラー1だけではなく、2つのテーラーが返されます(テーラー2はスリーブ#2を実行できません)

4

1 に答える 1

2

問題は、where が 2 つの行で一致する必要があることです。通常、サブクエリを使用してこれをテストします。だから何か

Tailor.where("exists (select 'x' from tailor_items where 
         tailor_id = tailors.id and tailor_items.item_id = ? and 
         tailor_items.item_type=?)", 1, 'Collar').
       where("exists (select 'x' from tailor_items where 
         tailor_id = tailors.id and tailor_items.item_id = ? and 
         tailor_items.item_type=?)", 2, 'Sleeve')

この例では、探している仕立て屋のアイテムごとに 1 つのサブクエリがあります。次のように、これを Tailor のスコープに簡単に作成できます。

class Tailor
  # ....
  scope :with_item, lambda{ |item_id, item_type | 
      where("exists (select 'x' from tailor_items where 
     tailor_id = tailors.id and tailor_items.item_id = ? and 
     tailor_items.item_type=?)", item_id, item_type)
     }

その後、Tailor リクエストを連鎖させることができます

Tailor.with_item(1, 'Collar').with_item(2, 'Sleeve')
于 2012-05-22T02:01:32.623 に答える