Rails:为什么with_exclusive_scope受到保护?关于如何使用它的任何好的做法?

Rng*_*Tng 47 scope ruby-on-rails

给定一个带有default_scope的模型来过滤所有过时的条目:

# == Schema Information
#
#  id          :integer(4)      not null, primary key
#  user_id     :integer(4)      not null, primary key
#  end_date    :datetime        

class Ticket < ActiveRecord::Base
  belongs_to :user
  default_scope :conditions => "tickets.end_date > NOW()"
end
Run Code Online (Sandbox Code Playgroud)

现在我想得到任何票.在这种情况下,with_exclusive_scope是要走的路,但这种方法是否受到保护?只有这个有效:

 Ticket.send(:with_exclusive_scope) { find(:all) }
Run Code Online (Sandbox Code Playgroud)

有点黑客,不是吗?那么正确的使用方法是什么?特别是在处理协会时,情况变得更糟(假设用户有很多票):

 Ticket.send(:with_exclusive_scope) { user.tickets.find(:all) }
Run Code Online (Sandbox Code Playgroud)

这是如此丑陋! - 不能成为轨道!?

bra*_*rad 174

对于任何寻找Rails3方式的人来说,你可以使用以下unscoped方法:

Ticket.unscoped.all
Run Code Online (Sandbox Code Playgroud)

  • 请注意使用unscoped方法,因为它将删除之前可能已添加的所有查询约束.例如,假设author.books.all返回作者的所有书籍(通过default_scope按id排序),author.books.unscoped.order('books.title').所有书籍实际上将返回所有书籍,无论作者是谁unscoped删除books.author_id == author.id的约束 (62认同)
  • 哇靠!我希望这更接近顶部! (2认同)

Rya*_*ary 34

default_scope尽可能避免.我想你应该重新问自己为什么需要一个default_scope.打击a default_scope通常比它的价值更加混乱,它应该只在极少数情况下使用.此外,default_scope在票证模型之外访问票证关联时,使用并不是很明显(例如"我打电话account.tickets.为什么我的票不在那里?").这with_exclusive_scope是受保护的部分原因.当你需要使用它时,你应该品尝一些语法醋.

作为替代方案,使用像pacecar这样的gem/plugin ,可以自动将有用的named_scope添加到您的模型中,从而为您提供更具启发性的代码.例如:

class Ticket < ActiveRecord::Base
  include Pacecar
  belongs_to :user
end

user.tickets.ends_at_in_future # returns all future tickets for the user
user.tickets                   # returns all tickets for the user
Run Code Online (Sandbox Code Playgroud)

您还可以装饰您的用户模型以使上述代码更清晰:

Class User < ActiveRecord::Base
  has_many :tickets

  def future_tickets
    tickets.ends_at_in_future
  end
end

user.future_tickets # returns all future tickets for the user
user.tickets        # returns all tickets for the user
Run Code Online (Sandbox Code Playgroud)

附注:另外,请考虑使用更惯用的日期时间列名称ends_at而不是end_date.


Vla*_*anu 20

您必须将受保护的方法封装在模型方法中,例如:

class Ticket < ActiveRecord::Base
  def self.all_tickets_from(user)
    with_exclusive_scope{user.tickets.find(:all)}
  end
end
Run Code Online (Sandbox Code Playgroud)

  • 不推荐使用"with_exclusive_scope".在导轨3和4中使用"unscoped"代替.有关详细信息和示例,请查看:http://github.com/rails/rails/commit/bd1666ad1de88598ed6f04ceffb8488a77be4385 (5认同)