【问题标题】:How could I remove duplicated sections in Ruby DSL如何删除 Ruby DSL 中的重复部分
【发布时间】:2015-11-01 13:51:51
【问题描述】:

我当前的配置格式似乎太多余了。如何将其转换为下一个预期的配置格式?

我的预期配置是:

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

【问题讨论】:

  • 欢迎来到 Stack Overflow。当您尝试从当前版本减少到所需版本时发生了什么?我看没问题,只是一个愿望清单。我们希望了解您尝试执行的操作以及您对其无法正常工作的原因的解释。

标签: ruby money-rails


【解决方案1】:
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 实例并返回一个 Hash 对象。如果第二个 Hash 对象有一些与第一个匹配的键,则第二个 Hash 的 key => value 替换/覆盖前一个。

【讨论】:

    【解决方案2】:

    创建这个小模块怎么样?你只需要为你的配置对象添加一个额外的属性:

    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
    

    【讨论】:

    • 你正在通过class方法方式访问instance方法
    【解决方案3】:

    例外情况相对较少,所以我倾向于将它们放在一个文件中,每个货币一行,以及货币名称缩写。例如,一行可能是:

    TWD SYM:"NT$ "
    

    (或TWD SYM:NT$,如果:symbol 的所有值末尾都有一个空格)。

    大多数行只有货币缩写,例如:

    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"},
      #    {...
      #    ...]
    

    如果您希望按键按特定顺序排列,这是一个小调整。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-25
      • 2010-12-08
      • 2015-12-04
      • 2017-12-26
      • 1970-01-01
      相关资源
      最近更新 更多