有人能告诉我在Rails 4中执行以下行的等效方法是什么?
has_many :friends, :through => :friendships, :conditions => "status = 'accepted'", :order => :first_name
Run Code Online (Sandbox Code Playgroud)
我尝试了以下方法:
has_many :friends, -> { where status: 'accepted' }, :through => :friendships , :order => :first_name
Run Code Online (Sandbox Code Playgroud)
但是我收到以下错误:
Invalid mix of scope block and deprecated finder options on ActiveRecord association: User.has_many :friends
Run Code Online (Sandbox Code Playgroud)
Kal*_*ope 113
需要成为第二个arg:
class Customer < ActiveRecord::Base
has_many :orders, -> { where processed: true }
end
Run Code Online (Sandbox Code Playgroud)
http://edgeguides.rubyonrails.org/association_basics.html#scopes-for-has-many
回复更新:
将订单放在块内:
has_many :friends, -> { where(friendship: {status: 'accepted'}).order('first_name DESC') }, :through => :friendships
Run Code Online (Sandbox Code Playgroud)
Moh*_*mad 54
虽然这里的其他答案在技术上是正确的,但它们违反了封装.该用户模型不应该知道的是,友谊模型有一个叫列status,并且它可以有这样一个特定的值accepted.
例如,如果您决定进行更改,以利用Rails 4中的Enums,则必须同时更改User和Friendship模型.这可能导致保持封装的错误避免.
我会在友谊模型中公开一个范围:
scope :accepted, -> { where(status: :accepted) }
Run Code Online (Sandbox Code Playgroud)
然后我会用这个范围的用户模式,隐藏任何实现细节的用户.
has_many :friendships, -> { Friendship.accepted }
has_many :friends, through: :friendships
# Or...
has_many :friends, -> { Friendship.accepted }, through: :friendships
Run Code Online (Sandbox Code Playgroud)
您可以进一步将范围重命名accepted_friendships为更清晰.
has_many :accepted_friendships, -> { Friendship.accepted }
has_many :friends, through: :accepted_friendships
Run Code Online (Sandbox Code Playgroud)
现在,您已在各自的模型中成功封装了实现细节.如果有任何改变,你只有一个地方可以改变它,减少维护并提高稳健性.
Mohamad 答案的 Rails 3.2 版本如下:
class Friend < ActiveRecord::Base
has_many :friendships, :order => :first_name
has_many :friends, :through => :friendships,
:conditions => proc { Friendship.accepted.where_ast }
has_many :pending_friends, :through => :friendships,
class_name => Friend,
:conditions => proc { Friendship.pending.where_ast }
end
class Friendship < ActiveRecord::Base
scope :status, ->(status) { where(:status => status) }
scope :accepted, -> { status('accepted') }
scope :pending, -> { where(arel_table[:status].not_eq('accepted')) }
end
Run Code Online (Sandbox Code Playgroud)
笔记:
where_ast 很重要,因为它返回条件工作所需的 AREL 节点:conditions,self并不总是一个模型实例(例如,当关联与另一个查询合并时)| 归档时间: |
|
| 查看次数: |
55383 次 |
| 最近记录: |