Carolyn Grant wrote in post #1083906:
basic_config = MySettings.new # Picks up & processes basic_config.yml
adv_config = MySettings.new # Picks up & processes adv_config.yml
In general it doesn’t make any sense for an object to know its “name”,
because an object may have zero or many names at any time. You can
assign the object reference to local variables, to global variables, to
instance variables of other objects, to constants, as elements of an
Array or Hash, etc.
In the above code, the object created by MySettings.new has no name at
the time it is created. Only after the #new function has returned the
object reference, it is assigned to the local variable.
So for the code you are writing above, I would strongly advise passing
the filename (or filename stem) as an argument:
basic_config = MySettings.new(“basic_config.yaml”)
adv_config = MySettings.new(“adv_config.yaml”)
Of course, as with many things in Ruby, there is an exception. The
exception is to do with class objects; that is, objects of class Class.
Normally classes are held in constants, and the first time a class is
assigned to a constant, it learns its name, and the name becomes an
attribute of the class itself.
A class definition like “class Foo” both creates the class and assigns
it to a constant, but you can see the behaviour if you first create an
anonymous class, and then later assign it to a constant.
foo = Class.new
=> #Class:0x106c91650
my_instance = foo.new
=> #<#Class:0x106c91650:0x106c8e6f8>
Bar = foo
=> Bar
foo
=> Bar
my_instance
=> #Bar:0x106c8e6f8
Baz = foo
=> Bar
foo
=> Bar
my_instance
=> #Bar:0x106c8e6f8
I tried my_class.name; that returns a “Method not defined” error" (I’m
using 1.9.3p194)
You’ll have to show the code. I use ruby 1.8, but it works fine for me.
Notice that “name” is a method of the class, not the instance, and is
only for Class objects because of the special-case behaviour described
above.
foo.name
=> “Bar”
my_instance.class.name
=> “Bar”
my_instance.name
NoMethodError: undefined method `name’ for #Bar:0x106c8e6f8
from (irb):11
What I’d really like to avoid is:
basic_config = MySettings.new(basic_config).
Why? It seems you want to create “magic” which will be very difficult
for another programmer to follow. When you create an object, you should
pass all the data which will be used to create state in that object, and
you should allow the caller to decide what to do with the returned
object.
The closest I could recommend is if you have a single config object
which holds all the sub-configs e.g. a hash. Then a single method
argument can say which file to load and which hash member to put it
in. For example:
require ‘yaml’
class Configs
def initialize
@configs = {}
end
def load(stem)
@configs[stem] = File.open("#{stem}.yaml") do |f|
YAML.load(f)
end
end
def
@configs[stem]
end
end
config = Configs.new
config.load “basic_config”
config.load “adv_config”
puts config[“basic_config”].inspect
Of course, if you want the config to be globally accessible throughout
your application, then you can assign it to a constant instead of a
local variable.
Config = Configs.new
Config.load “basic_config”
Config.load “adv_config”
puts Config[“basic_config”].inspect
Or you could use a global variable, but a constant is generally
preferred. Constants can be put into namespaces, e.g. MyApp::Config, to
avoid clashes with other uses of Config.