configure_me 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. data/.rvmrc +1 -1
  2. data/Guardfile +9 -0
  3. data/configure_me.gemspec +3 -0
  4. data/lib/configure_me/attribute_methods.rb +10 -7
  5. data/lib/configure_me/base.rb +32 -20
  6. data/lib/configure_me/caching.rb +4 -4
  7. data/lib/configure_me/loading.rb +2 -2
  8. data/lib/configure_me/naming.rb +8 -6
  9. data/lib/configure_me/nesting.rb +35 -29
  10. data/lib/configure_me/persistence.rb +5 -4
  11. data/lib/configure_me/persisting.rb +4 -5
  12. data/lib/configure_me/validations.rb +7 -6
  13. data/lib/configure_me/version.rb +1 -1
  14. data/lib/configure_me.rb +1 -6
  15. data/spec/lib/configure_me/attribute_methods_spec.rb +113 -0
  16. data/spec/lib/configure_me/base_spec.rb +81 -0
  17. data/spec/lib/configure_me/caching_spec.rb +75 -0
  18. data/spec/lib/configure_me/loading_spec.rb +97 -0
  19. data/spec/lib/configure_me/naming_spec.rb +22 -0
  20. data/spec/lib/configure_me/nesting_spec.rb +54 -0
  21. data/spec/lib/configure_me/persistence_spec.rb +65 -0
  22. data/spec/lib/configure_me/persisting_spec.rb +119 -0
  23. data/spec/{configure_me → lib/configure_me}/setting_spec.rb +0 -0
  24. data/spec/spec_helper.rb +3 -1
  25. metadata +62 -31
  26. data/lib/configure_me/identity.rb +0 -15
  27. data/spec/configure_me/attribute_methods_spec.rb +0 -113
  28. data/spec/configure_me/base_spec.rb +0 -58
  29. data/spec/configure_me/caching_spec.rb +0 -75
  30. data/spec/configure_me/identity_spec.rb +0 -30
  31. data/spec/configure_me/loading_spec.rb +0 -84
  32. data/spec/configure_me/naming_spec.rb +0 -23
  33. data/spec/configure_me/nesting_spec.rb +0 -36
  34. data/spec/configure_me/persistence_spec.rb +0 -62
  35. data/spec/configure_me/persisting_spec.rb +0 -123
data/.rvmrc CHANGED
@@ -1 +1 @@
1
- rvm use 1.9.2@configure_me
1
+ rvm use --create 1.9.2@configure_me
data/Guardfile ADDED
@@ -0,0 +1,9 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+ end
9
+
data/configure_me.gemspec CHANGED
@@ -19,8 +19,11 @@ Gem::Specification.new do |s|
19
19
  s.require_paths = %w(lib)
20
20
 
21
21
  s.add_dependency 'activerecord', '~> 3.1.0'
22
+ s.add_dependency 'activesupport', '~> 3.1.0'
22
23
 
23
24
  s.add_development_dependency 'rspec', '~> 2.7.0'
24
25
  s.add_development_dependency 'simplecov', '~> 0.5.4'
25
26
  s.add_development_dependency 'mocha', '~> 0.10.0'
27
+ s.add_development_dependency 'guard-rspec', '~> 0.5.10'
28
+ s.add_development_dependency 'libnotify', '~> 0.6.0'
26
29
  end
@@ -1,10 +1,15 @@
1
1
  module ConfigureMe
2
- class Base
3
- include ActiveModel::AttributeMethods
4
- include ActiveModel::Dirty
5
- attribute_method_suffix('', '=', '_before_type_cast')
2
+ module AttributeMethods
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ include ActiveModel::AttributeMethods
7
+ include ActiveModel::Dirty
8
+ attribute_method_suffix('', '=', '_before_type_cast')
9
+ extend OverriddenClassMethods
10
+ end
6
11
 
7
- class << self
12
+ module OverriddenClassMethods
8
13
  def setting(name, *args)
9
14
  class_settings[name.to_sym] = Setting.new(name.to_sym, *args)
10
15
  define_attribute_methods(true)
@@ -20,8 +25,6 @@ module ConfigureMe
20
25
  super(class_settings.keys)
21
26
  end
22
27
  end
23
- end
24
- module AttributeMethods
25
28
 
26
29
  def read_attribute(name)
27
30
  name_sym = name.to_sym
@@ -6,7 +6,6 @@ module ConfigureMe
6
6
  extend ActiveModel::Callbacks
7
7
  include AttributeMethods
8
8
  include Caching
9
- include Identity
10
9
  include Naming
11
10
  include Nesting
12
11
  include Persistence
@@ -22,7 +21,7 @@ module ConfigureMe
22
21
  def to_key
23
22
  if persisted?
24
23
  key = parent_config.nil? ? [] : parent_config.to_key
25
- key << self.config_name
24
+ key << self.class.config_name
26
25
  key
27
26
  else
28
27
  nil
@@ -37,36 +36,49 @@ module ConfigureMe
37
36
  end
38
37
  end
39
38
 
39
+ def config_key
40
+ to_param
41
+ end
42
+
43
+ def storage_key(name)
44
+ "#{config_key}-#{name.to_s}"
45
+ end
46
+
40
47
  class << self
41
48
  def inherited(subclass)
42
49
  super
43
50
  configs << subclass
44
51
  end
45
52
 
46
- def method_missing(method_sym, *args)
47
- if instance.respond_to?(method_sym)
48
- instance.send(method_sym, *args)
49
- else
50
- super
51
- end
53
+ def config_name
54
+ self.name.demodulize.gsub(/^(.*)Config$/, '\1').underscore
52
55
  end
53
56
 
54
- def respond_to?(method_sym, include_private = false)
55
- instance.children.each_pair do |name, instance|
56
- if name.to_s.eql?(method_sym.to_s)
57
- return true
58
- end
59
- end
60
- if class_settings.key?(method_sym)
61
- return true
62
- end
63
- super
64
- end
57
+ #def method_missing(method_sym, *args)
58
+ # if instance.respond_to?(method_sym)
59
+ # instance.send(method_sym, *args)
60
+ # else
61
+ # super
62
+ # end
63
+ #end
64
+
65
+ #def respond_to?(method_sym, include_private = false)
66
+ # instance.children.each_pair do |name, instance|
67
+ # if name.to_s.eql?(method_sym.to_s)
68
+ # return true
69
+ # end
70
+ # end
71
+ # if class_settings.key?(method_sym)
72
+ # return true
73
+ # end
74
+ # super
75
+ #end
65
76
 
66
77
  def find_by_id(id)
67
78
  configs.each do |config|
68
79
  if config.config_key.eql?(id)
69
- return config.instance
80
+ #return config.instance
81
+ return config.new
70
82
  end
71
83
  end
72
84
  nil
@@ -1,6 +1,8 @@
1
1
  module ConfigureMe
2
- class Base
3
- class << self
2
+ module Caching
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
4
6
  def cache_me
5
7
  @caching = true
6
8
  end
@@ -10,9 +12,7 @@ module ConfigureMe
10
12
  @caching && !ConfigureMe.cache_object.nil?
11
13
  end
12
14
  end
13
- end
14
15
 
15
- module Caching
16
16
  def read_cache(name)
17
17
  if self.class.caching?
18
18
  ConfigureMe.cache_object.read(self.storage_key(name))
@@ -50,8 +50,8 @@ module ConfigureMe
50
50
  private
51
51
 
52
52
  def define_custom_class(name)
53
- remove_const(name.to_sym) if const_defined?(name)
54
- const_set(name, Class.new(ConfigureMe::Base))
53
+ Object.send(:remove_const, name) if Object.const_defined?(name)
54
+ Object.const_set(name, Class.new(ConfigureMe::Base))
55
55
  end
56
56
  end
57
57
  end
@@ -1,8 +1,13 @@
1
1
  module ConfigureMe
2
- class Base
3
- extend ActiveModel::Naming
2
+ module Naming
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ extend ActiveModel::Naming
7
+ extend OverriddenClassMethods
8
+ end
4
9
 
5
- class << self
10
+ module OverriddenClassMethods
6
11
  def model_name
7
12
  if persisting?
8
13
  ConfigureMe.persistence_klass.model_name
@@ -12,7 +17,4 @@ module ConfigureMe
12
17
  end
13
18
  end
14
19
  end
15
-
16
- module Naming
17
- end
18
20
  end
@@ -1,42 +1,48 @@
1
1
  module ConfigureMe
2
- class Base
3
- class << self
2
+ module Nesting
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
4
6
  def nest_me(klass, name = nil)
5
- klass.instance.nest(self)
7
+ klass.nested_classes[self.config_name.to_sym] = self
8
+ klass.class_eval <<-EOF, __FILE__, __LINE__
9
+ def #{self.config_name}
10
+ @#{self.config_name} ||= begin
11
+ config = self.class.nested_classes["#{self.config_name}".to_sym].new
12
+ config.parent_config = self
13
+ self.children["#{self.config_name}".to_sym] = config
14
+ config
15
+ end
16
+ end
17
+ EOF
6
18
  end
7
- end
8
- end
9
19
 
10
- module Nesting
11
-
12
- def nest(klass)
13
- children[klass.instance.config_name.to_sym] = klass.instance
14
- klass.instance.parent_config = self
15
- self.class_eval <<-EOF, __FILE__, __LINE__
16
- def #{klass.instance.config_name}
17
- children[:#{klass.instance.config_name.to_s}]
18
- end
19
- EOF
20
+ def nested_classes
21
+ @nested_classes ||= {}
22
+ end
20
23
  end
21
24
 
22
- def parent_config
23
- @parent_config ||= nil
24
- end
25
+ module InstanceMethods
25
26
 
26
- def parent_config=(parent_config)
27
- @parent_config = parent_config
28
- end
27
+ def parent_config
28
+ @parent_config ||= nil
29
+ end
29
30
 
30
- def children
31
- @children ||= {}
32
- end
31
+ def parent_config=(parent_config)
32
+ @parent_config = parent_config
33
+ end
34
+
35
+ def children
36
+ @children ||= {}
37
+ end
33
38
 
34
- def all_configs
35
- res = [self]
36
- children.values.each do |child|
37
- res.concat(child.all_configs)
39
+ def all_configs
40
+ res = [self]
41
+ children.values.each do |child|
42
+ res.concat(child.all_configs)
43
+ end
44
+ res
38
45
  end
39
- res
40
46
  end
41
47
  end
42
48
  end
@@ -1,9 +1,10 @@
1
1
  module ConfigureMe
2
- class Base
3
- extend ActiveModel::Callbacks
4
- define_model_callbacks :save
5
- end
6
2
  module Persistence
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ define_model_callbacks :save
7
+ end
7
8
 
8
9
  def save(*)
9
10
  run_callbacks :save do
@@ -1,6 +1,8 @@
1
1
  module ConfigureMe
2
- class Base
3
- class << self
2
+ module Persisting
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
4
6
  def persist_me
5
7
  @persisting = true
6
8
  end
@@ -10,9 +12,6 @@ module ConfigureMe
10
12
  @persisting && !ConfigureMe.persistence_klass.nil?
11
13
  end
12
14
  end
13
- end
14
-
15
- module Persisting
16
15
 
17
16
  def read_persist(name)
18
17
  if self.class.persisting?
@@ -1,9 +1,13 @@
1
1
  require 'active_model'
2
2
 
3
3
  module ConfigureMe
4
- class Base
5
- include ActiveModel::Validations
6
- define_model_callbacks :validation
4
+ module Validations
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ include ActiveModel::Validations
9
+ define_model_callbacks :validation
10
+ end
7
11
 
8
12
  def save(options={})
9
13
  run_callbacks :validation do
@@ -27,7 +31,4 @@ module ConfigureMe
27
31
  end
28
32
  end
29
33
  end
30
-
31
- module Validations
32
- end
33
34
  end
@@ -1,3 +1,3 @@
1
1
  module ConfigureMe
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
data/lib/configure_me.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require 'active_model'
2
- require 'singleton'
2
+ require 'active_support'
3
3
 
4
4
  module ConfigureMe
5
5
  class << self
@@ -17,15 +17,10 @@ module ConfigureMe
17
17
  @cache_object
18
18
  end
19
19
  end
20
-
21
- class Base
22
- include Singleton
23
- end
24
20
  end
25
21
 
26
22
  require 'configure_me/attribute_methods'
27
23
  require 'configure_me/caching'
28
- require 'configure_me/identity'
29
24
  require 'configure_me/loading'
30
25
  require 'configure_me/naming'
31
26
  require 'configure_me/nesting'
@@ -0,0 +1,113 @@
1
+ require 'spec_helper'
2
+
3
+ describe ConfigureMe::AttributeMethods do
4
+ class AttributeTester
5
+ include ConfigureMe::AttributeMethods
6
+ end
7
+
8
+ let(:test_class) { define_test_class('MyTestConfig', AttributeTester) }
9
+ subject { test_class.new }
10
+ it 'make_clean should clear the temp_attributes' do
11
+ subject.send(:temp_attributes).expects(:clear)
12
+ subject.send(:make_clean)
13
+ end
14
+
15
+ describe 'reading an attribute' do
16
+ before {
17
+ test_class.send(:setting, :testsetting, :default => 'foo')
18
+ @config = test_class.new
19
+ @config.stubs(:read_cache)
20
+ @config.stubs(:read_persist)
21
+ }
22
+ subject { @config }
23
+ it 'should call "read_attribute"' do
24
+ @config.expects(:read_attribute).with('testsetting')
25
+ subject.testsetting
26
+ end
27
+ context 'with a pristine instance' do
28
+ it 'should attempt to read from the cache' do
29
+ subject.expects(:read_cache)
30
+ subject.testsetting
31
+ end
32
+ it 'should attempt to read from the persistence store' do
33
+ subject.expects(:read_persist)
34
+ subject.testsetting
35
+ end
36
+ it 'should return the default value' do
37
+ subject.testsetting.should eql('foo')
38
+ end
39
+ end
40
+ context 'with a persisted value' do
41
+ context 'with a non-cached value' do
42
+ before { @config.stubs(:read_cache).returns(nil) }
43
+ it 'should attempt to read from the cache' do
44
+ subject.expects(:read_cache).returns(nil)
45
+ subject.testsetting
46
+ end
47
+ it 'should attempt to read from the persistence store' do
48
+ subject.expects(:read_persist)
49
+ subject.testsetting
50
+ end
51
+ it 'should write the value to the cache' do
52
+ subject.stubs(:read_persist).returns('persisted')
53
+ subject.expects(:write_cache).with(:testsetting, 'persisted')
54
+ subject.testsetting
55
+ end
56
+ it 'should return the persisted value' do
57
+ subject.stubs(:read_cache).returns('persisted')
58
+ subject.testsetting.should eql('persisted')
59
+ end
60
+ end
61
+
62
+ context 'with a cached value' do
63
+ before { @config.stubs(:read_cache).returns('cached') }
64
+ it 'should attempt to read from the cache' do
65
+ subject.expects(:read_cache).returns('cached')
66
+ subject.testsetting
67
+ end
68
+ it 'should not attempt to read from the persistence store' do
69
+ subject.expects(:read_persist).never
70
+ subject.testsetting
71
+ end
72
+ it 'should return the cached value' do
73
+ subject.testsetting.should eql('cached')
74
+ end
75
+ end
76
+ end
77
+
78
+ context 'with a dirty value' do
79
+ before { @config.stubs(:testsetting_changed?).returns(true) }
80
+ it 'should not attempt to read from the cache' do
81
+ subject.expects(:read_cache).never
82
+ subject.testsetting
83
+ end
84
+ it 'should not attempt to read from the persistence store' do
85
+ subject.expects(:read_persist).never
86
+ subject.testsetting
87
+ end
88
+ it 'should return the value from the temp_attributes hash' do
89
+ subject.expects(:temp_attributes).returns(:testsetting => 'iamdirty')
90
+ subject.testsetting.should eql('iamdirty')
91
+ end
92
+ end
93
+ end
94
+
95
+ describe 'writing an attribute' do
96
+ before {
97
+ test_class.send(:setting, :testsetting, :default => 'foo')
98
+ @config = test_class.new
99
+ @config.stubs(:read_cache)
100
+ @config.stubs(:read_persist)
101
+ }
102
+ subject { @config }
103
+
104
+ it 'should set the attribute to dirty' do
105
+ subject.expects(:make_dirty).with(:testsetting)
106
+ subject.testsetting = 'newvalue'
107
+ end
108
+ it 'should write the value to the temp_attributes hash' do
109
+ subject.testsetting = 'newvalue'
110
+ subject.send(:temp_attributes)[:testsetting].should eql('newvalue')
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+
3
+ describe ConfigureMe do
4
+ it { should respond_to(:init) }
5
+ it { should respond_to(:persistence_klass) }
6
+ it { should respond_to(:cache_object) }
7
+ it 'should provide nil defaults for :init' do
8
+ ConfigureMe.init
9
+ ConfigureMe.persistence_klass.should be_nil
10
+ ConfigureMe.cache_object.should be_nil
11
+ end
12
+
13
+ it 'should accept a hash of initialization arguments' do
14
+ ConfigureMe.init(:persist_with => 'foo', :cache_with => 'bar')
15
+ ConfigureMe.persistence_klass.should eql('foo')
16
+ ConfigureMe.cache_object.should eql('bar')
17
+ end
18
+ end
19
+
20
+ describe ConfigureMe::Base do
21
+
22
+ class BaseTesterConfig < ConfigureMe::Base
23
+ setting :setting1, :type => :integer, :default => 12
24
+ end
25
+
26
+ subject { BaseTesterConfig.new }
27
+ its(:persisted?) { should be_true }
28
+
29
+ describe 'to_key' do
30
+ context 'without a parent config' do
31
+ before {
32
+ subject.stubs(:parent_config).returns(nil)
33
+ }
34
+ its(:to_key) { should eql(['base_tester']) }
35
+ end
36
+ context 'with a parent config' do
37
+ let(:parent_config) {
38
+ mock('ParentConfig') do
39
+ stubs(:to_key).returns(['parent'])
40
+ end
41
+ }
42
+ before {
43
+ subject.stubs(:parent_config).returns(parent_config)
44
+ }
45
+ its(:to_key) { should eql(['parent', 'base_tester']) }
46
+ end
47
+ end
48
+
49
+ describe 'to_param' do
50
+ context 'with a root config' do
51
+ its(:to_param) { should eql('base_tester') }
52
+ end
53
+ context 'with a nested config' do
54
+ before { subject.stubs(:to_key).returns(['parent', 'base_tester']) }
55
+ its(:to_param) { should eql('parent-base_tester') }
56
+ end
57
+ end
58
+
59
+ describe 'storage_key' do
60
+ specify { subject.storage_key('foo').should eql('base_tester-foo') }
61
+ end
62
+
63
+ describe 'ActiveModel compliance' do
64
+ subject { define_test_class('TestConfig', ConfigureMe::Base).new }
65
+ it_should_behave_like "ActiveModel"
66
+ end
67
+
68
+ describe 'find_by_id' do
69
+ subject { ConfigureMe::Base }
70
+ let(:configs) { [stub(:config_key => 'the-right-one', :new => 'object')] }
71
+ it 'should return nil for an invalid id' do
72
+ subject.stubs(:configs).returns([])
73
+ subject.find_by_id('something').should be_nil
74
+ end
75
+
76
+ it 'should return a matching config' do
77
+ subject.stubs(:configs).returns(configs)
78
+ subject.find_by_id('the-right-one').should eql('object')
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+
3
+ describe ConfigureMe::Caching do
4
+ class CachingTester
5
+ include ConfigureMe::Caching
6
+ end
7
+ let(:caching_class) { define_test_class('CachingConfig', CachingTester) }
8
+ subject { CachingTester }
9
+ it { should respond_to(:cache_me) }
10
+ it { should respond_to(:caching?) }
11
+
12
+ describe 'caching?' do
13
+ before {
14
+ caching_class.send(:cache_me)
15
+ }
16
+ subject { caching_class }
17
+
18
+ context 'when cache_object is available' do
19
+ before { ConfigureMe.stubs(:cache_object).returns({}) }
20
+ specify { subject.caching?.should be_true }
21
+ end
22
+
23
+ context 'when cache_object is unavailable' do
24
+ before { ConfigureMe.stubs(:cache_object).returns(nil) }
25
+ specify { subject.caching?.should be_false }
26
+ end
27
+
28
+ end
29
+
30
+ context 'when caching is enabled' do
31
+ let(:cache_object) { stub(:read => 'cached_value', :write => true) }
32
+ before {
33
+ caching_class.stubs(:caching?).returns(true)
34
+ ConfigureMe.stubs(:cache_object).returns(cache_object)
35
+ @caching_obj = caching_class.new
36
+ @caching_obj.stubs(:storage_key).returns('cache_tester')
37
+ }
38
+ subject { @caching_obj }
39
+
40
+ it 'should attempt to read from the cache' do
41
+ ConfigureMe.expects(:cache_object).once.returns(cache_object)
42
+ subject.read_cache('cachedsetting')
43
+ end
44
+
45
+ it 'should return the value from the cache' do
46
+ subject.read_cache('cachedsetting').should eql('cached_value')
47
+ end
48
+
49
+ it 'should attempt to write to the cache' do
50
+ cache_object.expects(:write).once
51
+ subject.write_cache('cachedsetting', 'newvalue')
52
+ end
53
+ end
54
+
55
+ context 'when caching is disabled' do
56
+ before {
57
+ caching_class.stubs(:caching?).returns(false)
58
+ }
59
+ subject { caching_class.new }
60
+
61
+ it 'should not attempt to read from the cache' do
62
+ ConfigureMe.expects(:cache_object).never
63
+ subject.read_cache('cachedsetting')
64
+ end
65
+
66
+ it 'should return nil when read_cache is called' do
67
+ subject.read_cache('cachedsetting').should be_nil
68
+ end
69
+
70
+ it 'should not attempt to write to the cache' do
71
+ ConfigureMe.expects(:cache_object).never
72
+ subject.write_cache('cachedsetting', 'newvalue')
73
+ end
74
+ end
75
+ end