5

Rails 3.2 を使用した私の ActiveRecord モデルは次のとおりです。

class User < ActiveRecord::Base
    has_one :criterion
    has_many :user_offer_choices
end

class Offer < ActiveRecord::Base
    has_many :user_offer_choices

    def seen
        user_offer_choices.where(seen: true)
    end

    def accepted
        user_offer_choices.where(accepted: true)
    end
end

class Criterion < ActiveRecord::Base
    belongs_to :user
end

class UserOfferChoice < ActiveRecord::Base
    belongs_to :user
    belongs_to :offer
end

オファーを見たユーザーのすべての基準を取得したいと考えています。何かのようなもの :

Offer.find(11).seen.users.criterions

しかし、ActiveRecordでそれを行う方法がわかりません

私は次のようなことができることを知っています:

Criterion.joins(user: { user_offer_choices: :offer }).where(user: { user_offer_choices: {accepted: true, offer_id: 11}  } )

しかし、私は自分のスコープをオファーで使用できるようにしたい (見た & 受け入れた)。どうすればそれができますか?

編集: 私が探していたもの、Arelのマージ方法を見つけました:http://benhoskin.gs/2012/07/04/arel-merge-a-hidden-gem

4

1 に答える 1

3

まず、本当に必要なのは、選択の範囲を定義することです。

class UserOfferChoice < ActiveRecord::Base
  belongs_to :user
  belongs_to :offer

  scope :seen, where(seen: true)
  scope :accepted, where(accepted: true)
end

これにより、これを行うことができます

Offer.find(11).user_offer_choices.seen

そして基準を取得するには:

Offer.find(1).user_offer_choices.seen.map{|choice| choice.user}.map{|user| user.criterion}

これは、Offer クラスの has many スルーでクリーンアップできます。

class Offer < ActiveRecord::Base
  has_many :user_offer_choices
  has_many :users, :through => :user_offer_choices
end

しかし、それは私たちをユーザーに導きますが、スコープをスキップします.

Offer.find(1).users

さて、Rails 2.3.5 の named_scopes ではできなかった Rails 3 のスコープでできるトリックがあります。named_scopes は引数としてハッシュを取りましたが、リレーションを返しました。Rails 3 のスコープは、where などのクエリ メソッドと同様にリレーションを取得します。したがって、choices クラスで定義されたスコープを使用して、users でスコープを定義できます。

class User < ActiveRecord::Base
  has_one :criterion
  has_many :user_offer_choices
  has_many :offers, :through => :user_offer_choices

  scope :seen, UserOfferChoice.seen
  scope :accepted, UserOfferChoice.accepted
end

これにより、次のことが可能になります。

Offer.find(1).users.seen

マップは次のようになります。

Offer.find(1).users.seen.map{|user| user.criterion}

ところで、基準の複数形は基準です。読んでいるときに頭の中で基準を聞くのは痛いです。これを行うと、Rails に複数形を認識させることができます。

config/initializers/inflections.rb
ActiveSupport::Inflector.inflections do |inflect|
  inflect.plural /^criterion$/i, 'criteria'
end
于 2012-05-22T00:57:50.073 に答える