Ruby on rails Ruby/Rails中的类方法与常量
我正在实现一个表单,其中包含一个集合的硬编码下拉列表,我想知道什么是最好的解决方案,我知道下面工作中暴露的两种方法,但我还是做了如下工作:Ruby on rails Ruby/Rails中的类方法与常量,ruby-on-rails,ruby,Ruby On Rails,Ruby,我正在实现一个表单,其中包含一个集合的硬编码下拉列表,我想知道什么是最好的解决方案,我知道下面工作中暴露的两种方法,但我还是做了如下工作: class Example # Options for Example. self.options [ 'Yes', 'No', 'Not sure' ] end end 由示例.options调用,但我知道也可以执行以下操作: class Example # Options for Example. OPTIONS = [
class Example
# Options for Example.
self.options
[ 'Yes', 'No', 'Not sure' ]
end
end
由示例.options
调用,但我知道也可以执行以下操作:
class Example
# Options for Example.
OPTIONS = [ 'Yes', 'No', 'Not sure' ]
end
这将通过Example::OPTIONS
调用
问题是,这些方法是好的还是根本不重要?后者更好。如果它是一个方法,每次调用它时都会创建一个新数组和新字符串,这是对资源的浪费;医生:这要看情况。这些值是否要在类外使用?他们会变得充满活力吗?它们是否可以更改为子类 正如@sawa所写,该方法(以这种方式编写)的缺点是每次都会创建一个新的数组和字符串 更好的写作方法是:
class Example
def self.options
@options ||= ['Yes', 'No', 'Not sure']
end
end
数组存储在实例变量@options
中,以避免每次创建新数组
以这种方式编写的方法与常量非常相似
class Player
@@jurisdictions = %i(de uk ru)
def self.jurisdictions
@@jurisdictions
end
end
一个关键区别是,如果将示例
子类化,则与常量选项
相比,细化选项
方法更为自然:
class Parent < Example
def self.options
@options ||= [*super, 'Extra']
end
end
class父类<示例
def self.options
@选项| |=[*超级,“额外”]
结束
结束
用常数做类似的事情是困难的。假设您的选项列表用于类方法,如下所示:
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
类示例
选项=[“是”、“否”、“不确定”]
def self.foo(arg)
将“可用选项:”,
self::OPTIONS#这里需要self::
# ...
结束
结束
类父类<示例
选项=[*超类::选项,“额外”]
结束
常数的棘手之处在于self::OPTIONS
和OPTIONS
并不总是相同的,而self.OPTIONS
和OPTIONS
是相同的。常量通常在不指定范围的情况下使用(例如,OPTIONS
而不是self::OPTIONS
),在这种情况下继承将不起作用
请注意,该方法使您有机会在不更改API的情况下动态生成结果(即根据其他情况返回不同的结果)
最后一点注意:我建议在您的阵列上调用
freeze
,以避免任何人对其进行修改。我通常会混合使用上述技术:
class Player
JURISDICTIONS = %i(de uk ru)
def self.jurisdictions
JURISDICTIONS
end
end
它没有什么优势:
- 它提供了一个干净的接口,封装了一个常量(您调用
而不是Player.辖区
)Player::辖区
- 以后只需改变方法,就可以添加额外的逻辑
- 该方法可在试验中使用
可以使用
private\u Constant
method()隐藏常量为了进一步完善Artur的建议,我将使用一个类变量来隐藏常量的可见性
class Player
@@jurisdictions = %i(de uk ru)
def self.jurisdictions
@@jurisdictions
end
end
普遍接受的方法是后一种方法,因为注释是向用户提供的一种文档形式,这与可能的答案有关,我建议在字符串上使用符号,除非您的代码特别需要字符串。因此,
[:是,:否,:不确定]
@CharlesCaldwell或更短的%i[是否不确定]
。在我看来,这个问题与哪个更好地解释选项背后的心态有关。常量包含源代码中定义的常量值,变量包含变化的值,方法应该做些什么(而不是返回硬编码数组)。太棒了,+10,如果可以;-)+1同时调用示例。当您知道是一个类常量时,方法将告诉options是一个方法。这是生成一致代码的另一个技巧。不过,在方法中缓存数组很容易@options | |=[…]
写了另一个答案,因为我不同意常数是更好的方法。方法提供的灵活性比节省一分钱更重要(显然,IMHO),你仍然可以对常数做类似的事情:示例::options=[“是”、“否”、“不确定”];父项::选项=[*示例::选项,“额外”]
。唯一的区别是您必须显式地编写父类,而不是使用super
@sawa:的确,您可以(并且您可以使用superclass
而不是显式地编写父类),但是访问常量可能会很棘手。编辑了我的答案。问题中的相关想法是直接调用常量,如Example::OPTIONS
或Parent::OPTIONS
,或OPTIONS
。我不明白你为什么要定义self.foo
来调用它们。这是一个使用options/options
的类方法示例。你有一个拼写错误,它应该是self。效果更好,同意!但到目前为止,我无法解决这里所描述的继承问题:在我写了这个之后,我发现你也应该考虑类级别的实例变量: