我有一个管理配置的类(本地保存为JSON),我编写了一个方法将配置从一个文件复制到另一个文件。两个JSON文件都作为哈希加载到实例变量中(分别为@local
和@repository
)。我遇到了一些奇怪的行为,在一个哈希上设置一个键就会覆盖另一个哈希中相同键的值。我已将问题缩小到下面代码片段的第14行。第12行的puts
语句将@repository[brand][:branches][branch]
显示为包含数据的非空哈希,而第21行的puts
语句将@repository[brand][:branches][branch]
显示为空哈希。< / p>
def copy(brand, branch = nil)
brand = brand.to_sym
branch = branch.to_sym
if branch.nil?
if @local[:repository].has_key?(brand)
@local[:repository][brand].deep_merge(@repository[brand])
else
@local[:repository][brand] = @repository[brand]
end
else
puts @repository[brand][:branches][branch]
unless @local[:repository].has_key?(brand)
@local[:repository][brand] = @repository[brand]
@local[:repository][brand][:branches] = Hash.new
end
unless @local[:repository][brand][:branches].has_key?(branch)
@local[:repository][brand][:branches][branch] = Hash.new
end
puts @repository[brand][:branches][branch]
@local[:repository][brand][:branches][branch].deep_merge(@repository[brand][:branches][branch])
end
self.write(CONFIG_FILE, @local)
end
如果我将第14行更改为@local[:repository][brand] = Hash.new
,则第21行上该哈希的值不再为空,实际上是预期值。一个关键是brand
中的@local[:repository]
键尚不存在。
有人能说清楚这里发生了什么吗?
答案 0 :(得分:2)
罪魁祸首在于这一行(你使用了两次):
@local[:repository][brand] = @repository[brand]
这不会复制驻留在@repository[brand]
中的哈希。
让我们把它分开一点,这样我们就可以更清楚地谈论它了:
brand_detail = @repository[brand]
local_repo = @local[:repository]
local_repo[brand] = brand_detail
在第三个语句之后,local_repo[brand]
将不包含brand_details
哈希的副本,而是引用到该哈希。所以现在所有这些线都会产生同样的效果;他们都会修改相同的哈希实例:
brand_detail[:branches] = 3
local_repo[brand][:branches] = 3
@repository[brand][:branches] = 3
您应该能够通过使用dup
明确添加副本而不是引用来规避这一点:
@local[:repository][brand] = @repository[brand].dup