logical_model 0.5.13 → 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.
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: