What is a DRY way to read options from a configuration file to be used in multiple classes?
I have some configuration options for a program stored in a JSON file. I want to be able to access the options in several different classes without explicitly having to open the file and read the configuration in each class. Is there a good, DRY way to do this?
I tried creating a module which reads the configuration into a class variable, and just include the module in every class, but is this a good use of class variables? Reading this makes me wary of class variables.
Here is what I have right now:
module Config
@@config = nil
def self.included(base)
if @@config.nil?
open('config.json', 'r') { |f| @@config = JSON.load(f) }
end
end
end
Thanks!
Update:
Maybe it's better just to place all the classes that require the configuration under it's own namespace?
module MyFishTank
Config = { "lo开发者_开发知识库cation" => "My room" }
Class Fish
def location
Config['location']
end
end
end
fish = MyFishTank::Fish.new
puts fish.location #=> "My room"
You could look at how others have tried to solve this problem also. For example check out RConfig
or Configatron
.
In my last project I used Configatron, and quite liked it, but I think for the next project I'm going to give RConfig a shot. Configatron may have a bit too much magic built into it, and RConfig looks like a more straight forward solution.
You could also use them as a base. I think you cold add JSON support to RConfig quite easily, and have a generalized config solution from there for future projects too...
RConfig:
https://github.com/rahmal/rconfig
Configatron:
https://github.com/markbates/configatron
Why not something like this:
module Configured
def config
# memoize config upon load
@config ||= 'foo'
end
end
class A
extend Configured
def initialize
puts A.config # or
puts self.class.config
end
end
A.new
#=> foo
Edit: if you want to avoid class method invocation (which seems wrong to me, as the configuration is indeed class-wide, not instance-wide), you can do something like:
module Configured
def self.included(base)
base.define_singleton_method :config do
@config ||= 'foo'
end
end
def config
self.class.config
end
end
class A
include Configured
def initialize
puts config
end
end
A.new
Though there probably is more succinct way of doing it.
精彩评论