【问题标题】:Rails: What's the difference between lambda, scope and class method? What's best practice?Rails:lambda、范围和类方法有什么区别?什么是最佳做法?
【发布时间】:2014-01-03 00:43:37
【问题描述】:

code sn-p 有三种方法:lambdascopeclass method

它们都返回相同的结果。

问题:

  1. Ruby/Rails 中是否有任何最佳做法,当首选使用其中一种而不是另一种时?
  2. 在什么情况下您会使用lambdascopeclass 方法(最佳实践)。

    class Cars < ActiveRecord::Base     
      attr_accessible :manufacturer, :price, :used
    
      #one
      scope :used_and_cheap_lambda, lambda { where('used = ?', true ).where('price >= ?',30000) }
    
      #two
      scope :used_and_cheap_scope, where('used = ?', true ).where('price >= ?',30000)
    
      #three
      def self.used_and_cheap_class
        where('used = ?', true ).where('price >= ?',30000)
      end
    end
    
    
    
    
    
    Cars.used_and_cheap_lambda.count
    => #24
    
    Cars.used_and_cheap_class.count
    => #24
    
    Cars.used_and_cheap_scope.count
    => #24
    

【问题讨论】:

    标签: ruby-on-rails ruby methods


    【解决方案1】:

    最好避免使用选项 2。当您的 Rails 应用程序加载时,该代码会立即运行,这很糟糕,因为对于您在其中使用的任何 Time 参数,它总是返回相同的值。这是因为它不会在每次调用时都重新评估。

    正如 musicnerd47 所指出的,选项 1 是延迟加载的,建议您将 lambdas 传递给 Rails 4 中的范围,而不是执行选项 2,因为每次调用时都会重新计算它们,因此它们将返回更新的值。

    因此,唯一的选择是 1 和 3。这通常是您的团队所坚持的风格问题。在我们公司,当我们传递给它的代码将是一个 ActiveRecord 查询并且我们希望它输出一个可以链接的查询时,我们使用选项 1。这是为了确保每次查询多条记录时都返回一个 ActiveRecord::Relation 对象。这意味着它们总是可以与其他 ActiveRecord::Relation 方法和我们其他定义的范围链接。

    如果用于不需要与其他范围链接的行为,我们使用选项 3。

    这是关于范围和 class_methods 问题的好读物,他详细介绍并提供了范围和类方法之间差异的示例。 http://blog.plataformatec.com.br/2013/02/active-record-scopes-vs-class-methods/

    【讨论】:

    【解决方案2】:

    从 Rails 4 开始,您必须使用 lambda - 通常这是一种更好的做法,因为它是延迟加载的并且可以防止很多陷阱,尤其是在处理日期和时间时。

    我认为对于处理单个 where 调用或其他内容的简单范围,使用 scope 是可以的。当它更复杂时,转移到类方法会更好(例如,当您需要在返回作用域之前调用其他方法或设置局部变量时)。

    【讨论】:

    • Logan Serman - 感谢您的回答。您能具体说明您的意思是什么陷阱吗? (你提到了日期和时间)
    • 如果您有一个涉及例如Time.now(或类似)的范围,则将在加载类时(当您启动 Rails 应用程序时)对其进行评估。所以Time.now 将不准确,它将是加载类的时间。使用 lambda 会延迟加载作用域,因此在调用作用域时会调用 Time.now,这将是您所期望的。
    • 你不必使用 lambda,选项 2 在 Rails4 的 ActiveRecord 中不再可用,但使用 scope"is exactly the same as defining a class method, and which you use is a matter of personal preference""Using a class method is the preferred way to accept arguments for scopes" 所以有时官方首选类方法。
    • 不必使用 lambda 是什么意思?您链接的页面上的所有示例都使用 lambda。 IIRC,不使用 lambda 时会出现弃用警告(除非在补丁 > 4.0.0 中将其删除?)
    【解决方案3】:

    我会使用 lambda。您描述的功能非常简单。使用 lambda 也会延迟初始化。我将您 here 定向到 Rails 样式指南。

    【讨论】:

      【解决方案4】:

      不幸的是,没有黄金法则。示波器专为这种确切的应用而设计。当逻辑的应用舒适地适合一个范围时,我认为这是最好的选择。当事情开始变得过于复杂时,通常最好将逻辑移动到类方法中。

      【讨论】:

        猜你喜欢
        • 2013-06-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-06
        • 1970-01-01
        • 2010-10-05
        • 1970-01-01
        相关资源
        最近更新 更多