configure_me 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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