Loading a YML file in Rails, and maybe using a i18n file instead

血红的双手。 提交于 2019-12-11 09:32:05

问题


I have a dropdown.yml file that stores all my dropdown values for my multi-select fields in my forms. It is not environment dependent, so I do not have :development, :production, etc.

I would like cache the file into a constant so I can use across my app. I found this command.

config = Rails.application.config_for(:payment)

However, it looks like it is environment dependent. What is the best way to add the yml?

Second, should I use locales for this instead of a custom yml file?

config/dropdown.yml

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

Also, is there a way to have a dropdown accessible from multiple names?

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

So that I could reference field1, from any of the name keys, car_model, truck_model, or bike_model?


回答1:


I think I would make a utility class and module for this. Something like:

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

Then you can do:

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"}}

Wherever you like.

You'll notice I extended the model hash with a custom DropdownExt, so you can also do:

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

When you do extend(SomeModule) on an instance, then only that instance is extended with the module so you don't polute Hash (in this case) throughout your entire application.

IMO, using config seems a little too low-level. But, I realize that's a matter of personal preference. Also, this will save you a little typing.

Another advantage of this approach is that you get the class methods for each of your models "for free". So you can do:

Dropdowns.car_model

instead of

Rails.application.config.dropdown[:car_model]

I don't know. That just seems nicer to me.

Finally, I guess I like encapsulating the whole thing in a class. Again, a matter of personal preference. But, that seems more ruby-ish to me.

BTW, my YAML was wanting to change your yes and no to true and false. So, I did:

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

Which returned

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



回答2:


Load it in your application.rb, inside the config block:

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

use in code via `Rails.application.config.dropdown[:key]

note: I would drop the top level dropdown key, or add that on the end of the load line so you don't need to invoke it every time you want the config. e.g.

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

Could also just chuck it in a constant in your application.rb:

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


来源:https://stackoverflow.com/questions/55266413/loading-a-yml-file-in-rails-and-maybe-using-a-i18n-file-instead

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!