logical_model 0.5.13 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.13
1
+ 0.6.0
@@ -14,6 +14,9 @@ class LogicalModel
14
14
  attr_accessor "#{key}_id"
15
15
  attr_class = get_attr_class(key, options)
16
16
 
17
+ @belongs_to_keys ||= {}
18
+ @belongs_to_keys.merge!({key => attr_class})
19
+
17
20
  define_method("#{key}=") do |param|
18
21
  if param.is_a?(Hash)
19
22
  param.stringify_keys!
@@ -51,6 +54,30 @@ class LogicalModel
51
54
  end
52
55
  end
53
56
 
57
+ def belongs_to_keys
58
+ # This hack was needed to consider the case where the belongs_to was set on a parent class, for example:
59
+ #
60
+ # class ContactAttribute < LogicalModel
61
+ # ...
62
+ # belongs_to :contact
63
+ # end
64
+ #
65
+ # class Telephone < ContactAttribute
66
+ # ...
67
+ # end
68
+ #
69
+ # It returns the parent's class variable if present.
70
+ result = nil
71
+ if !@belongs_to_keys.nil?
72
+ result = @belongs_to_keys
73
+ elsif self.superclass.respond_to? :belongs_to_keys
74
+ result = self.superclass.belongs_to_keys
75
+ else
76
+ result = nil
77
+ end
78
+ result
79
+ end
80
+
54
81
  private
55
82
 
56
83
  def get_attr_class(key, options)
@@ -66,6 +66,8 @@ class LogicalModel
66
66
  # in this case we recieved instanciated objects
67
67
  collection << attr_params
68
68
  else
69
+ clazz_name = attr_params['_type']
70
+ attr_class = clazz_name.constantize unless clazz_name.blank?
69
71
  # in this case we recieved object attributes, we instanciate here
70
72
  collection << attr_class.new(attr_params)
71
73
  end
@@ -75,13 +77,16 @@ class LogicalModel
75
77
 
76
78
  # Initialize instance of associated object
77
79
  define_method "new_#{StringHelper.singularize(association.to_s)}" do |attr_params|
78
- clazz = attr_class
80
+ run_callbacks :new_nested do
81
+ clazz_name = attr_params['_type']
82
+ clazz = clazz_name.blank? ? attr_class : clazz_name.constantize
79
83
 
80
- return unless clazz
84
+ return unless clazz
81
85
 
82
- temp_object = clazz.new(attr_params.merge({"#{self.json_root}_id" => self.id}))
83
- eval(association.to_s) << temp_object
84
- temp_object
86
+ temp_object = clazz.new(attr_params.merge({"#{self.json_root}_id" => self.id}))
87
+ eval(association.to_s) << temp_object
88
+ temp_object
89
+ end
85
90
  end
86
91
 
87
92
  # this method loads the contact attributes from the html form (using nested resources conventions)
@@ -2,9 +2,11 @@ class LogicalModel
2
2
  module Cache
3
3
 
4
4
  def self.included(base)
5
- base.send(:extend, ClassMethods)
5
+ base.extend ClassMethods
6
6
  base.send(:include, InstanceMethods)
7
7
  base.send(:after_initialize, :initialize_loaded_at)
8
+ base.send(:define_model_callbacks, :new_nested)
9
+ base.send(:after_new_nested, :delete_cached)
8
10
  end
9
11
 
10
12
  module InstanceMethods
@@ -19,9 +21,7 @@ class LogicalModel
19
21
  end
20
22
 
21
23
  def _save_with_cache
22
- model_name = self.class.to_s.pluralize.underscore
23
- self.class.logger.debug "LogicalModel Log CACHE: Delete cache for #{model_name}\/#{self.id}-.*"
24
- self.class.cache_store.delete_matched(/#{model_name}\/#{self.id}-.*/)
24
+ delete_cached
25
25
  _save_without_cache
26
26
  end
27
27
  alias_method_chain :_save, :cache
@@ -31,9 +31,7 @@ class LogicalModel
31
31
  end
32
32
 
33
33
  def _update_with_cache(params={})
34
- model_name = self.class.to_s.pluralize.underscore
35
- self.class.logger.debug "LogicalModel Log CACHE: Delete cache for #{model_name}\/#{self.id}-.*"
36
- self.class.cache_store.delete_matched(/#{model_name}\/#{self.id}-.*/)
34
+ delete_cached
37
35
  _update_without_cache params
38
36
  end
39
37
  alias_method_chain :_update, :cache
@@ -43,12 +41,27 @@ class LogicalModel
43
41
  end
44
42
 
45
43
  def _destroy_with_cache(params={})
44
+ delete_cached
45
+ _destroy_without_cache
46
+ end
47
+ alias_method_chain :_destroy, :cache
48
+
49
+ def delete_cached
46
50
  model_name = self.class.to_s.pluralize.underscore
47
51
  self.class.logger.debug "LogicalModel Log CACHE: Delete cache for #{model_name}\/#{self.id}-.*"
52
+ # Delete cached models
48
53
  self.class.cache_store.delete_matched(/#{model_name}\/#{self.id}-.*/)
49
- _destroy_without_cache
54
+
55
+ if self.class.respond_to?(:belongs_to_keys) && !self.class.belongs_to_keys.blank?
56
+ # If it belongs to another model (or models)
57
+ self.class.belongs_to_keys.each do |association_name, association_class|
58
+ model_name = association_class.to_s.pluralize.underscore
59
+ self.class.logger.debug "LogicalModel Log CACHE: Delete cache for #{model_name}\/#{self.send("#{association_name}_id")}-.*"
60
+ # Delete cached models
61
+ self.class.cache_store.delete_matched(/#{model_name}\/#{self.send("#{association_name}_id")}-.*/)
62
+ end
63
+ end
50
64
  end
51
- alias_method_chain :_destroy, :cache
52
65
  end
53
66
 
54
67
  module ClassMethods
@@ -111,6 +124,7 @@ class LogicalModel
111
124
  model_name = self.to_s.pluralize.underscore
112
125
  self.logger.debug "LogicalModel Log CACHE: Delete cache for #{model_name}\/#{id}-.*"
113
126
  self.cache_store.delete_matched(/#{model_name}\/#{id}-.*/)
127
+ #TODO: also delete cache for parent (belongs_to)
114
128
  delete_without_cache(id, params)
115
129
  end
116
130
  alias_method_chain :delete, :cache
@@ -123,10 +137,10 @@ class LogicalModel
123
137
  model_name = self.to_s.pluralize.underscore
124
138
  self.logger.debug "LogicalModel Log CACHE: Delete cache for #{model_name}\/(#{ids.join('|')})-.*"
125
139
  self.cache_store.delete_matched(/#{model_name}\/(#{ids.join('|')})-.*/)
140
+ #TODO: also delete cache for parent (belongs_to)
126
141
  delete_multiple_without_cache(ids, params)
127
142
  end
128
143
  alias_method_chain :delete_multiple, :cache
129
144
  end
130
-
131
145
  end
132
146
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "logical_model"
8
- s.version = "0.5.13"
8
+ s.version = "0.6.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Dwayne Macgowan"]
12
- s.date = "2014-06-13"
12
+ s.date = "2014-06-25"
13
13
  s.description = "LogicalModel allows to use a resource as a model. It is based on web presentation http://www.slideshare.net/ihower/serviceoriented-design-and-implement-with-rails3"
14
14
  s.email = "dwaynemac@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -1,17 +1,19 @@
1
1
  require './lib/logical_model'
2
2
 
3
3
  describe LogicalModel::Cache do
4
+ class Example < LogicalModel
5
+
6
+ attribute :id
7
+ attribute :name
8
+
9
+ self.hydra = Typhoeus::Hydra.new
10
+
11
+ self.enable_delete_multiple = true
12
+ end
13
+
4
14
  describe "when included" do
5
15
  before do
6
- class Example < LogicalModel
7
-
8
- attribute :id
9
- attribute :name
10
-
11
- self.hydra = Typhoeus::Hydra.new
12
-
13
- self.enable_delete_multiple = true
14
- end
16
+
15
17
  end
16
18
 
17
19
  it "adds expires_in class method" do
@@ -133,4 +135,59 @@ describe LogicalModel::Cache do
133
135
  end
134
136
  end
135
137
  end
138
+
139
+ describe "when using has_many & belongs_to" do
140
+
141
+ class SecondaryExample < LogicalModel
142
+ attribute :id
143
+
144
+ self.hydra = Typhoeus::Hydra.new
145
+
146
+ self.enable_delete_multiple = true
147
+
148
+ belongs_to :example
149
+ end
150
+
151
+ class SecondaryExampleChild < SecondaryExample
152
+ attribute :name
153
+ end
154
+
155
+ before do
156
+ Example.has_many_keys = [:secondary_examples]
157
+ end
158
+
159
+ it "should set belongs_to_keys" do
160
+ SecondaryExampleChild.belongs_to_keys.should_not be_blank
161
+ end
162
+
163
+ describe "save" do
164
+ before do
165
+ Example.stub_chain(:cache_store, :read).and_return(Example.new)
166
+ SecondaryExampleChild.stub_chain(:cache_store, :read).and_return(SecondaryExampleChild.new(:example_id => 123))
167
+ Example.stub_chain(:cache_store, :delete_matched).and_return(nil)
168
+ SecondaryExampleChild.stub_chain(:cache_store, :delete_matched).and_return(nil)
169
+ SecondaryExampleChild.async_find("id") {|r| @result = r}
170
+ end
171
+
172
+ it "should clear cache" do
173
+ SecondaryExampleChild.cache_store.should_receive(:delete_matched).with(/examples\/123-.*/)
174
+ @result.save
175
+ end
176
+ end
177
+
178
+ describe "adding a new model to has_many" do
179
+ before do
180
+ Example.stub_chain(:cache_store, :read).and_return(Example.new(:id => 123))
181
+ SecondaryExampleChild.stub_chain(:cache_store, :read).and_return(SecondaryExampleChild.new(:example_id => 123))
182
+ Example.stub_chain(:cache_store, :delete_matched).and_return(nil)
183
+ SecondaryExampleChild.stub_chain(:cache_store, :delete_matched).and_return(nil)
184
+ Example.async_find("123") {|r| @result = r}
185
+ end
186
+
187
+ it "should clear cache" do
188
+ Example.cache_store.should_receive(:delete_matched).with(/examples\/123-.*/)
189
+ @result.new_secondary_example(:example_id => 123)
190
+ end
191
+ end
192
+ end
136
193
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logical_model
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.13
4
+ version: 0.6.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-06-13 00:00:00.000000000 Z
12
+ date: 2014-06-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activemodel
@@ -393,7 +393,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
393
393
  version: '0'
394
394
  segments:
395
395
  - 0
396
- hash: -822604947
396
+ hash: -732207341
397
397
  required_rubygems_version: !ruby/object:Gem::Requirement
398
398
  none: false
399
399
  requirements: