我想知道下面的方法在多个环境中捕获自定义配置参数有多糟糕。这是为了解决可能需要组织好几层的非常大的配置参数的情况。
需要以下功能: - 设置配置参数需要非常简单,易于复制/粘贴 - 访问配置参数需要简洁 - 应该是编程的灵活性,没有 yaml(除非被说服) - 每个环境的配置不需要强制性的,应该依靠一个健全的默认值(在这种情况下,:base 配置) - 初始化配置对象需要简洁 - 需要隐藏环境细节
这个实现的缺点: - eval 是邪恶的?在这种情况下 eval 真的那么糟糕吗?用户不控制这些值,它们都在源代码中硬编码。- 不是最快的,但在我的情况下没关系 - 初始化哈希很奇怪 - “get”调用也有点奇怪
创建它是因为我需要一种强大的方法来处理可能包含大量参数的文件。这些参数可能因环境而异,因此能够轻松覆盖基值(每个环境)至关重要。
这些参数还需要与调用它们的模型紧密耦合,因此初始化程序和全局变量不是一个选项。
如果有人有更好的方式以更优雅的方式实现这些目标,我很想听听。这段代码不是很好的 idomatic 设计,所以我希望得到一些其他的想法,比如强大的 oop 方法。
class Paramz
def initialize(params)
@env = :development # Rails.env.to_sym
@params = params
end
def get(values)
eval_hash(values.split("."))
end
protected
def eval_hash(values)
new_val = String.new
values.map { |v| new_val = new_val + "[:#{v}]" }
base, env = eval("@params[:base]" + new_val), eval("@params[@env]" + new_val)
return env != {} ? env : base
end
end
p = Hash.new{ |h,k| h[k] = Hash.new(&h.default_proc) }
# file config
p[:base][:file][:path] = "/opt/files"
p[:qa][:file][:path] = "c:\\files\\"
p[:production][:file][:path] = "/opt/projects/final"
params = Paramz.new(p)
# env = :base
puts params.get("file.path")
# >> "/opt/files" # returns :base config
# env = :development
# puts params.get("file.path")
# >> "/opt/files" # no :development config, falls back on :base
# env = :production
# puts params.get("file.path")
# >> "/opt/projects/final" # return :production config