我如何删除 Ruby DSL 中的重复部分
How could I remove duplicated sections in Ruby DSL
我目前的配置格式似乎太多余了。我怎样才能将它转换成下一个预期的配置格式?
我的预期配置是:
MoneyRails.configure do |config|
register_currency("TWD", 100)
register_currency("USD", 100)
....
end
我当前的配置是:
MoneyRails.configure do |config|
config.register_currency = {
:priority => 1,
:iso_code => "TWD",
:name => "TWD",
:symbol => "NT$ ",
:symbol_first => true,
:subunit => "Subcent",
:subunit_to_unit => 100,
:thousands_separator => ",",
:decimal_mark => "."
}
config.register_currency = {
:priority => 1,
:iso_code => "USD",
:name => "USD",
:symbol => "$ ",
:symbol_first => true,
:subunit => "Subcent",
:subunit_to_unit => 100,
:thousands_separator => ",",
:decimal_mark => "."
}
config.register_currency = {
:priority => 1,
:iso_code => "SGD",
:name => "SGD",
:symbol => "$ ",
:symbol_first => true,
:subunit => "Subcent",
:subunit_to_unit => 100,
:thousands_separator => ",",
:decimal_mark => "."
}
config.register_currency = {
:priority => 1,
:iso_code => "THB",
:name => "THB",
:symbol => "$ ",
:symbol_first => true,
:subunit => "Subcent",
:subunit_to_unit => 100,
:thousands_separator => ",",
:decimal_mark => "."
}
config.register_currency = {
:priority => 1,
:iso_code => "AUD",
:name => "AUD",
:symbol => "$ ",
:symbol_first => true,
:subunit => "Subcent",
:subunit_to_unit => 100,
:thousands_separator => ",",
:decimal_mark => "."
}
config.register_currency = {
:priority => 1,
:iso_code => "KRW",
:name => "KRW",
:symbol => "$ ",
:symbol_first => true,
:subunit => "Subcent",
:subunit_to_unit => 100,
:thousands_separator => ",",
:decimal_mark => "."
}
...
end
创建这个小模块怎么样?您只需要在配置对象中添加一个额外的属性:
module MoneyRails
module MyApp
def register_currency(config, name, subunit_to_unit)
config.register_currency(options_hash(name, subunit_to_unit))
end
private
def options_hash(name, subunit_to_unit)
{
:priority => 1,
:iso_code => name,
:name => name,
:symbol => "$ ",
:symbol_first => true,
:subunit => "Subcent",
:subunit_to_unit => subunit_to_unit,
:thousands_separator => ",",
:decimal_mark => "."
}
end
end
end
请注意,我对其命名空间是为了不污染基本命名空间。将其更改为您的休闲。
然后:
include MoneyRails::MyApp
MoneyRails.configure do |config|
register_currency(config, "TWD", 100)
register_currency(config, "USD", 100)
....
end
default_options = {
:priority => 1,
:iso_code => 'USD',
:name => 'USD',
:symbol => "$ ",
:symbol_first => true,
:subunit => "Subcent",
:subunit_to_unit => 100,
:thousands_separator => ",",
:decimal_mark => "."
}
MoneyRails.configure do |config|
config.register_currency = default_options
config.register_currency = default_options.merge(name: 'TWD', iso_code: 'TWD', symbol: 'NT$')
config.register_currency = default_options.merge(name: 'THB', iso_code: 'THB')
config.register_currency = default_options.merge(name: 'SGD')
end
merge
方法合并两个 Hash 实例和 returns 一个 Hash 对象。如果第二个 Hash 对象有一些键与第一个匹配,那么第二个 Hash 的 key => value
replaces/overrides 前一个。
例外情况相对较少,所以我倾向于将它们放在一个文件中,每种货币一行,连同货币名称缩写。例如,一行可能是:
TWD SYM:"NT$ "
(或 TWD SYM:NT$
如果 :symbol
的所有值最后都有一个 space)。
大多数行只有货币缩写,例如:
USD
然后您将读取该文件并将其解析为如下数组:
specific_bits = [
["TWD", { symbol: "NT$ " }],
["USD", {}],
["SGD", {} ],
["THB", { subunit_to_unit: 999 }],
["AUD", {}],
["KRW", {}],
["XYZ", { symbol: "XT$ ", subunit_to_unit: -5 }],
]
然后定义:
BASE_HASH = {
priority: 1,
symbol: "$ ",
symbol_first: true,
subunit: "Subcent",
subunit_to_unit: 100,
thousands_separator: ",",
decimal_mark: "."
}
这使您可以非常简单地构建哈希:
specific_bits.map do |name, exceptions|
h = { :iso_code => name, :name => name }
exceptions.each { |k,v| h[k] = v }
BASE_HASH.merge h
end
#=> [{:priority=>1, :symbol=>"NT$ ", :symbol_first=>true, :subunit=>"Subcent",
# :subunit_to_unit=>100, :thousands_separator=>",", :decimal_mark=>".",
# :iso_code=>"TWD", :name=>"TWD"},
# {...
# ...]
如果您希望按键按特定顺序排列,这是一个小调整。
我目前的配置格式似乎太多余了。我怎样才能将它转换成下一个预期的配置格式?
我的预期配置是:
MoneyRails.configure do |config|
register_currency("TWD", 100)
register_currency("USD", 100)
....
end
我当前的配置是:
MoneyRails.configure do |config|
config.register_currency = {
:priority => 1,
:iso_code => "TWD",
:name => "TWD",
:symbol => "NT$ ",
:symbol_first => true,
:subunit => "Subcent",
:subunit_to_unit => 100,
:thousands_separator => ",",
:decimal_mark => "."
}
config.register_currency = {
:priority => 1,
:iso_code => "USD",
:name => "USD",
:symbol => "$ ",
:symbol_first => true,
:subunit => "Subcent",
:subunit_to_unit => 100,
:thousands_separator => ",",
:decimal_mark => "."
}
config.register_currency = {
:priority => 1,
:iso_code => "SGD",
:name => "SGD",
:symbol => "$ ",
:symbol_first => true,
:subunit => "Subcent",
:subunit_to_unit => 100,
:thousands_separator => ",",
:decimal_mark => "."
}
config.register_currency = {
:priority => 1,
:iso_code => "THB",
:name => "THB",
:symbol => "$ ",
:symbol_first => true,
:subunit => "Subcent",
:subunit_to_unit => 100,
:thousands_separator => ",",
:decimal_mark => "."
}
config.register_currency = {
:priority => 1,
:iso_code => "AUD",
:name => "AUD",
:symbol => "$ ",
:symbol_first => true,
:subunit => "Subcent",
:subunit_to_unit => 100,
:thousands_separator => ",",
:decimal_mark => "."
}
config.register_currency = {
:priority => 1,
:iso_code => "KRW",
:name => "KRW",
:symbol => "$ ",
:symbol_first => true,
:subunit => "Subcent",
:subunit_to_unit => 100,
:thousands_separator => ",",
:decimal_mark => "."
}
...
end
创建这个小模块怎么样?您只需要在配置对象中添加一个额外的属性:
module MoneyRails
module MyApp
def register_currency(config, name, subunit_to_unit)
config.register_currency(options_hash(name, subunit_to_unit))
end
private
def options_hash(name, subunit_to_unit)
{
:priority => 1,
:iso_code => name,
:name => name,
:symbol => "$ ",
:symbol_first => true,
:subunit => "Subcent",
:subunit_to_unit => subunit_to_unit,
:thousands_separator => ",",
:decimal_mark => "."
}
end
end
end
请注意,我对其命名空间是为了不污染基本命名空间。将其更改为您的休闲。
然后:
include MoneyRails::MyApp
MoneyRails.configure do |config|
register_currency(config, "TWD", 100)
register_currency(config, "USD", 100)
....
end
default_options = {
:priority => 1,
:iso_code => 'USD',
:name => 'USD',
:symbol => "$ ",
:symbol_first => true,
:subunit => "Subcent",
:subunit_to_unit => 100,
:thousands_separator => ",",
:decimal_mark => "."
}
MoneyRails.configure do |config|
config.register_currency = default_options
config.register_currency = default_options.merge(name: 'TWD', iso_code: 'TWD', symbol: 'NT$')
config.register_currency = default_options.merge(name: 'THB', iso_code: 'THB')
config.register_currency = default_options.merge(name: 'SGD')
end
merge
方法合并两个 Hash 实例和 returns 一个 Hash 对象。如果第二个 Hash 对象有一些键与第一个匹配,那么第二个 Hash 的 key => value
replaces/overrides 前一个。
例外情况相对较少,所以我倾向于将它们放在一个文件中,每种货币一行,连同货币名称缩写。例如,一行可能是:
TWD SYM:"NT$ "
(或 TWD SYM:NT$
如果 :symbol
的所有值最后都有一个 space)。
大多数行只有货币缩写,例如:
USD
然后您将读取该文件并将其解析为如下数组:
specific_bits = [
["TWD", { symbol: "NT$ " }],
["USD", {}],
["SGD", {} ],
["THB", { subunit_to_unit: 999 }],
["AUD", {}],
["KRW", {}],
["XYZ", { symbol: "XT$ ", subunit_to_unit: -5 }],
]
然后定义:
BASE_HASH = {
priority: 1,
symbol: "$ ",
symbol_first: true,
subunit: "Subcent",
subunit_to_unit: 100,
thousands_separator: ",",
decimal_mark: "."
}
这使您可以非常简单地构建哈希:
specific_bits.map do |name, exceptions|
h = { :iso_code => name, :name => name }
exceptions.each { |k,v| h[k] = v }
BASE_HASH.merge h
end
#=> [{:priority=>1, :symbol=>"NT$ ", :symbol_first=>true, :subunit=>"Subcent",
# :subunit_to_unit=>100, :thousands_separator=>",", :decimal_mark=>".",
# :iso_code=>"TWD", :name=>"TWD"},
# {...
# ...]
如果您希望按键按特定顺序排列,这是一个小调整。