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?
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"}}
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')))