在Rails中加载YML文件,并且可能改用i18n文件

时间:2019-03-20 17:03:44

标签: ruby-on-rails yaml rails-i18n ruby-on-rails-5.2

我有一个dropdown.yml文件,用于存储表单中多选字段的所有下拉值。它不依赖于环境,所以我没有:development,:production等。

我想将文件缓存到一个常量中,以便可以在我的应用程序中使用。我找到了这个命令。

config = Rails.application.config_for(:payment)

但是,它看起来像是取决于环境的。添加yml的最佳方法是什么?

第二,我应该为此使用语言环境而不是自定义的yml文件吗?

config / dropdown.yml

dropdown:
  car_model:
    field1:
      yes: true
       no: false
    region:
      US: United States
      CA: Canada

还可以通过多个名称访问下拉菜单吗?

dropdown:
  car_model| truck_model| bike_model:
    field1:
      yes: true
       no: false
    region:
      US: United States
      CA: Canada

这样我就可以从任何名称键car_model,truck_model或bike_model中引用field1了?

2 个答案:

答案 0 :(得分:1)

将其加载到您的application.rb中的配置块内:

class Application < Rails::Application
  ...
  config.dropdowns = HashWithIndifferentAccess.new(YAML.load_file(File.join(Rails.root, 'config', 'dropdown.yml')))
  ...
end

通过`Rails.application.config.dropdown [:key]

在代码中使用

注意:我会放下顶层的下拉键,或者在加载行的末尾添加它,这样就不需要在每次需要配置时都调用它。例如

HashWithIndifferentAccess.new(YAML.load_file(File.join(Rails.root, 'config', 'dropdown.yml')))[:dropdown]

也可以在应用程序中将其固定为常量。rb:

MY_CONST = HashWithIndifferentAccess.new(YAML.load_file(File.join(Rails.root, 'config', 'dropdown.yml')))

答案 1 :(得分:1)

我想我会为此制作一个实用程序类和模块。像这样:

module DropdownExt

  def self.extended(receiver)
    receiver.each do |k,v|
      define_method(k) do 
        v.is_a?(Hash) ? v.extend(DropdownExt) : v
      end
    end
  end

end

class Dropdowns

  class << self

    private

    def dropdowns_spec
      YAML.load_file("#{path}").with_indifferent_access
    end

    def path
      Rails.root.join("spec/so/dropdowns/dropdowns.yaml") # <== you'll need to change this
    end

  end

  dropdowns_spec[:dropdown].each do |k,v|
    define_singleton_method k do 
      v.extend(DropdownExt)
    end
  end

  %i(
    truck_model
    bike_model
  ).each do |to_alias|
    singleton_class.send(:alias_method, to_alias, :car_model)
  end

end

然后您可以做:

Dropdowns.car_model
 => {"field1"=>{true=>"true", false=>"false"}, "region"=>{"US"=>"United States", "CA"=>"Canada"}}
Dropdowns.truck_model
 => {"field1"=>{"yes"=>"true", "no"=>"false"}, "region"=>{"US"=>"United States", "CA"=>"Canada"}}
Dropdowns.bike_model
 => {"field1"=>{"yes"=>"true", "no"=>"false"}, "region"=>{"US"=>"United States", "CA"=>"Canada"}}

随你喜欢。

您会发现我使用自定义DropdownExt扩展了模型哈希,因此您也可以这样做:

Dropdowns.car_model.field1
 => {"yes"=>"true", "no"=>"false"}
Dropdowns.car_model.field1.yes 
 => "true"
Dropdowns.car_model.region.US
 => United States

在实例上执行extend(SomeModule)时,模块只会扩展该实例,因此您不会污染整个应用程序中的Hash(在这种情况下)。

IMO,使用config似乎有点低级。但是,我意识到这是个人喜好问题。另外,这将为您节省一些打字输入。

此方法的另一个优点是您可以“免费”获得每个模型的类方法。因此,您可以这样做:

Dropdowns.car_model

代替

Rails.application.config.dropdown[:car_model]

我不知道。这对我来说似乎更好。

最后,我想我喜欢将整个内容封装在一个类中。同样,个人喜好问题。但是,这对我来说似乎更像红宝石。

顺便说一句,我的YAML希望将您的yesno更改为truefalse。所以,我做到了:

---
dropdown:
  car_model:
    field1:
      'yes':  'true'
      'no':   'false'
    region:
      US: United States
      CA: Canada

哪个回来了

{"field1"=>{"yes"=>"true", "no"=>"false"}, "region"=>{"US"=>"United States", "CA"=>"Canada"}}