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
后者更好.如果它是一个方法,每次调用时都会创建一个新数组和新字符串,这会浪费资源.
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
阵列,以避免任何人修改它.
我通常做的是混合使用上述技术:
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)