1

私はこのように接続されている3つのモデルを持っています:

class FooTemplate < ActiveRecord::Base
    has_many :foos
end

class Foo < ActiveRecord::Base
    belongs_to :foo_template
    belongs_to :bar
end

class Bar < ActiveRecord::Base
    has_many :foos
end

モデル内では、配列内の ID によって参照されるそれぞれに属するものをBarすべて見つけるメソッドが必要です。BarsFoosFooTemplate

def find_by_foo_templates(foo_template_ids)
    # what goes here?
end

パラメータは、常に次の形式を持つ配列です。

[""]
["", "1", "2"]

ID が送信されない場合でも、配列には常に空の文字列が含まれます。

私がやろうとしていることを理解していただければ幸いです。

アップデート

例を示しましょう。

Bar: 1
  Foo: 1
    FooTemplate: 1
  Foo: 2
    FooTemplate: 2

Bar: 2
  Foo: 3
    FooTemplate: 2
  Foo: 4
    FooTemplate: 3

Bar: 3
  Foo: 5
    FooTemplate: 3
  Foo: 6
    FooTemplate: 4

これは、それぞれ 2 つの独立した Foo を持つ 3 つのバーになります。そして、Foos にはいくつかの「重複する」FooTemplates があります。

いくつかのリストの望ましい結果:

["1"] schould only return Bar 1, because it's the only one whose Foos have a FooTemplate 1.
["2"] should return Bar 1 & 2, because they both have a Foo with a FooTemplate 2
["2", "3"] should return only Bar 2, because it's the only one which has a Foo with FooTemplate 2 AND a Foo with FooTemplate 3
["1", "4"] should return nothing because there is no Bar whose Foos have FooTemplates 1 AND 4

更新 2

機能する解決策を見つけましたが、拒否を使用し、さらにいくつかのデータベース クエリを生成します。

class Bar < ActiveRecord::Base
    has_many :foos
    has_many :foo_templates, through: :foos

    def self.find_by_foo_template_ids(foo_template_ids)
        ids = foo_template_ids.map { |id| id.to_i }

        joins(foos: :foo_template).uniq.where(foos: { foo_template_id: ids }).reject do |bar|
            !(bar.foo_template_ids & ids == ids)
        end
    end
end

これは配列を返しますが、ActiveRecord::Relation追加のクエリを実行する必要があります。

4

2 に答える 2

2
def self.find_by_foo_templates(foo_template_ids)
  joins(:foos => :foo_template).where(['foo_templates.id in (?)', foo_template_ids.reject!(&:empty?)])
end
于 2013-07-01T21:05:51.033 に答える
0

注: これはほぼ確実に PostGres のみです。また、ちょっとしたハックのようにも感じます。しかし、私はそれがうまくいくと思います。

def self.find_by_foo_templates(foo_template_ids)
  joins(:foos => :foo_template).
  group('bars.id').
  having("array_agg(foo_templates.id) @> string_to_array(?, ',')::int[]", foo_template_ids.join(','))
end

これは、返された各 Bar に関連付けられた Foo に対応する FooTemplate の ID を集約し、すべての入力 ID を含む Bar のみを返す必要があります。

于 2013-07-01T22:08:32.210 に答える