I am making a program that will load settings from a config file. I am
thinking of the best way to implement this. One idea is that the main
file could simply set constants that are equal to values loaded from
the config file, then I could use those constants in the sections of
code where user configurable settings are relevant.
Another option would be to directly load from the config file in each of
the methods that need to get user set variables, and set these variables
as regular local variables internal to the individual methods.
I can see advantages and disadvantages to each technique.
I’d use a single constant (like CONFIG), which holds a special object
representing the configuration values. This allows you to encapsulate
the technical stuff (file opening, parsing etc.) in the object.
Setting a constant for every value may be the second best possibilty, if
you put them into a module. But personally I don’t like dynamically
created constants.
To load the values directly seems like a bad idea. First of all, it’s
inefficient. And it forces you to deal with the file stuff again and
again – this also makes the program very inflexible, because you’d have
to change all the methods if anything changes about the configuration
file.
if your program is also going to have some kind of settings manager,
so that the user can change various settings, you probably don’t want
constants - but rather variables. i’d put all of the settings into a
module, that you later include in your main file. this way, if the
settings module is called Settings, and you have a variable in that
module called @volume, you can just call Settings.volume in the main
file to get the value.
keep in mind that you’ll also want to write in some way to create
default settings and a new settings file in case the original settings
file somehow goes missing…
I don’t think a module is the right choice. Your code relies on the
programmer calling the “read” method before he reads or sets any value.
If he doesn’t, he’ll get strange errors.
I find these implicit dependencies rather confusing. It’s probably
better to use an actual object which has the setup procedure in its
initialize method.
Also I wouldn’t use an array to store the settings, because this is
rather error prone.
def initialize
begin
# parse file @settings = ‘<FILE_CONTENT>’
rescue @settings = DEFAULT_SETTINGS
save!
end
end
def save!
# write settings to file
end
getters and setters
DEFAULT_SETTINGS.each_key do |config_key|
define_method config_key do
DEFAULT_SETTINGS[config_key]
end
define_method “#{config_key}=” do |val|
DEFAULT_SETTINGS[config_key] = val
end
end
DEFAULT_SETTINGS.each_key do |config_key|
define_method config_key do
DEFAULT_SETTINGS[config_key]
end
define_method “#{config_key}=” do |val|
DEFAULT_SETTINGS[config_key] = val
end
end
I think you mean @settings, not DEFAULT_SETTINGS?
Also I would be inclined to do
@settings = DEFAULT_SETTINGS.dup
and to freeze DEFAULT_SETTINGS
But it may be simpler to do:
begin
Settings = YAML.load(“<settings_path>”)
rescue
Set defaults
Settings = {“foo”=>123, “bar”=>456}
end
If you want the accessor methods, you could use an OpenStruct, or this:
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.