use*_*793 2 ruby ruby-on-rails
我知道我可以使用class作为Hash键,但这是一个好习惯吗?在性能或测试方面有任何缺点吗?
{
SomeClassA: 'hash value',
AnotherClass: 'hash value'
}
Run Code Online (Sandbox Code Playgroud)
{
SomeClassA: 'hash value',
AnotherClass: 'hash value'
}
Run Code Online (Sandbox Code Playgroud)
实际上相当于:
{
:SomeClassA => 'hash value',
:AnotherClass => 'hash value'
}
Run Code Online (Sandbox Code Playgroud)
键是符号.在"新"文字散列语法中,键被视为文字,它们被转换为符号(前提是它们是有效的语法).
要使用常量,范围或任何其他类型的对象,您可以将梦想作为使用hashrockets所需的键:
{
SomeClassA => 'hash value',
AnotherClass => 'hash value'
}
Run Code Online (Sandbox Code Playgroud)
这是一个好习惯吗?
它是一种可以在少数有限情况下使用的技术.例如,替换一系列if语句.
def foo(bar)
if bar.is_a? SomeClassA
'hash value'
end
if bar.is_a? AnotherClass
'another value'
end
end
def foo(bar)
{
SomeClassA => 'hash value',
AnotherClass => 'another value'
}[bar]
end
Run Code Online (Sandbox Code Playgroud)
但我宁愿在那里使用案例陈述,因为它的意图更清晰,更灵活.
在性能或测试方面有任何缺点吗?
您创建的每个哈希都会包含指向内存中完全相同对象的键,就像您使用符号一样.
一个很大的问题是Rails猴子补丁const_missing到自动加载文件 - 当你引用类名时rails会将文件从文件系统加载到内存中.这就是你声明与以下关联的原因:
class Foo < ApplicationRecord
belongs_to :bar, class_name: "Baz"
end
Run Code Online (Sandbox Code Playgroud)
它允许Rails在需要时延迟加载Baz.您将通过以下示例执行相同的操作:
def foo(bar)
{
'SomeClassA' => 'hash value',
'AnotherClass' => 'another value'
}[bar.name]
end
Run Code Online (Sandbox Code Playgroud)