configure_me 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +21 -0
- data/.rspec +3 -0
- data/Gemfile +2 -0
- data/README.md +112 -0
- data/Rakefile +24 -0
- data/configure_me.gemspec +30 -0
- data/features/memory.feature +16 -0
- data/features/step_definitions/base_steps.rb +33 -0
- data/lib/configure_me.rb +13 -0
- data/lib/configure_me/base.rb +40 -0
- data/lib/configure_me/caching.rb +25 -0
- data/lib/configure_me/nesting.rb +36 -0
- data/lib/configure_me/persistence.rb +34 -0
- data/lib/configure_me/setting.rb +16 -0
- data/lib/configure_me/settings.rb +94 -0
- data/lib/configure_me/version.rb +3 -0
- data/lib/generators/configure_me_generator.rb +19 -0
- data/lib/generators/templates/initializer.rb +1 -0
- data/lib/generators/templates/migration.rb +16 -0
- data/lib/generators/templates/model.rb +2 -0
- data/spec/configure_me/base_spec.rb +108 -0
- data/spec/configure_me/setting_spec.rb +23 -0
- data/spec/spec_helper.rb +10 -0
- metadata +205 -0
data/.gitignore
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
pkg/*
|
2
|
+
*.gem
|
3
|
+
.bundle
|
4
|
+
config/database.yml
|
5
|
+
config/*.sphinx.conf
|
6
|
+
*~
|
7
|
+
*.cache
|
8
|
+
*.log
|
9
|
+
autotest
|
10
|
+
*.pid
|
11
|
+
tmp/**/*
|
12
|
+
.DS_Store
|
13
|
+
db/*.sqlite3
|
14
|
+
doc/api
|
15
|
+
doc/app
|
16
|
+
doc/plugins
|
17
|
+
doc/*.dot
|
18
|
+
coverage/*
|
19
|
+
*.sw?
|
20
|
+
vendor/plugins/ns_web
|
21
|
+
Gemfile.lock
|
data/.rspec
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
## ConfigureMe
|
2
|
+
|
3
|
+
A really simple gem for helping to manage dynamic application configuration.
|
4
|
+
|
5
|
+
### Installation
|
6
|
+
gem "configure_me"
|
7
|
+
|
8
|
+
### Usage
|
9
|
+
Using ConfigureMe is easy. First, derive a class from ConfigureMe::Base. Then define your settings just as you would attributes.
|
10
|
+
|
11
|
+
class AppConfig < ConfigureMe::Base
|
12
|
+
setting :timeout
|
13
|
+
setting :max_items
|
14
|
+
end
|
15
|
+
|
16
|
+
Settings can also be given default values:
|
17
|
+
|
18
|
+
class AppConfig < ConfigureMe::Base
|
19
|
+
setting :min_password_length, :default => 8
|
20
|
+
end
|
21
|
+
|
22
|
+
To access the settings, just reference the class's *instance* method, followed by the name of the setting:
|
23
|
+
|
24
|
+
# AppConfig.instance.min_password_length
|
25
|
+
=> 8
|
26
|
+
|
27
|
+
Changes to the configuration are made the same way:
|
28
|
+
|
29
|
+
# AppConfig.instance.min_password_length = 6
|
30
|
+
=> 6
|
31
|
+
# AppConfig.instance.min_password_length
|
32
|
+
=> 6
|
33
|
+
|
34
|
+
### Nesting
|
35
|
+
You can also nest configuration classes. To nest one config under another, just call *nest_me* from inside the nested class, passing it the class you would like to nest it under. When an instance of the parent class is created, an instance of the nested class will be instantiated at the same time.
|
36
|
+
|
37
|
+
class MainConfig < ConfigureMe::Base
|
38
|
+
setting :site_name, :default => "Ninja Robot Monkeys"
|
39
|
+
end
|
40
|
+
|
41
|
+
class ExtensionConfig < ConfigureMe::Base
|
42
|
+
nest_me(MainConfig)
|
43
|
+
setting :secret_weapon, :default => "throwing star"
|
44
|
+
end
|
45
|
+
|
46
|
+
# MainConfig.instance.extension.secret_weapon
|
47
|
+
=> "throwing star"
|
48
|
+
|
49
|
+
The default behaviour when nesting is to use the name of the nested class (excluding "Config") to create the accessor method. To override this behavior, just pass the alternate name to *nest_me*
|
50
|
+
|
51
|
+
class ExtensionConfig < ConfigureMe::Base
|
52
|
+
nest_me MainConfig, 'altextension'
|
53
|
+
...
|
54
|
+
end
|
55
|
+
|
56
|
+
# AppConfig.instance.altextension.secret_weapon
|
57
|
+
=> "throwing star"
|
58
|
+
|
59
|
+
## Persisting
|
60
|
+
An easily editable configuration doesn't do any good without persisting it. To store our configuration settings in the database, we need to generate an ActiveRecord model to store our settings.
|
61
|
+
|
62
|
+
# rails g configure_me Setting
|
63
|
+
|
64
|
+
This will create a model/migration, and an initializer to let ConfigureMe know what model it should use for persisting. You can call the model whatever you want, so long as you pass the correct name in the initializer. All that's left is to tell ConfigureMe to actually persist our configuration. And its a one-liner:
|
65
|
+
|
66
|
+
class AppConfig < ConfigureMe::Base
|
67
|
+
...
|
68
|
+
persist_me
|
69
|
+
end
|
70
|
+
|
71
|
+
Now, when updating any setting, the new value will be written to the database as well as stored in memory. Settings are converted to YAML before being written, so complex values can be stored. When accessing a setting, the database is always consulted first, and if no value is stored, the default is returned or, if no default was specified, nil.
|
72
|
+
|
73
|
+
## Caching
|
74
|
+
To really crank up the performance, you can enable caching of values. If you're paying attention, the method to enable this should be obvious.
|
75
|
+
|
76
|
+
class AppConfig < ConfigureMe::Base
|
77
|
+
cache_me
|
78
|
+
end
|
79
|
+
|
80
|
+
Now, when values are accessed, the cache will be referenced before falling back to other means. If combined with *persist_me*, this can make dealing with dynamic site configuration perform much better than a database only solution.
|
81
|
+
|
82
|
+
## Putting it all together
|
83
|
+
|
84
|
+
Here's a complete configuration example:
|
85
|
+
|
86
|
+
class MainConfig < ConfigureMe::Base
|
87
|
+
persist_me
|
88
|
+
cache_me
|
89
|
+
|
90
|
+
setting :site_name
|
91
|
+
setting :admin_email
|
92
|
+
setting :theme, :default => 'spacecadet'
|
93
|
+
end
|
94
|
+
|
95
|
+
class UserConfig < ConfigureMe::Base
|
96
|
+
nest_me(MainConfig)
|
97
|
+
persist_me
|
98
|
+
cache_me
|
99
|
+
|
100
|
+
setting :min_username, :default => 8
|
101
|
+
setting :min_password, :default => 8
|
102
|
+
end
|
103
|
+
|
104
|
+
With this setup, we'll have access to a total of 5 configuration options:
|
105
|
+
|
106
|
+
AppConfig.instance.site_name
|
107
|
+
AppConfig.instance.admin_email
|
108
|
+
AppConfig.instance.theme
|
109
|
+
AppConfig.instance.user.min_username
|
110
|
+
AppConfig.instance.user.min_password
|
111
|
+
|
112
|
+
All of which will be stored in the database when modified, and read from the cache when possible.
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'rake'
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
require 'cucumber'
|
8
|
+
require 'cucumber/rake/task'
|
9
|
+
|
10
|
+
RSpec::Core::RakeTask.new do |t|
|
11
|
+
t.verbose = false
|
12
|
+
end
|
13
|
+
|
14
|
+
namespace :spec do
|
15
|
+
RSpec::Core::RakeTask.new(:rcov) do |t|
|
16
|
+
t.rcov = true
|
17
|
+
t.rcov_opts = %w{--text-report --sort coverage}
|
18
|
+
t.rcov_opts << %w{--exclude gems\/,spec\/}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Cucumber::Rake::Task.new(:features) do |t|
|
23
|
+
t.cucumber_opts = 'features --format progress'
|
24
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "configure_me/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "configure_me"
|
7
|
+
s.version = ConfigureMe::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Josh Williams"]
|
10
|
+
s.email = ["theprime@codingprime.com"]
|
11
|
+
s.homepage = "http://www.github.com/t3hpr1m3/configure_me"
|
12
|
+
s.summary = %q{Simple configuration library}
|
13
|
+
s.description = %q{Simple gem to assist with persisting configuration data.}
|
14
|
+
|
15
|
+
s.rubyforge_project = "configure_me"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = %w(lib)
|
21
|
+
|
22
|
+
s.add_dependency 'activemodel', '~> 3.0.1'
|
23
|
+
s.add_dependency 'activesupport', '~> 3.0.1'
|
24
|
+
|
25
|
+
s.add_development_dependency 'rspec', '~> 2.0.1'
|
26
|
+
s.add_development_dependency 'rcov', '~> 0.9.9'
|
27
|
+
s.add_development_dependency 'mocha', '~> 0.9.8'
|
28
|
+
s.add_development_dependency 'cucumber', '~> 0.9.4'
|
29
|
+
s.add_development_dependency 'activerecord', '~> 3.0.1'
|
30
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
Feature: Store configuration in memory
|
2
|
+
In order to store configuration information
|
3
|
+
As a ruby developer
|
4
|
+
I want to create a configuration class that stores settings in memory
|
5
|
+
|
6
|
+
Scenario: Simple configuration object
|
7
|
+
Given a Configuration class that derives from ConfigureMe::Base
|
8
|
+
And I add a "color" setting with a type of "string" and a default of "red"
|
9
|
+
When I create an instance of the class
|
10
|
+
And I read the "color" setting
|
11
|
+
Then the result should be "red"
|
12
|
+
|
13
|
+
When I set the "color" setting to "blue"
|
14
|
+
And I read the "color" setting
|
15
|
+
Then the result should be "blue"
|
16
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'configure_me'
|
2
|
+
|
3
|
+
Given /^a (.*) class that derives from ConfigureMe::Base$/ do |name|
|
4
|
+
@klass = Class.new(ConfigureMe::Base)
|
5
|
+
end
|
6
|
+
|
7
|
+
Given /^I add a "([^"]*)" setting with a type of "([^"]*)" and a default of "([^"]*)"$/ do |name, type, default|
|
8
|
+
@klass.send :setting, name.to_sym, type.to_sym, :default => default
|
9
|
+
end
|
10
|
+
|
11
|
+
When /^I create an instance of the class$/ do
|
12
|
+
@obj = @klass.new
|
13
|
+
end
|
14
|
+
|
15
|
+
When /^I create another instance of the class$/ do
|
16
|
+
@obj2 = @klass.new
|
17
|
+
end
|
18
|
+
|
19
|
+
When /^I read the "([^"]*)" setting$/ do |name|
|
20
|
+
@result = @obj.send name.to_sym
|
21
|
+
end
|
22
|
+
|
23
|
+
When /^I read the new class's "([^"]*)" setting$/ do |name|
|
24
|
+
@result = @obj2.send name.to_sym
|
25
|
+
end
|
26
|
+
|
27
|
+
When /^I set the "([^"]*)" setting to "([^"]*)"$/ do |name, value|
|
28
|
+
@obj.send "#{name}=".to_sym, value
|
29
|
+
end
|
30
|
+
|
31
|
+
Then /^the result should be "([^"]*)"$/ do |value|
|
32
|
+
@result.should eql(value)
|
33
|
+
end
|
data/lib/configure_me.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'active_model'
|
2
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
3
|
+
require 'singleton'
|
4
|
+
require 'configure_me/persistence'
|
5
|
+
require 'configure_me/caching'
|
6
|
+
require 'configure_me/settings'
|
7
|
+
require 'configure_me/nesting'
|
8
|
+
|
9
|
+
module ConfigureMe
|
10
|
+
class Base
|
11
|
+
include ActiveModel::AttributeMethods
|
12
|
+
include Settings
|
13
|
+
include Persistence
|
14
|
+
include Caching
|
15
|
+
include Nesting
|
16
|
+
include Singleton
|
17
|
+
|
18
|
+
class << self
|
19
|
+
def config_name
|
20
|
+
self.name.gsub(/^(.*)Config$/, '\1').downcase
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def parent
|
25
|
+
@parent || nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def parent=(parent)
|
29
|
+
@parent = parent
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize
|
33
|
+
@children = {}
|
34
|
+
@settings = settings_from_class_settings
|
35
|
+
self.class.nested.each do |klass|
|
36
|
+
nest(klass)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module ConfigureMe
|
4
|
+
module Caching
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
@caching = false
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
def cache_me(caching_key = nil)
|
13
|
+
@caching = true
|
14
|
+
end
|
15
|
+
|
16
|
+
def caching?
|
17
|
+
@caching
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def cache_key(name)
|
22
|
+
persistence_key(name)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module ConfigureMe
|
4
|
+
module Nesting
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
@@nested = []
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
def nest_me(klass, name = nil)
|
13
|
+
klass.nest(self)
|
14
|
+
@nested_name = name || klass.config_name
|
15
|
+
end
|
16
|
+
|
17
|
+
def nested
|
18
|
+
@nested ||= []
|
19
|
+
end
|
20
|
+
|
21
|
+
def nest(klass)
|
22
|
+
nested << klass
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def nest(klass)
|
27
|
+
@children[klass.config_name] = klass.instance
|
28
|
+
klass.instance.parent = self
|
29
|
+
self.class_eval <<-EOF
|
30
|
+
def #{klass.config_name}
|
31
|
+
@children['#{klass.config_name}']
|
32
|
+
end
|
33
|
+
EOF
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module ConfigureMe
|
4
|
+
module Persistence
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
@persisting = false
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
def persist_me(persistence_key = nil)
|
13
|
+
if ConfigureMe.persistence_klass.nil?
|
14
|
+
raise ::RuntimeError, "configure_me - persistence_klass is not set. Make sure you have an initializer to assign it."
|
15
|
+
end
|
16
|
+
@persisting = true
|
17
|
+
end
|
18
|
+
|
19
|
+
def persisting?
|
20
|
+
@persisting
|
21
|
+
end
|
22
|
+
|
23
|
+
def persistence_key
|
24
|
+
self.config_name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def persistence_key(name)
|
29
|
+
key = "#{self.class.persistence_key}_#{name.to_s}"
|
30
|
+
key = @parent.persistence_key(key) unless @parent.nil?
|
31
|
+
key
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module ConfigureMe
|
2
|
+
class Setting
|
3
|
+
attr_reader :name, :default
|
4
|
+
|
5
|
+
def initialize(owner, name, *args)
|
6
|
+
options = args.extract_options!
|
7
|
+
|
8
|
+
@owner, @name = owner, name.to_s
|
9
|
+
@default = options.key?(:default) ? options[:default] : nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def define_methods!
|
13
|
+
@owner.define_attribute_methods(true)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module ConfigureMe
|
4
|
+
module Settings
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
attribute_method_suffix('', '=')
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
def setting(name, options = {})
|
13
|
+
new_setting = Setting.new(self, name, options)
|
14
|
+
class_settings[name] = new_setting
|
15
|
+
new_setting.define_methods!
|
16
|
+
end
|
17
|
+
|
18
|
+
def class_settings
|
19
|
+
@class_settings ||= {}.with_indifferent_access
|
20
|
+
end
|
21
|
+
|
22
|
+
def define_attribute_methods(force = false)
|
23
|
+
return unless class_settings
|
24
|
+
undefine_attribute_methods if force
|
25
|
+
super(class_settings.keys)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def settings_from_class_settings
|
30
|
+
self.class.class_settings.inject({}.with_indifferent_access) do |settings, (name, setting)|
|
31
|
+
settings[name] = setting.default
|
32
|
+
settings
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def read_setting(name)
|
37
|
+
if self.class.caching?
|
38
|
+
setting = Rails.cache.read(cache_key(name))
|
39
|
+
return setting unless setting.nil?
|
40
|
+
end
|
41
|
+
|
42
|
+
if self.class.persisting?
|
43
|
+
setting = ConfigureMe.persistence_klass.find_by_key(persistence_key(name))
|
44
|
+
return YAML::load(setting.value) unless setting.nil?
|
45
|
+
end
|
46
|
+
|
47
|
+
@settings[name.to_sym]
|
48
|
+
end
|
49
|
+
|
50
|
+
def write_setting(name, value)
|
51
|
+
if self.class.class_settings[name]
|
52
|
+
@settings[name.to_sym] = value
|
53
|
+
else
|
54
|
+
raise NoMethodError, "Unknown setting: #{name.inspect}"
|
55
|
+
end
|
56
|
+
|
57
|
+
if self.class.caching?
|
58
|
+
Rails.cache.write(cache_key(name), value)
|
59
|
+
end
|
60
|
+
|
61
|
+
if self.class.persisting?
|
62
|
+
setting = ConfigureMe.persistence_klass.find_or_create_by_key(persistence_key(name))
|
63
|
+
setting.value = value.to_yaml
|
64
|
+
setting.save!
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
protected
|
70
|
+
|
71
|
+
def attribute_method?(name)
|
72
|
+
self.class.class_settings.key?(name)
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def settings=(new_settings)
|
78
|
+
return unless new_settings.is_a?(Hash)
|
79
|
+
settings = new_settings.stringify_keys
|
80
|
+
|
81
|
+
settings.each do |k, v|
|
82
|
+
respond_to?("#{k}=".to_sym) ? send("#{k}=".to_sym, v) : raise(UnknownMethodError, "Unknown setting: #{k}")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def attribute(name)
|
87
|
+
read_setting(name.to_sym)
|
88
|
+
end
|
89
|
+
|
90
|
+
def attribute=(name, value)
|
91
|
+
write_setting(name.to_sym, value)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rails/generators/active_record'
|
2
|
+
|
3
|
+
class ConfigureMeGenerator < ActiveRecord::Generators::Base #Rails::Generators::NamedBase
|
4
|
+
include Rails::Generators::Migration
|
5
|
+
|
6
|
+
source_root File.expand_path('../templates', __FILE__)
|
7
|
+
|
8
|
+
def generate_model
|
9
|
+
template 'model.rb', "app/models/#{singular_name}.rb"
|
10
|
+
end
|
11
|
+
|
12
|
+
def generate_migration
|
13
|
+
migration_template 'migration.rb', "db/migrate/create_#{plural_name}.rb"
|
14
|
+
end
|
15
|
+
|
16
|
+
def generate_initializer
|
17
|
+
template 'initializer.rb', 'config/initializers/init_configure_me.rb'
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
ConfigureMe.persist_with <%= class_name %>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class Create<%= class_name.pluralize %> < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :<%= plural_name %> do |t|
|
4
|
+
t.string :key
|
5
|
+
t.text :value
|
6
|
+
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
|
10
|
+
add_index :<%= plural_name %>, :key, :unique => true
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.down
|
14
|
+
drop_table :<%= plural_name %>
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ConfigureMe::Base do
|
4
|
+
class TestConfig < ConfigureMe::Base
|
5
|
+
end
|
6
|
+
|
7
|
+
it { TestConfig.should respond_to(:setting) }
|
8
|
+
it { TestConfig.instance.should respond_to(:read_setting) }
|
9
|
+
it { TestConfig.instance.should respond_to(:write_setting) }
|
10
|
+
it { TestConfig.send(:persisting?).should be_false }
|
11
|
+
|
12
|
+
describe 'with a "color" setting with a default of "red"' do
|
13
|
+
before(:each) do
|
14
|
+
@klass = Class.new(ConfigureMe::Base)
|
15
|
+
@klass.send :setting, :color, :default => 'red'
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'an instance ' do
|
19
|
+
it 'should respond to attribute_method?(:color) with true' do
|
20
|
+
@obj = @klass.instance
|
21
|
+
@obj.send(:attribute_method?, :color).should be_true
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should respond to attribute_method?(:size) with false' do
|
25
|
+
@obj = @klass.instance
|
26
|
+
@obj.send(:attribute_method?, :size).should be_false
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should respond to :color with "red"' do
|
30
|
+
@obj = @klass.instance
|
31
|
+
@obj.color.should eql('red')
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should store a new :color of "blue"' do
|
35
|
+
@obj = @klass.instance
|
36
|
+
@obj.color = 'blue'
|
37
|
+
@obj.color.should eql('blue')
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should raise error when setting an unknown attribute' do
|
41
|
+
@obj = @klass.instance
|
42
|
+
lambda { @obj.write_setting('size', 'big') }.should raise_error(NoMethodError)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should assign from a hash' do
|
46
|
+
@obj = @klass.instance
|
47
|
+
@obj.send :settings=, {:color => 'blue'}
|
48
|
+
@obj.color.should eql('blue')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe 'persisting' do
|
54
|
+
before(:each) do
|
55
|
+
@klass = TestConfig
|
56
|
+
@persistence = mock('PersistenceClass')
|
57
|
+
ConfigureMe.persist_with @persistence
|
58
|
+
@klass.send :setting, :color, :default => 'red'
|
59
|
+
@klass.send :persist_me
|
60
|
+
end
|
61
|
+
|
62
|
+
it { @klass.send(:persisting?).should be_true }
|
63
|
+
it { @klass.should respond_to(:persistence_key) }
|
64
|
+
it { @klass.persistence_key.should eql('test') }
|
65
|
+
|
66
|
+
describe 'with a non-persisted setting' do
|
67
|
+
before(:each) do
|
68
|
+
@obj = @klass.instance
|
69
|
+
@unpersisted = mock('UnpersistedSetting') do
|
70
|
+
stubs(:value=)
|
71
|
+
end
|
72
|
+
@persistence = mock('PersistenceClass')
|
73
|
+
ConfigureMe.persist_with @persistence
|
74
|
+
end
|
75
|
+
|
76
|
+
it { @obj.send(:persistence_key, :color).should eql('test_color') }
|
77
|
+
|
78
|
+
it 'should store updates to the database' do
|
79
|
+
@unpersisted = mock('UnpersistedSetting') do
|
80
|
+
expects(:value=)
|
81
|
+
expects(:save!)
|
82
|
+
end
|
83
|
+
@persistence.stubs(:find_or_create_by_key).returns(@unpersisted)
|
84
|
+
@obj.color = "blue"
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'should return the default value' do
|
88
|
+
@persistence.stubs(:find_by_key).returns(nil)
|
89
|
+
@obj.color.should eql('red')
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe 'with a persisted setting' do
|
94
|
+
before(:each) do
|
95
|
+
@obj = @klass.instance
|
96
|
+
@persisted = mock('PersistedSetting') do
|
97
|
+
stubs(:value).returns("blue".to_yaml)
|
98
|
+
end
|
99
|
+
@persistence.stubs(:find_by_key).returns(@persisted)
|
100
|
+
ConfigureMe.persist_with @persistence
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should return a valid value' do
|
104
|
+
@obj.color.should eql("blue")
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ConfigureMe::Setting do
|
4
|
+
before(:each) do
|
5
|
+
@owner = mock('owner') do
|
6
|
+
stubs(:define_attribute_methods)
|
7
|
+
end
|
8
|
+
@setting = ConfigureMe::Setting.new(@owner, :foo, :default => 'bar')
|
9
|
+
end
|
10
|
+
|
11
|
+
it { @setting.should respond_to(:name) }
|
12
|
+
it { @setting.name.should eql('foo') }
|
13
|
+
it { @setting.should respond_to(:default) }
|
14
|
+
it { @setting.default.should eql('bar') }
|
15
|
+
|
16
|
+
it "define_methods! should call the owner class's define_attribute_methods with false" do
|
17
|
+
owner = mock('owner') do
|
18
|
+
expects(:define_attribute_methods).with(true)
|
19
|
+
end
|
20
|
+
setting = ConfigureMe::Setting.new(owner, :foo, :default => 'bar')
|
21
|
+
setting.define_methods!
|
22
|
+
end
|
23
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,205 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: configure_me
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 25
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Josh Williams
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-12-27 00:00:00 -06:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: activemodel
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 5
|
30
|
+
segments:
|
31
|
+
- 3
|
32
|
+
- 0
|
33
|
+
- 1
|
34
|
+
version: 3.0.1
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: activesupport
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 5
|
46
|
+
segments:
|
47
|
+
- 3
|
48
|
+
- 0
|
49
|
+
- 1
|
50
|
+
version: 3.0.1
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: rspec
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 13
|
62
|
+
segments:
|
63
|
+
- 2
|
64
|
+
- 0
|
65
|
+
- 1
|
66
|
+
version: 2.0.1
|
67
|
+
type: :development
|
68
|
+
version_requirements: *id003
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rcov
|
71
|
+
prerelease: false
|
72
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
hash: 41
|
78
|
+
segments:
|
79
|
+
- 0
|
80
|
+
- 9
|
81
|
+
- 9
|
82
|
+
version: 0.9.9
|
83
|
+
type: :development
|
84
|
+
version_requirements: *id004
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: mocha
|
87
|
+
prerelease: false
|
88
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
hash: 43
|
94
|
+
segments:
|
95
|
+
- 0
|
96
|
+
- 9
|
97
|
+
- 8
|
98
|
+
version: 0.9.8
|
99
|
+
type: :development
|
100
|
+
version_requirements: *id005
|
101
|
+
- !ruby/object:Gem::Dependency
|
102
|
+
name: cucumber
|
103
|
+
prerelease: false
|
104
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
hash: 51
|
110
|
+
segments:
|
111
|
+
- 0
|
112
|
+
- 9
|
113
|
+
- 4
|
114
|
+
version: 0.9.4
|
115
|
+
type: :development
|
116
|
+
version_requirements: *id006
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: activerecord
|
119
|
+
prerelease: false
|
120
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
hash: 5
|
126
|
+
segments:
|
127
|
+
- 3
|
128
|
+
- 0
|
129
|
+
- 1
|
130
|
+
version: 3.0.1
|
131
|
+
type: :development
|
132
|
+
version_requirements: *id007
|
133
|
+
description: Simple gem to assist with persisting configuration data.
|
134
|
+
email:
|
135
|
+
- theprime@codingprime.com
|
136
|
+
executables: []
|
137
|
+
|
138
|
+
extensions: []
|
139
|
+
|
140
|
+
extra_rdoc_files: []
|
141
|
+
|
142
|
+
files:
|
143
|
+
- .gitignore
|
144
|
+
- .rspec
|
145
|
+
- Gemfile
|
146
|
+
- README.md
|
147
|
+
- Rakefile
|
148
|
+
- configure_me.gemspec
|
149
|
+
- features/memory.feature
|
150
|
+
- features/step_definitions/base_steps.rb
|
151
|
+
- lib/configure_me.rb
|
152
|
+
- lib/configure_me/base.rb
|
153
|
+
- lib/configure_me/caching.rb
|
154
|
+
- lib/configure_me/nesting.rb
|
155
|
+
- lib/configure_me/persistence.rb
|
156
|
+
- lib/configure_me/setting.rb
|
157
|
+
- lib/configure_me/settings.rb
|
158
|
+
- lib/configure_me/version.rb
|
159
|
+
- lib/generators/configure_me_generator.rb
|
160
|
+
- lib/generators/templates/initializer.rb
|
161
|
+
- lib/generators/templates/migration.rb
|
162
|
+
- lib/generators/templates/model.rb
|
163
|
+
- spec/configure_me/base_spec.rb
|
164
|
+
- spec/configure_me/setting_spec.rb
|
165
|
+
- spec/spec_helper.rb
|
166
|
+
has_rdoc: true
|
167
|
+
homepage: http://www.github.com/t3hpr1m3/configure_me
|
168
|
+
licenses: []
|
169
|
+
|
170
|
+
post_install_message:
|
171
|
+
rdoc_options: []
|
172
|
+
|
173
|
+
require_paths:
|
174
|
+
- lib
|
175
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
176
|
+
none: false
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
hash: 3
|
181
|
+
segments:
|
182
|
+
- 0
|
183
|
+
version: "0"
|
184
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
185
|
+
none: false
|
186
|
+
requirements:
|
187
|
+
- - ">="
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
hash: 3
|
190
|
+
segments:
|
191
|
+
- 0
|
192
|
+
version: "0"
|
193
|
+
requirements: []
|
194
|
+
|
195
|
+
rubyforge_project: configure_me
|
196
|
+
rubygems_version: 1.3.7
|
197
|
+
signing_key:
|
198
|
+
specification_version: 3
|
199
|
+
summary: Simple configuration library
|
200
|
+
test_files:
|
201
|
+
- features/memory.feature
|
202
|
+
- features/step_definitions/base_steps.rb
|
203
|
+
- spec/configure_me/base_spec.rb
|
204
|
+
- spec/configure_me/setting_spec.rb
|
205
|
+
- spec/spec_helper.rb
|