El_*_*dor 5 activerecord ruby-on-rails ruby-on-rails-3.2
这是我的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
Run Code Online (Sandbox Code Playgroud)
我想获得看到报价的用户的所有标准.就像是 :
Offer.find(11).seen.users.criterions
Run Code Online (Sandbox Code Playgroud)
但我不知道如何使用ActiveRecord
我知道我可以这样做:
Criterion.joins(user: { user_offer_choices: :offer }).where(user: { user_offer_choices: {accepted: true, offer_id: 11} } )
Run Code Online (Sandbox Code Playgroud)
但我希望能够在优惠(看到和接受)上使用我的范围.那我该怎么办呢?
编辑: 我找到了我要找的东西,Arel的合并方法:http://benhoskin.gs/2012/07/04/arel-merge-a-hidden-gem
首先,您真正想要的是定义您的选择范围。
class UserOfferChoice < ActiveRecord::Base
belongs_to :user
belongs_to :offer
scope :seen, where(seen: true)
scope :accepted, where(accepted: true)
end
Run Code Online (Sandbox Code Playgroud)
这允许你这样做
Offer.find(11).user_offer_choices.seen
Run Code Online (Sandbox Code Playgroud)
并获得标准:
Offer.find(1).user_offer_choices.seen.map{|choice| choice.user}.map{|user| user.criterion}
Run Code Online (Sandbox Code Playgroud)
现在,这可以通过 Offer 类中的 has many through 来解决。
class Offer < ActiveRecord::Base
has_many :user_offer_choices
has_many :users, :through => :user_offer_choices
end
Run Code Online (Sandbox Code Playgroud)
但这让我们接触到了用户,但跳过了范围。
Offer.find(1).users
Run Code Online (Sandbox Code Playgroud)
现在,您可以使用 Rails 3 范围执行一个技巧,而使用 Rails 2.3.5 命名范围则无法执行此操作。name_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
Run Code Online (Sandbox Code Playgroud)
这使我们能够这样做:
Offer.find(1).users.seen
Run Code Online (Sandbox Code Playgroud)
地图现在看起来像这样:
Offer.find(1).users.seen.map{|user| user.criterion}
Run Code Online (Sandbox Code Playgroud)
顺便说一句,标准的复数是标准。当我读到它时,我脑海中的听觉标准很痛苦。你可以这样做来让 Rails 知道复数:
config/initializers/inflections.rb
ActiveSupport::Inflector.inflections do |inflect|
inflect.plural /^criterion$/i, 'criteria'
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3787 次 |
| 最近记录: |