Last active
August 29, 2015 14:10
-
-
Save structuralartistry/dc4b06dbfa75a1233f72 to your computer and use it in GitHub Desktop.
Making constants consistent and mungeable in tests
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# config/initializers/app_config.rb | |
APP_CONFIG = AppConfig.new(YAML.load_file("#{Rails.root}/config/application.yml")[Rails.env]) | |
# then you have application.yml or whatever you want to call it: | |
# config/application.yml (or some better name) | |
development: | |
<<: *defaults | |
default_audio_file_format: m4a | |
media_path: 'public/media/development' | |
media_path_clips: 'public/media/development/clips' | |
staging: | |
... | |
production: | |
... | |
# usage | |
# when need a constant, just use: | |
APP_CONFIG.constant_name | |
# of course the above works only for top level in the yml but nested you can still get | |
APP_CONFIG.constant_tree_name[:sub_value_one][:sub_value_two] | |
# ... in fact I think we could also make this more 'treeable' and have it traverse the yml and actually give us nested objects with a little bit of work, like: | |
APP_CONFIG.constant_tree_name.sub_value_one.sub_value_two | |
# whats cool about this is that it not only makes constants more consistent and easily 'seeable' from one file (vs in the environment files), but it also (and this is why I started doing it this way), allows us to easily change constant values for testing: | |
APP_CONFIG.stub(:constant_name).and_return('blah') | |
# the app config class file | |
# lib/app_config.rb (or whatever) | |
# this creates a class which will take hash from yaml application.yml file and simulate an | |
# instance method for each top level setting... this facilitates stubbing in tests | |
# class << hsh; def []=(key,val); return 'xxxx'; end; end; | |
class AppConfig | |
def initialize(hash) | |
hash.stringify_keys! | |
# dynamic should be regular hash, updatable | |
@dynamic = hash['dynamic'] || {} | |
hash.delete('dynamic') | |
# static uses AppConfigHash so we can control the setter | |
freeze_hash(hash) | |
@settings = hash | |
end | |
def dynamic | |
@dynamic | |
end | |
private | |
def method_missing(meth, *args, &block) | |
return @settings[meth.to_s] | |
end | |
def freeze_hash(hash) | |
disable_hash_setter(hash) | |
hash.each do |key, value| | |
if hash[key].is_a?(Hash) | |
freeze_hash(value) | |
end | |
end | |
end | |
def disable_hash_setter(hash) | |
class << hash | |
def []=(key,val) | |
raise 'Can not overwrite non-dynamic AppConfig constant!' | |
end | |
end | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment