flagpole_sitta 0.7.3 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +15 -13
- data/app/helpers/flagpole_sitta_helper.rb +19 -15
- data/lib/flagpole_sitta/cache_sitta.rb +59 -22
- data/lib/flagpole_sitta/engine.rb +1 -1
- data/lib/flagpole_sitta/existence_hash.rb +16 -9
- data/lib/flagpole_sitta/version.rb +1 -1
- metadata +2 -2
data/README.rdoc
CHANGED
@@ -147,6 +147,14 @@ This also means if your just showing objects in an index you don't even have to
|
|
147
147
|
|
148
148
|
:index_only => true, tells the helper to not bother trying to associated this cache with anyone item in particular.
|
149
149
|
|
150
|
+
You could also pass it :scope which will add a 'scope' to a :models_in_index cache, which will cause the cache to only be destroyed if an object with in its 'scope' is create, updated or destroyed. Like :model and :route_id for each model there must be a corresponding route_id. If you don't want a scope on every model then just do something like the following
|
151
|
+
|
152
|
+
- cache_sitta :models_in_index => [Blog, Setting], :scope => [@scope, nil] :index_only => true, :section => "body" do
|
153
|
+
|
154
|
+
The 'scope' can only be arguments for a where call. Which means it will either be a hash, record object, string, or an array.
|
155
|
+
|
156
|
+
Scopes should be used sparling because in order to verify them on save they require a call to the database, and while it boils down to a call by id, they can still add up if you don't pay attention.
|
157
|
+
|
150
158
|
== existence_hash
|
151
159
|
|
152
160
|
If you might have already figured out the overall strategy of this gem has a weakness. Namely how do you deal with instances where, the object being routed to doesn't exist. See if your not querying the database until your already in the view then you can't exactly redirect with out some crazy stuff going on. You could put some if statements in your view to show a 404 if the objects are nil, but the issue with that is that you would still end up with a bunch of pointless caches. This can all be avoided by creating a 'hash' in the cache which you can use to check for the existence of an object. This 'hash' too is updated on save/destory. Also the hash really isn't hash but rather a bunch of cache keys held together by a flag key. Lets use the page example from above.
|
@@ -166,27 +174,21 @@ A quick note you only actually have to pass :route_id once if your using both ca
|
|
166
174
|
|
167
175
|
class PagesController < ApplicationController
|
168
176
|
|
169
|
-
|
170
|
-
|
171
|
-
def show
|
177
|
+
def show
|
172
178
|
|
173
|
-
|
179
|
+
if Page.get_existence_hash(params[:url])
|
180
|
+
calls_sitta :name => "page", :section => "body" do
|
174
181
|
if params[:url]
|
175
182
|
@page = Page.find_by_url params[:url]
|
176
183
|
else
|
177
184
|
@page = Page.find_by_url 'home'
|
178
185
|
end
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
]
|
184
|
-
|
186
|
+
end
|
187
|
+
else
|
188
|
+
redirect_to :action => 'home'
|
189
|
+
flash[:notice] = "The Page you are looking for doesn't exist"
|
185
190
|
end
|
186
191
|
|
187
|
-
else
|
188
|
-
redirect_to :action => 'home'
|
189
|
-
flash[:notice] = "The Page you are looking for doesn't exist"
|
190
192
|
end
|
191
193
|
|
192
194
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module FlagpoleSittaHelper
|
2
2
|
|
3
|
-
def update_index_array_cache model, key
|
4
|
-
model.try(:update_array_cache, key)
|
3
|
+
def update_index_array_cache model, key, scope=nil
|
4
|
+
model.try(:update_array_cache, key, :scope => scope)
|
5
5
|
end
|
6
6
|
|
7
7
|
def update_show_array_cache model, key, route_id
|
8
|
-
model.try(:update_array_cache, key, route_id)
|
8
|
+
model.try(:update_array_cache, key, :route_id => route_id)
|
9
9
|
end
|
10
10
|
|
11
11
|
##
|
@@ -55,9 +55,13 @@ module FlagpoleSittaHelper
|
|
55
55
|
#That way your caching each possible version of the page
|
56
56
|
#instead of just one.
|
57
57
|
#
|
58
|
-
#:
|
59
|
-
#
|
60
|
-
#
|
58
|
+
#:scope which will add a 'scope' to a :models_in_index cache,
|
59
|
+
#which will cause the cache to only be destroyed if an object with in its 'scope' is create,
|
60
|
+
#updated or destroyed. Like :model and :route_id for each model there must be a corresponding route_id.
|
61
|
+
#If you don't want a scope on every model then just make the index model's scope nil.
|
62
|
+
#The 'scope' can only be arguments for a where call. Which means it will either be a hash or an array.
|
63
|
+
#Scopes should be used sparling because in order to verify them on save they require a call to the database,
|
64
|
+
#and while it boils down to a call by id, they can still add up if you don't pay attention.
|
61
65
|
def cache_sitta options={}, &block
|
62
66
|
|
63
67
|
if options[:route_id].class.eql?(Array)
|
@@ -120,11 +124,7 @@ module FlagpoleSittaHelper
|
|
120
124
|
if calls
|
121
125
|
calls.each do |c|
|
122
126
|
if instance_variable_get("@#{c[0]}").nil?
|
123
|
-
|
124
|
-
instance_variable_set("@#{c[0]}", c[1].call(options[:calls_args]))
|
125
|
-
else
|
126
|
-
instance_variable_set("@#{c[0]}", c[1].call())
|
127
|
-
end
|
127
|
+
instance_variable_set("@#{c[0]}", c[1].call())
|
128
128
|
end
|
129
129
|
end
|
130
130
|
end
|
@@ -142,13 +142,17 @@ module FlagpoleSittaHelper
|
|
142
142
|
#any of the model types involved are updated.
|
143
143
|
|
144
144
|
if options[:models_in_index].class.eql?(Array)
|
145
|
-
options[:models_in_index].
|
146
|
-
|
147
|
-
|
145
|
+
options[:models_in_index].each_index do |i|
|
146
|
+
m = options[:models_in_index][i]
|
147
|
+
if options[:scope]
|
148
|
+
scope = options[:scope][i]
|
149
|
+
end
|
150
|
+
processed_model = m.respond_to?(:constantize) ? m.constantize : m
|
151
|
+
update_index_array_cache(processed_model, key, scope)
|
148
152
|
end
|
149
153
|
elsif options[:models_in_index]
|
150
154
|
processed_model = options[:models_in_index].respond_to?(:constantize) ? options[:models_in_index].constantize : options[:models_in_index]
|
151
|
-
update_index_array_cache(options[:
|
155
|
+
update_index_array_cache(processed_model, key, options[:scope])
|
152
156
|
end
|
153
157
|
|
154
158
|
#AR - Create a link between each declared object and the cache.
|
@@ -10,6 +10,7 @@ module FlagpoleSitta
|
|
10
10
|
|
11
11
|
included do
|
12
12
|
before_save :cache_sitta_save
|
13
|
+
after_save :cache_sitta_after_save
|
13
14
|
before_destroy :cache_sitta_destory
|
14
15
|
end
|
15
16
|
|
@@ -40,9 +41,9 @@ module FlagpoleSitta
|
|
40
41
|
end
|
41
42
|
|
42
43
|
#Updates the 'array' in the cache.
|
43
|
-
def update_array_cache key,
|
44
|
+
def update_array_cache key, options={}
|
44
45
|
|
45
|
-
mid_key = mid_key_gen route_id
|
46
|
+
mid_key = mid_key_gen options[:route_id]
|
46
47
|
|
47
48
|
clazz = self
|
48
49
|
|
@@ -50,14 +51,14 @@ module FlagpoleSitta
|
|
50
51
|
|
51
52
|
#AR - If it doesn't exist start the process of creating it
|
52
53
|
if flag.nil?
|
53
|
-
flag = initialize_array_cache route_id
|
54
|
+
flag = initialize_array_cache options[:route_id]
|
54
55
|
end
|
55
56
|
|
56
57
|
#AR - update the array's end point
|
57
58
|
flag[:space] = flag[:space] + 1
|
58
59
|
|
59
60
|
#AR - write out the new index at the end of the array
|
60
|
-
Rails.cache.write("#{clazz}/#{mid_key}/#{flag[:space]}", {:key => key})
|
61
|
+
Rails.cache.write("#{clazz}/#{mid_key}/#{flag[:space]}", {:key => key, :scope => options[:scope]})
|
61
62
|
|
62
63
|
#AR - update flag in the cache
|
63
64
|
Rails.cache.write("#{clazz}/#{mid_key}/Flag", flag)
|
@@ -72,19 +73,16 @@ module FlagpoleSitta
|
|
72
73
|
clazz = self
|
73
74
|
|
74
75
|
flag = Rails.cache.read("#{clazz}/#{mid_key}/Flag")
|
75
|
-
|
76
|
-
#AR - If it doesn't exist start the process of creating it
|
77
|
-
if flag.nil?
|
78
|
-
flag = initialize_array_cache route_id
|
79
|
-
end
|
80
76
|
|
81
77
|
#AR - If there aren't any index do nothing.
|
82
78
|
#Else wise loop through every index.
|
83
79
|
#If it actually does exist then yield.
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
80
|
+
if flag
|
81
|
+
for i in 0..flag[:space] do
|
82
|
+
hash = Rails.cache.read("#{clazz}/#{mid_key}/#{i}")
|
83
|
+
if hash
|
84
|
+
yield hash
|
85
|
+
end
|
88
86
|
end
|
89
87
|
end
|
90
88
|
|
@@ -93,19 +91,32 @@ module FlagpoleSitta
|
|
93
91
|
end
|
94
92
|
|
95
93
|
#Nukes all corresponding caches for a given array.
|
96
|
-
def destroy_array_cache
|
94
|
+
def destroy_array_cache options={}
|
97
95
|
|
98
|
-
mid_key = mid_key_gen route_id
|
96
|
+
mid_key = mid_key_gen options[:route_id]
|
99
97
|
|
100
98
|
clazz = self
|
101
99
|
|
102
|
-
|
103
|
-
|
104
|
-
|
100
|
+
i = 0
|
101
|
+
|
102
|
+
each_cache options[:route_id] do |hash|
|
103
|
+
if hash.present?
|
104
|
+
if hash[:scope].nil? || options[:obj].in_scope(hash[:scope])
|
105
|
+
Rails.cache.delete(hash[:key])
|
106
|
+
else
|
107
|
+
Rails.cache.write("#{clazz}/#{mid_key}/#{i}", hash)
|
108
|
+
i = i + 1
|
109
|
+
end
|
105
110
|
end
|
106
111
|
end
|
107
112
|
|
108
|
-
|
113
|
+
if i == 0
|
114
|
+
Rails.cache.delete("#{clazz}/#{mid_key}/Flag")
|
115
|
+
else
|
116
|
+
flag = Rails.cache.read("#{clazz}/#{mid_key}/Flag")
|
117
|
+
flag[:space => (i - 1)]
|
118
|
+
Rails.cache.write("#{clazz}/#{mid_key}/Flag", flag)
|
119
|
+
end
|
109
120
|
end
|
110
121
|
|
111
122
|
end
|
@@ -114,6 +125,10 @@ module FlagpoleSitta
|
|
114
125
|
self.cache_work(true)
|
115
126
|
end
|
116
127
|
|
128
|
+
def cache_sitta_after_save
|
129
|
+
self.post_cache_work
|
130
|
+
end
|
131
|
+
|
117
132
|
def cache_sitta_destory
|
118
133
|
self.cache_work(false)
|
119
134
|
end
|
@@ -128,15 +143,15 @@ module FlagpoleSitta
|
|
128
143
|
while(clazz.respond_to? :destroy_array_cache)
|
129
144
|
|
130
145
|
#AR - Clear all caches related to the old route_id
|
131
|
-
clazz.destroy_array_cache(self.try(:send, ("#{clazz.route_id}_was")).to_s)
|
146
|
+
clazz.destroy_array_cache(:route_id => self.try(:send, ("#{clazz.route_id}_was")).to_s)
|
132
147
|
#AR - Clear all caches related to the new route_id just in case
|
133
|
-
clazz.destroy_array_cache(self.try(:send, ("#{clazz.route_id}")).to_s)
|
148
|
+
clazz.destroy_array_cache(:route_id => self.try(:send, ("#{clazz.route_id}")).to_s)
|
134
149
|
#AR - If the new and old are the same All that will happen on the second call is that
|
135
150
|
#it will write the flag out and then destroy it. A very tiny bit of work
|
136
151
|
#for a great amount of extra protection.
|
137
152
|
|
138
153
|
# AR - Remember to include models_in_index in your helper call in the corresponding index cache.
|
139
|
-
clazz.destroy_array_cache
|
154
|
+
clazz.destroy_array_cache(:obj => self)
|
140
155
|
|
141
156
|
clazz = clazz.superclass
|
142
157
|
end
|
@@ -146,11 +161,33 @@ module FlagpoleSitta
|
|
146
161
|
|
147
162
|
end
|
148
163
|
|
164
|
+
#Sense the current in_scope requires the object to be in the database, this has to be called in case the new version that has been
|
165
|
+
#saved fits into any cache's scope. The above call to clear index caches is basically the object_was call, while this is just the call
|
166
|
+
#for the update object.
|
167
|
+
def post_cache_work
|
168
|
+
original_clazz = self.class
|
169
|
+
clazz = original_clazz
|
170
|
+
|
171
|
+
while(clazz.respond_to? :destroy_array_cache)
|
172
|
+
# AR - Remember to include models_in_index in your helper call in the corresponding index cache.
|
173
|
+
clazz.destroy_array_cache(:obj => self)
|
174
|
+
|
175
|
+
clazz = clazz.superclass
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
179
|
+
|
149
180
|
#AR - For Safety this will not recurse upwards for the extra cache maintenance
|
150
181
|
def extra_cache_maintenance alive
|
151
182
|
method = (@_cache_extra_maintance || Proc.new{})
|
152
183
|
method.call
|
153
184
|
end
|
154
185
|
|
186
|
+
def in_scope scope
|
187
|
+
|
188
|
+
self.class.where(scope).exists?(self.id)
|
189
|
+
|
190
|
+
end
|
191
|
+
|
155
192
|
end
|
156
193
|
end
|
@@ -27,8 +27,8 @@ module FlagpoleSitta
|
|
27
27
|
i = 0
|
28
28
|
superclazz.find_each do |m|
|
29
29
|
#Route ID is the key. The POS is used to emulate an array, along with the length stored in the flag.
|
30
|
-
Rails.cache.write("#{superclazz}/ExistenceHash/#{m.send(m.class.route_id).to_s}", {:type => m.has_attribute?('type') ? m.type : m.class, :pos => i, :num => 0})
|
31
|
-
Rails.cache.write("#{superclazz}/ExistenceHash/#{i}", {:key => m.send(m.class.route_id).to_s})
|
30
|
+
Rails.cache.write("#{superclazz}/ExistenceHash/#{m.class}/#{m.send(m.class.route_id).to_s}", {:type => m.has_attribute?('type') ? m.type : m.class, :pos => i, :num => 0})
|
31
|
+
Rails.cache.write("#{superclazz}/ExistenceHash/#{i}", {:key => m.send(m.class.route_id).to_s, :type => m.class})
|
32
32
|
i = i + 1
|
33
33
|
end
|
34
34
|
|
@@ -39,6 +39,8 @@ module FlagpoleSitta
|
|
39
39
|
#Gets a value from the 'hash' in the cache given a key.
|
40
40
|
def get_existence_hash key
|
41
41
|
|
42
|
+
clazz = self
|
43
|
+
|
42
44
|
superclazz = get_super_with_existence_hash
|
43
45
|
#Try to find the hash
|
44
46
|
flag = Rails.cache.read("#{superclazz}/ExistenceHash/Flag")
|
@@ -47,12 +49,14 @@ module FlagpoleSitta
|
|
47
49
|
initialize_existence_hash
|
48
50
|
end
|
49
51
|
|
50
|
-
Rails.cache.read("#{superclazz}/ExistenceHash/#{key}")
|
52
|
+
Rails.cache.read("#{superclazz}/ExistenceHash/#{clazz}/#{key}")
|
51
53
|
|
52
54
|
end
|
53
55
|
|
54
56
|
#Increments a value from the 'hash' in the cache given a key.
|
55
57
|
def increment_existence_hash key
|
58
|
+
|
59
|
+
clazz = self
|
56
60
|
|
57
61
|
superclazz = get_super_with_existence_hash
|
58
62
|
#Try to find the hash
|
@@ -61,7 +65,7 @@ module FlagpoleSitta
|
|
61
65
|
#Update the hash key if it exists
|
62
66
|
if hash
|
63
67
|
hash[:num] = hash[:num] + 1
|
64
|
-
Rails.cache.write("#{superclazz}/ExistenceHash/#{key}", hash)
|
68
|
+
Rails.cache.write("#{superclazz}/ExistenceHash/#{clazz}/#{key}", hash)
|
65
69
|
end
|
66
70
|
|
67
71
|
#Return the value
|
@@ -72,6 +76,8 @@ module FlagpoleSitta
|
|
72
76
|
#Goes through each entry in the hash returning a key and value
|
73
77
|
def each_existence_hash &block
|
74
78
|
|
79
|
+
clazz = self
|
80
|
+
|
75
81
|
superclazz = get_super_with_existence_hash
|
76
82
|
|
77
83
|
flag = Rails.cache.read("#{superclazz}/ExistenceHash/Flag")
|
@@ -85,8 +91,8 @@ module FlagpoleSitta
|
|
85
91
|
|
86
92
|
value = Rails.cache.read("#{superclazz}/ExistenceHash/#{i}")
|
87
93
|
|
88
|
-
if value.present?
|
89
|
-
hash = Rails.cache.read("#{superclazz}/ExistenceHash/#{value[:key]}")
|
94
|
+
if value.present? && value[:type].eql?(clazz)
|
95
|
+
hash = Rails.cache.read("#{superclazz}/ExistenceHash/#{value[:type]}/#{value[:key]}")
|
90
96
|
yield value[:key], hash
|
91
97
|
end
|
92
98
|
|
@@ -129,6 +135,7 @@ module FlagpoleSitta
|
|
129
135
|
|
130
136
|
#Updates the 'hash' on save of any of its records.
|
131
137
|
def update_existence_hash alive
|
138
|
+
clazz = self.class
|
132
139
|
superclazz = self.class.get_super_with_existence_hash
|
133
140
|
|
134
141
|
#Old key is where it was, and new is where it is going.
|
@@ -151,13 +158,13 @@ module FlagpoleSitta
|
|
151
158
|
hash = {:type => self.has_attribute?('type') ? self.type : self.class, :num => 0, :pos => flag[:space]}
|
152
159
|
else
|
153
160
|
hash = self.class.get_existence_hash(self.send("#{self.class.route_id}_was"))
|
154
|
-
Rails.cache.delete("#{superclazz}/ExistenceHash/#{old_key}")
|
161
|
+
Rails.cache.delete("#{superclazz}/ExistenceHash/#{clazz}/#{old_key}")
|
155
162
|
end
|
156
163
|
|
157
164
|
#If the record is not being destroyed add new route_id to existence hash
|
158
165
|
if alive
|
159
|
-
Rails.cache.write("#{superclazz}/ExistenceHash/#{new_key}", hash)
|
160
|
-
Rails.cache.write("#{superclazz}/ExistenceHash/#{hash[:pos]}", {:key => new_key})
|
166
|
+
Rails.cache.write("#{superclazz}/ExistenceHash/#{clazz}/#{new_key}", hash)
|
167
|
+
Rails.cache.write("#{superclazz}/ExistenceHash/#{hash[:pos]}", {:key => new_key, :type => clazz})
|
161
168
|
#The following check is needed if for some reason someone does destroy on a none saved record.
|
162
169
|
elsif !self.new_record?
|
163
170
|
if hash[:pos] == flag[:space]
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flagpole_sitta
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.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: 2012-07-
|
12
|
+
date: 2012-07-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: dalli
|