Ruby/Rails中的类方法与常量

Gen*_*nís 36 ruby ruby-on-rails

我正在实现一个包含一个集合的硬编码下拉列表的表单,我想知道什么是最好的解决方案,我知道两种方式暴露在工作之下,我仍然做如下:

class Example

  # Options for Example.
  self.options
    [ 'Yes', 'No', 'Not sure' ]
  end
end
Run Code Online (Sandbox Code Playgroud)

这被称为Example.options,但我知道也可以这样做:

class Example

  # Options for Example.
  OPTIONS = [ 'Yes', 'No', 'Not sure' ]
end
Run Code Online (Sandbox Code Playgroud)

这将被称为Example::OPTIONS.

问题是,这些中的任何一种都是好方法还是根本不重要?

saw*_*awa 36

后者更好.如果它是一个方法,每次调用时都会创建一个新数组和新字符串,这会浪费资源.

  • 方法提供的灵活性比节省便士更重要(恕我直言,显然) (5认同)
  • 虽然很容易在方法中缓存数组...`@options || = [...]` (3认同)

Mar*_*une 31

TL; DR:这取决于.这些值是否意味着在课外使用?他们会变得充满活力吗?他们可以改变子类吗?

正如@sawa写的那样,该方法的缺点(以这种方式编写)是每次都创建一个新的数组和字符串.

写一个更好的方法是:

class Example
  def self.options
    @options ||= ['Yes', 'No', 'Not sure']
  end
end
Run Code Online (Sandbox Code Playgroud)

该数组存储在实例变量中@options,以避免每次都创建一个新数组.

这样写的方法与常量非常相似.

一个关键的区别是如果Example是子类,那么优化options方法比常量更自然OPTIONS:

class Parent < Example
  def self.options
    @options ||= [*super, 'Extra']
  end
end
Run Code Online (Sandbox Code Playgroud)

用常量做类似的事很难.想象一下,您的选项列表在类方法中使用,如下所示:

class Example
  OPTIONS = ['Yes', 'No', 'Not sure']

  def self.foo(arg)
     puts "Available options:",
          self::OPTIONS  # The self:: is needed here
     # ...
  end
end

class Parent < Example
  OPTIONS = [*superclass::OPTIONS, 'Extra']
end
Run Code Online (Sandbox Code Playgroud)

关于常数的棘手问题是,self::OPTIONS并且OPTIONS不是总是相同的,self.options而且options是相同的.通常使用常量而不指定范围(例如,OPTIONS而不是self::OPTIONS),并且继承在这种情况下根本不起作用.

请注意,该方法使您有机会在不更改API的情况下使结果动态化(即根据其他情况返回不同的结果).

最后注意事项:我建议您调用freeze阵列,以避免任何人修改它.

  • @sawa:的确,您可以(并且可以使用`superclass`而不是显式编写父类),但访问常量可能很棘手.编辑我的回答. (2认同)

Art*_*jev 7

我通常做的是混合使用上述技术:

class Player
  JURISDICTIONS = %i(de uk ru)

  def self.jurisdictions
    JURISDICTIONS
  end
end
Run Code Online (Sandbox Code Playgroud)

它没有什么优点:

  • 它提供了一个干净的接口,封装了一个常量(你调用Player.jurisdictions而不是Player::JURISDICTIONS).
  • 稍后可以通过改变方法来添加附加逻辑.
  • 该方法可以在测试中存根.

恕我直言,这里的表现并不重要.

更新:使用private_constant方法隐藏常量(http://ruby-doc.org/core-2.3.0/Module.html#method-i-private_constant)

  • 你有一个错字应该是自我. (2认同)