Reputation: 2199
I've created a class that I'm using to store configuration data. Currently the class looks like this:
class Configed
@@username = "[email protected]"
@@password = "password"
@@startpage = "http://www.example.com/login"
@@nextpage = "http://www.example.com/product"
@@loginfield = "username"
@@passwordfield = "password"
@@parser = "button"
@@testpage = "http://www.example.com/product/1"
@@button1 = "button1"
def self.username
@@username
end
def self.password
@@password
end
def self.startpage
@@startpage
end
def self.nextpage
@@nextpage
end
def self.loginfield
@@loginfield
end
def self.passwordfield
@@passwordfield
end
def self.parser
@@parser
end
def self.testpage
@@testpage
end
def self.button1
@@button1
end
end
To access the variables I'm using:
# Config file
require_relative 'Configed'
# Parse config
startpage = Configed.startpage
loginfield = Configed.loginfield
passwordfield = Configed.passwordfield
username = Configed.username
password = Configed.password
nextpage = Configed.nextpage
parser = Configed.parser
testpage = Configed.testpage
This is not very modular. Adding additional configuration data needs to be referenced in three places.
Is there a better way of accomplishing this?
Upvotes: 1
Views: 49
Reputation: 36860
You can make class level instance variables...
class Configed
@username = "[email protected]"
@password = "password"
@startpage = "http://www.example.com/login"
# ...
class << self
attr_reader :username, :password, :startpage # ...
end
end
It's somewhat more compact, and still gives you
username = Configed.username
# ...
NOTE: there's a lot of good ideas in @philomory 's answer that deserves consideration. The use of YAML in particular would allow you to set up different constants for different environemnts test
, development
, production
etc, and you can load the current environment's configuration options into an OpenStruct created in an initializer. Makes for a more flexible solution.
Upvotes: 4
Reputation: 1767
There are a lot of potential improvements. First of all, no reason to use class variables if you don't want their weird specific inheritance-related behavior, and no reason to use a class at all if you're not going to instantiate it.
You could use a module:
module Configed
module_function
def username
'username'
end
# etc
end
Configed.username
But frankly, you're almost certainly better off using a hash:
Config = {
username: 'username'
# etc
}.freeze
Config[:username]
or, if you prefer method-style access, an OpenStruct:
require 'openstruct' # from standard library
Config = OpenStruct.new(
username: 'username'
# etc
).freeze
Config.username
If they need to be modifiable, just don't freeze
them. Also, typically a constant which is not a class or a module (such as a hash) would have a name in ALL_CAPS, e.g. CONFIGED
, but, that's a stylistic decision with no actual impact on the code.
Your question refers to 'parsing' the config, but of course, you're not; the config data in your setup (and in my examples so far) is just Ruby code. If you'd rather load it from a non-code file, there's always YAML:
config.yaml:
username: username
password: password
config.rb:
require 'yaml' # from Standard Library
Configed = YAML.load_file('config.yaml')
Configed['username']
or JSON:
config.json:
{
"username": "username",
"password": "password"
}
config.rb:
require 'json' # from Standard Library
Configed = JSON.parse(File.read('config.json'))
Configed['username']
Upvotes: 3