5

这是我的 ActiveRecord 模型,带有 Rails 3.2:

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 through 来清理。

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

但这让我们接触到了用户,但跳过了范围。

Offer.find(1).users

现在,您可以使用 Rails 3 作用域做一个技巧,而用 Rails 2.3.5 named_scopes 做不到。named_scopes 将散列作为参数,但返回一个关系。Rails 3 范围采用关系,例如来自 where 等查询方法。因此,您可以使用您的选择类中定义的范围在用户中定义范围!

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 回答