flagpole_sitta 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +37 -18
- data/app/helpers/flagpole_sitta_helper.rb +8 -7
- data/flagpole_sitta.gemspec +1 -4
- data/lib/flagpole_sitta/bracket_retrieval.rb +20 -17
- data/lib/flagpole_sitta/cache_sitta.rb +12 -1
- data/lib/flagpole_sitta/controller_sitta.rb +91 -0
- data/lib/flagpole_sitta/existence_hash.rb +72 -65
- data/lib/flagpole_sitta/version.rb +1 -1
- data/lib/flagpole_sitta.rb +1 -0
- metadata +3 -2
data/README.rdoc
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
= FlagpoleSitta
|
2
2
|
|
3
3
|
I had visions, I was in them,
|
4
|
+
|
4
5
|
I was looking into the mirror
|
6
|
+
|
5
7
|
To see a little bit clearer
|
8
|
+
|
6
9
|
The rottenness and evil in me.
|
7
10
|
|
8
11
|
♫~♫~♫~♫~♫~♫~♫~♫~♫~♫~♫~♫~♫~♫~♫~♫~♫~♫~♫~♫~♫~♫~♫
|
@@ -17,7 +20,23 @@ http://www.harveydanger.com/contribute.php
|
|
17
20
|
|
18
21
|
My grammar ability's are fail. So if something doesn't make sense in the docs don't be afraid to point it out and/or submit a patch. Because to me it all looks right.....
|
19
22
|
|
20
|
-
This gem has also only so far been tested with Memcache using the Dalli gem. File System caching and memory caching are not recommended.Redis/Memcache are defiantly suggested and strongly encouraged for this gem.
|
23
|
+
This gem has also only so far been tested with Memcache using the Dalli gem. File System caching and memory caching are not recommended. Redis/Memcache are defiantly suggested and strongly encouraged for this gem.
|
24
|
+
|
25
|
+
== Inspiration
|
26
|
+
|
27
|
+
My insperation for this project came from the following post on github
|
28
|
+
|
29
|
+
http://stackoverflow.com/a/1035832/1436131
|
30
|
+
|
31
|
+
On a project I was handling things like the OP was, which of course has a chance of failure if between the controller and the view the cache expires or is deleted.
|
32
|
+
|
33
|
+
That post also lead me to the following depericated ruby gem.
|
34
|
+
|
35
|
+
https://github.com/evan/interlock
|
36
|
+
|
37
|
+
I looked at it and decided it didn't meet my needs even if I where to get it updated. Which lead me to decided to create my own.
|
38
|
+
|
39
|
+
PS feel free to vote up the above answer on stackoverflow, I know I have!
|
21
40
|
|
22
41
|
== Installation
|
23
42
|
|
@@ -31,6 +50,12 @@ OR
|
|
31
50
|
|
32
51
|
Then bundle install.
|
33
52
|
|
53
|
+
== Special Thanks
|
54
|
+
|
55
|
+
Taha Mukaddam
|
56
|
+
https://github.com/tmkdam
|
57
|
+
For his feedback and help on this gem.
|
58
|
+
|
34
59
|
== cache_sitta
|
35
60
|
|
36
61
|
Flagpole Sitta is a gem thats main purpose is to make it easier to effectively fragment cache in dynamic fashions in Rails.
|
@@ -55,17 +80,13 @@ For a simple application you could do something like this.
|
|
55
80
|
|
56
81
|
def show
|
57
82
|
|
58
|
-
|
83
|
+
calls_sitta :name => "page", :section => "body" do
|
59
84
|
if params[:url]
|
60
85
|
@page = Page.find_by_url params[:url]
|
61
86
|
else
|
62
87
|
@page = Page.find_by_url 'home'
|
63
88
|
end
|
64
|
-
|
65
|
-
|
66
|
-
@body_calls = [
|
67
|
-
['page', @page_call]
|
68
|
-
]
|
89
|
+
end
|
69
90
|
|
70
91
|
end
|
71
92
|
|
@@ -76,17 +97,15 @@ For a simple application you could do something like this.
|
|
76
97
|
- cache_sitta :model => Page, :route_id => params[:url], :section => "body" do
|
77
98
|
= @page.content.try(:html_safe)
|
78
99
|
|
79
|
-
First off lets look at
|
100
|
+
First off lets look at calls_sitta. The view helper method cache_sitta will look for its calls at @#{:section}_calls. The method calls_sitta in the controller will append its provided block or proc (:block => yourproc) to @#{:section}_calls.
|
80
101
|
|
81
|
-
Second off
|
82
|
-
|
83
|
-
@page = @page_call.call
|
102
|
+
Second off @#{:section}_calls is an array of arrays. This is because you can have multiple calls, and each call must be given a target instance variable ie name ('page' in this instance) and a call object (the provide proc or block). They must also be ordered thus the array and not a hash.
|
84
103
|
|
85
104
|
You can also pass your calls options by providing :calls_args to the helper. You must though set up your calls to expect an options hash.
|
86
105
|
|
87
106
|
:route_id and :model must be provide so that the cache can be associated with the correct object, and the cache clear when its supposed to.
|
88
107
|
|
89
|
-
:route_id must also be a
|
108
|
+
:route_id must also be a unique field on the model, other wise the cache won't connect properly to the object.
|
90
109
|
|
91
110
|
For an index page you could do something like the following for a simple app.
|
92
111
|
|
@@ -104,13 +123,9 @@ For an index page you could do something like the following for a simple app.
|
|
104
123
|
|
105
124
|
def index
|
106
125
|
|
107
|
-
|
126
|
+
calls_sitta :name => "blogs", :section => "body" do
|
108
127
|
@blogs = Blog.all
|
109
|
-
|
110
|
-
|
111
|
-
@body_calls = [
|
112
|
-
['blogs', @blogs_call]
|
113
|
-
]
|
128
|
+
end
|
114
129
|
|
115
130
|
end
|
116
131
|
|
@@ -200,6 +215,10 @@ This amounts to a very small specific cache_sitta call. For now its suggested to
|
|
200
215
|
|
201
216
|
More examples to come in the wiki, and in the coming example app.
|
202
217
|
|
218
|
+
Also if for what ever reason you have made your app multi threaded this gem will break. If your interested in possible making it multithread safe the following link has some good info.
|
219
|
+
|
220
|
+
http://stackoverflow.com/a/1390978/1436131
|
221
|
+
|
203
222
|
===This gem should be considered in early beta and highly unstable. Do not use in a production app!
|
204
223
|
|
205
224
|
MIT License
|
@@ -8,24 +8,25 @@ module FlagpoleSittaHelper
|
|
8
8
|
model.try(:update_array_cache, key, route_id)
|
9
9
|
end
|
10
10
|
|
11
|
+
##
|
11
12
|
#AR - cache_sitta helper
|
12
13
|
#NOTE This is not safe for .builder xml files.
|
13
14
|
#Options
|
14
|
-
|
15
|
+
#
|
15
16
|
#:section
|
16
17
|
#The section of the page the cache represents. This is
|
17
18
|
#best used in connection with -content_for. Can be any
|
18
19
|
#string you want it to be. If not provided will default to
|
19
20
|
#body. Also looks for the calls using sections. Will assume calls
|
20
21
|
#are in the instance variable '@#{options[:section]_calls'
|
21
|
-
|
22
|
+
#
|
22
23
|
#:model
|
23
24
|
#The model of the object, or objects that you want to link
|
24
25
|
#the cache too. Pass the actually model, or an array of models.
|
25
26
|
#Must also have a corresponding route_id. If model is an array,
|
26
27
|
#route_id must also be an array of equal length. model[i] is
|
27
28
|
#connected to route_id[i].
|
28
|
-
|
29
|
+
#
|
29
30
|
#:route_id
|
30
31
|
#The unique identifier of the object, most likely what you route on
|
31
32
|
#for showing the object or objects that you want to link
|
@@ -33,7 +34,7 @@ module FlagpoleSittaHelper
|
|
33
34
|
#Must also have a corresponding model. If route_id is an array,
|
34
35
|
#model must also be an array of equal length. model[i] is
|
35
36
|
#connected to route_id[i].
|
36
|
-
|
37
|
+
#
|
37
38
|
#:models_in_index
|
38
39
|
#Use this if the fragment you are rendering is an index
|
39
40
|
#pass it all the different types of models/classes could be
|
@@ -41,19 +42,19 @@ module FlagpoleSittaHelper
|
|
41
42
|
#sitta enabled. The cache for the used index pages will then be
|
42
43
|
#wiped clear when anyone of these models/classes has an object
|
43
44
|
#created or updated.
|
44
|
-
|
45
|
+
#
|
45
46
|
#:index_only
|
46
47
|
#Use this if the cache should not be associated with any object,
|
47
48
|
#but rather only a model. Use this if your cache is an index, or
|
48
49
|
#can be 'random'.
|
49
|
-
|
50
|
+
#
|
50
51
|
#:sub_route_id
|
51
52
|
#Use this if options on the url can result in a difference in
|
52
53
|
#the cache. So if you had an page where you could pass
|
53
54
|
#in a year and month would be a great place for this.
|
54
55
|
#That way your caching each possible version of the page
|
55
56
|
#instead of just one.
|
56
|
-
|
57
|
+
#
|
57
58
|
#:calls_args
|
58
59
|
#Any args you want to pass to your calls. Can only take one argument.
|
59
60
|
#The best idea is to pass an option hash.
|
data/flagpole_sitta.gemspec
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
require File.expand_path("../lib/flagpole_sitta/version", __FILE__)
|
2
2
|
|
3
|
-
# Provide a simple gemspec so you can easily use your enginex
|
4
|
-
# project in your rails apps through git.
|
5
3
|
Gem::Specification.new do |s|
|
6
4
|
s.name = "flagpole_sitta"
|
7
5
|
s.version = FlagpoleSitta::VERSION
|
@@ -16,8 +14,7 @@ Gem::Specification.new do |s|
|
|
16
14
|
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
17
15
|
s.require_path = 'lib'
|
18
16
|
|
19
|
-
#
|
20
|
-
|
17
|
+
#Dependencies
|
21
18
|
s.add_dependency('dalli')
|
22
19
|
|
23
20
|
end
|
@@ -1,9 +1,10 @@
|
|
1
1
|
module FlagpoleSitta
|
2
|
+
##
|
3
|
+
#Used for getting and caching settings or html fragments stored in the database.
|
2
4
|
module BracketRetrieval
|
3
5
|
|
4
6
|
extend ActiveSupport::Concern
|
5
7
|
|
6
|
-
#When forcing a call back into a class from a module you must do it inside an include block
|
7
8
|
included do
|
8
9
|
validates_uniqueness_of (@_key_field || "name").to_sym
|
9
10
|
validates_presence_of (@_key_field || "name").to_sym
|
@@ -19,13 +20,16 @@ module FlagpoleSitta
|
|
19
20
|
self.br_update(false)
|
20
21
|
end
|
21
22
|
|
23
|
+
#After update destroy old cache and write new one.
|
22
24
|
def br_update alive
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
clazz = self.class
|
26
|
+
|
27
|
+
Rails.cache.delete("#{clazz}/BracketRetrieval/#{self.send(self.class.key_field + "_was")}")
|
28
|
+
|
29
|
+
if alive
|
30
|
+
Rails.cache.write("#{clazz}/BracketRetrieval/#{self.send(self.class.key_field)}", self.send(self.class.value_field))
|
28
31
|
end
|
32
|
+
|
29
33
|
end
|
30
34
|
|
31
35
|
module ClassMethods
|
@@ -45,20 +49,16 @@ module FlagpoleSitta
|
|
45
49
|
result = @_value_field || (self.superclass.respond_to?(:value_field) ? self.superclass.value_field : nil) || "content"
|
46
50
|
end
|
47
51
|
|
48
|
-
#Will look up the object chain till it finds what it was set to, or not set too.
|
52
|
+
#Will look up the object chain till it finds what it was set to, or not set too.
|
53
|
+
#Default value cannot be nil.
|
49
54
|
def default_value
|
50
55
|
result = @_default_value || (self.superclass.respond_to?(:default_value) ? self.superclass.default_value : nil) || ""
|
51
56
|
end
|
52
57
|
|
53
58
|
def [] key
|
54
|
-
|
55
|
-
#If its in cache return that, unless blank, then return nil
|
56
|
-
|
57
|
-
#then return it.
|
58
|
-
#else create the corresponding object as blank, and return nil.
|
59
|
-
#The last line there is why this extension should never be used
|
60
|
-
#with user generated content.
|
61
|
-
if value = Rails.cache.read("#{downcased}/#{key}") || Rails.cache.exist?("#{downcased}/#{key}")
|
59
|
+
clazz = self
|
60
|
+
#If its in cache return that, unless blank, then return nil.
|
61
|
+
if value = Rails.cache.read("#{clazz}/BracketRetrieval/#{key}") || Rails.cache.exist?("#{clazz}/BracketRetrieval/#{key}")
|
62
62
|
if value.present?
|
63
63
|
value = self.safe_content? ? value.html_safe : value
|
64
64
|
else
|
@@ -67,13 +67,16 @@ module FlagpoleSitta
|
|
67
67
|
#thus the reason for this odd nested if statement.
|
68
68
|
value = nil
|
69
69
|
end
|
70
|
+
#Else if the object is in the database put it into the cache then return it.
|
70
71
|
elsif obj = self.send("find_by_#{self.key_field}", key)
|
71
72
|
value = obj.send(self.value_field)
|
72
|
-
Rails.cache.write("#{
|
73
|
+
Rails.cache.write("#{clazz}/BracketRetrieval/#{key}", value)
|
73
74
|
value = value && self.safe_content? ? value.html_safe : value
|
75
|
+
#Else create the corresponding object as blank, and return nil.
|
76
|
+
#The last line there is why this extension should never be used with user generated content.
|
74
77
|
else
|
75
78
|
rec = self.create(self.key_field.to_sym => key, self.value_field.to_sym => self.default_value)
|
76
|
-
Rails.cache.write("#{
|
79
|
+
Rails.cache.write("#{clazz}/BracketRetrieval/#{key}", rec.send(self.value_field))
|
77
80
|
value = nil
|
78
81
|
end
|
79
82
|
value
|
@@ -1,8 +1,13 @@
|
|
1
1
|
module FlagpoleSitta
|
2
|
+
##
|
3
|
+
#CacheSitta's main purpose is to make it easier to effectively fragment cache in dynamic fashions in Rails.
|
4
|
+
#
|
5
|
+
#When ever a cache is created it is associated with any model and/or record you tell it to be from the view helper method. When that model and/or record is updated all it’s associated caches are cleared.
|
6
|
+
#
|
7
|
+
#Flagpole also expects you to put all your database calls into Procs/Lamdbas. This makes it so that your database calls wont have to happen unless your cache hasn’t been created. Thus speeding up response time and reducing database traffic.
|
2
8
|
module CacheSitta
|
3
9
|
extend ActiveSupport::Concern
|
4
10
|
|
5
|
-
#When forcing a call back into a class from a module you must do it inside an include block
|
6
11
|
included do
|
7
12
|
before_save :cache_sitta_save
|
8
13
|
before_destroy :cache_sitta_destory
|
@@ -10,6 +15,7 @@ module FlagpoleSitta
|
|
10
15
|
|
11
16
|
module ClassMethods
|
12
17
|
|
18
|
+
#Determines if its for an index array or show array.
|
13
19
|
def mid_key_gen route_id
|
14
20
|
if route_id
|
15
21
|
mid_key = "#{route_id}/ShowArray"
|
@@ -18,6 +24,7 @@ module FlagpoleSitta
|
|
18
24
|
end
|
19
25
|
end
|
20
26
|
|
27
|
+
#Creates the 'array' in the cache.
|
21
28
|
def initialize_array_cache route_id = nil
|
22
29
|
|
23
30
|
|
@@ -33,6 +40,7 @@ module FlagpoleSitta
|
|
33
40
|
|
34
41
|
end
|
35
42
|
|
43
|
+
#Updates the 'array' in the cache.
|
36
44
|
def update_array_cache key, route_id = nil
|
37
45
|
|
38
46
|
mid_key = mid_key_gen route_id
|
@@ -57,6 +65,7 @@ module FlagpoleSitta
|
|
57
65
|
|
58
66
|
end
|
59
67
|
|
68
|
+
#Loops through the array in the cache.
|
60
69
|
def each_cache route_id = nil, &block
|
61
70
|
|
62
71
|
mid_key = mid_key_gen route_id
|
@@ -84,6 +93,7 @@ module FlagpoleSitta
|
|
84
93
|
|
85
94
|
end
|
86
95
|
|
96
|
+
#Nukes all corresponding caches for a given array.
|
87
97
|
def destroy_array_cache route_id = nil
|
88
98
|
|
89
99
|
mid_key = mid_key_gen route_id
|
@@ -107,6 +117,7 @@ module FlagpoleSitta
|
|
107
117
|
self.cache_work(false)
|
108
118
|
end
|
109
119
|
|
120
|
+
#Updates the cache after update of any cache sittaed item.
|
110
121
|
def cache_work(alive)
|
111
122
|
original_clazz = self.class
|
112
123
|
# Also have to go through all its super objects till the super objects aren't cache sittaed
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module FlagpoleSitta
|
2
|
+
module ControllerSitta
|
3
|
+
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
##
|
7
|
+
#Creates adds the block or provided proc or lamdba to the given
|
8
|
+
#section or sections call array. These calls backs are then used by
|
9
|
+
#the cache_sitta view helper.
|
10
|
+
#
|
11
|
+
#:section the section or sections the block will be connected too. Array or String.
|
12
|
+
#
|
13
|
+
#:name the name of the instance variable the returned value of the block String
|
14
|
+
#will be stored at. Ie 'blog' would result in @blog.
|
15
|
+
#
|
16
|
+
#:block you can pass in an already defined proc or lamdba instead of a block. Proc pr lamdba
|
17
|
+
#
|
18
|
+
def calls_sitta options={}, &block
|
19
|
+
|
20
|
+
options[:section] ? (section = options[:section]) : (section = "body")
|
21
|
+
|
22
|
+
options[:name] ? (name = options[:name]) : (name = "object")
|
23
|
+
|
24
|
+
if section.class.eql?(Array)
|
25
|
+
section.each do |s|
|
26
|
+
if options[:block]
|
27
|
+
calls_sitta_set(s, name, options[:block])
|
28
|
+
else
|
29
|
+
calls_sitta_set(s, name, block)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
else
|
33
|
+
if options[:block]
|
34
|
+
calls_sitta_set(section, name, options[:block])
|
35
|
+
else
|
36
|
+
calls_sitta_set(section, name, block)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
#Takes the predefined blocks from one section and adds them to one or more other sections.
|
44
|
+
#
|
45
|
+
#:frome_section from where you want to copy. String
|
46
|
+
#
|
47
|
+
#:to_section the section or sections you want to copy to. String or Array.
|
48
|
+
def calls_sitta_append options={}
|
49
|
+
|
50
|
+
calls_sitta_init options[:from_section]
|
51
|
+
|
52
|
+
if options[:to_section].class.eql?(Array)
|
53
|
+
options[:to_section].each do |s|
|
54
|
+
calls_sitta_init s
|
55
|
+
instance_variable_set("@#{s}_calls",
|
56
|
+
instance_variable_get("@#{s}_calls") + instance_variable_get("@#{options[:from_section]}_calls")
|
57
|
+
)
|
58
|
+
end
|
59
|
+
else
|
60
|
+
calls_sitta_init options[:to_section]
|
61
|
+
instance_variable_set("@#{options[:to_section]}_calls",
|
62
|
+
instance_variable_get("@#{options[:to_section]}_calls") + instance_variable_get("@#{options[:from_section]}_calls")
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
##
|
69
|
+
# Make sure the instance variable has the correct starting value.
|
70
|
+
def calls_sitta_init section
|
71
|
+
if !instance_variable_defined?("@#{section}_calls")
|
72
|
+
instance_variable_set("@#{section}_calls", [])
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
##
|
77
|
+
# A method to help dry out calls_sitta
|
78
|
+
def calls_sitta_set section, name, block
|
79
|
+
|
80
|
+
calls_sitta_init section
|
81
|
+
|
82
|
+
instance_variable_set("@#{section}_calls",
|
83
|
+
instance_variable_get("@#{section}_calls") + [[name, block]]
|
84
|
+
)
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
ActionController::Base.send(:include, FlagpoleSitta::ControllerSitta)
|
@@ -1,4 +1,6 @@
|
|
1
1
|
module FlagpoleSitta
|
2
|
+
##
|
3
|
+
#A ‘hash’ in the cache which you can use to check for the existence of an object
|
2
4
|
module ExistenceHash
|
3
5
|
|
4
6
|
extend ActiveSupport::Concern
|
@@ -10,30 +12,56 @@ module FlagpoleSitta
|
|
10
12
|
|
11
13
|
module ClassMethods
|
12
14
|
|
15
|
+
#Creates the 'hash' in the cache.
|
16
|
+
def initialize_existence_hash
|
17
|
+
|
18
|
+
superclazz = get_super_with_existence_hash
|
19
|
+
|
20
|
+
#Used to emulate an array, keeps the stored count and space. The space is not actually a count of existing entries, but rather how long
|
21
|
+
#the 'container' goes, it starts at 0, so thats why 1 is subtracted. The count is well the count. They should start out the same.
|
22
|
+
count = superclazz.count
|
23
|
+
|
24
|
+
flag = {:space => (count - 1), :count => count}
|
25
|
+
|
26
|
+
Rails.cache.write("#{superclazz}/ExistenceHash/Flag", flag)
|
27
|
+
i = 0
|
28
|
+
superclazz.find_each do |m|
|
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})
|
32
|
+
i = i + 1
|
33
|
+
end
|
34
|
+
|
35
|
+
flag
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
#Gets a value from the 'hash' in the cache given a key.
|
13
40
|
def get_existence_hash key
|
14
41
|
|
15
|
-
|
42
|
+
superclazz = get_super_with_existence_hash
|
16
43
|
#Try to find the hash
|
17
|
-
flag = Rails.cache.read("#{
|
44
|
+
flag = Rails.cache.read("#{superclazz}/ExistenceHash/Flag")
|
18
45
|
#If it doesn't exist start the process of creating it
|
19
46
|
if flag.nil?
|
20
47
|
initialize_existence_hash
|
21
48
|
end
|
22
49
|
|
23
|
-
Rails.cache.read("#{
|
50
|
+
Rails.cache.read("#{superclazz}/ExistenceHash/#{key}")
|
24
51
|
|
25
52
|
end
|
26
53
|
|
54
|
+
#Increments a value from the 'hash' in the cache given a key.
|
27
55
|
def increment_existence_hash key
|
28
56
|
|
29
|
-
|
57
|
+
superclazz = get_super_with_existence_hash
|
30
58
|
#Try to find the hash
|
31
59
|
hash = get_existence_hash key
|
32
60
|
|
33
61
|
#Update the hash key if it exists
|
34
62
|
if hash
|
35
63
|
hash[:num] = hash[:num] + 1
|
36
|
-
Rails.cache.write("#{
|
64
|
+
Rails.cache.write("#{superclazz}/ExistenceHash/#{key}", hash)
|
37
65
|
end
|
38
66
|
|
39
67
|
#Return the value
|
@@ -41,55 +69,12 @@ module FlagpoleSitta
|
|
41
69
|
|
42
70
|
end
|
43
71
|
|
44
|
-
|
45
|
-
|
46
|
-
if @_existence_hash_main_class.nil?
|
47
|
-
|
48
|
-
c = self
|
49
|
-
#Get the original super class that declares the existence hash
|
50
|
-
|
51
|
-
while(c.superclass.respond_to? :get_existence_hash)
|
52
|
-
c = c.superclass
|
53
|
-
end
|
54
|
-
|
55
|
-
@_existence_hash_main_class = c
|
56
|
-
|
57
|
-
end
|
58
|
-
|
59
|
-
@_existence_hash_main_class
|
60
|
-
|
61
|
-
end
|
62
|
-
|
63
|
-
def initialize_existence_hash
|
64
|
-
|
65
|
-
c = get_super_with_existence_hash
|
66
|
-
|
67
|
-
dcname = c.name.downcase
|
68
|
-
|
69
|
-
#Used to emulate an array, keeps the stored count and space. The space is not actually a count of existing entries, but rather how long
|
70
|
-
#the 'container' goes, it starts at 0, so thats why 1 is subtracted. The count is well the count. They should start out the same.
|
71
|
-
count = c.count
|
72
|
-
|
73
|
-
flag = {:space => (count - 1), :count => count}
|
74
|
-
|
75
|
-
Rails.cache.write("#{dcname}_existence_hash_flag", flag)
|
76
|
-
i = 0
|
77
|
-
c.find_each do |m|
|
78
|
-
#Route ID is the key. The POS is used to emulate an array, along with the length stored in the flag.
|
79
|
-
Rails.cache.write("#{dcname}_existence_hash/#{m.send(c.route_id).to_s}", {:type => m.has_attribute?('type') ? m.type : m.class, :pos => i, :num => 0})
|
80
|
-
Rails.cache.write("#{dcname}_existence_hash/#{i}", {:key => m.send(c.route_id).to_s})
|
81
|
-
i = i + 1
|
82
|
-
end
|
83
|
-
|
84
|
-
flag
|
85
|
-
|
86
|
-
end
|
87
|
-
|
72
|
+
#Goes through each entry in the hash returning a key and value
|
88
73
|
def each_existence_hash &block
|
89
74
|
|
90
|
-
|
75
|
+
superclazz = get_super_with_existence_hash
|
91
76
|
|
92
|
-
flag = Rails.cache.read("#{
|
77
|
+
flag = Rails.cache.read("#{superclazz}/ExistenceHash/Flag")
|
93
78
|
|
94
79
|
if flag.nil?
|
95
80
|
flag = initialize_existence_hash
|
@@ -98,10 +83,10 @@ module FlagpoleSitta
|
|
98
83
|
unless flag[:count] == 0
|
99
84
|
for i in 0..flag[:space] do
|
100
85
|
|
101
|
-
value = Rails.cache.read("#{
|
86
|
+
value = Rails.cache.read("#{superclazz}/ExistenceHash/#{i}")
|
102
87
|
|
103
88
|
if value.present?
|
104
|
-
hash = Rails.cache.read("#{
|
89
|
+
hash = Rails.cache.read("#{superclazz}/ExistenceHash/#{value[:key]}")
|
105
90
|
yield value[:key], hash
|
106
91
|
end
|
107
92
|
|
@@ -112,6 +97,26 @@ module FlagpoleSitta
|
|
112
97
|
|
113
98
|
end
|
114
99
|
|
100
|
+
#Gets its original super class.
|
101
|
+
def get_super_with_existence_hash
|
102
|
+
|
103
|
+
if @_existence_hash_main_class.nil?
|
104
|
+
|
105
|
+
c = self
|
106
|
+
#Get the original super class that declares the existence hash
|
107
|
+
|
108
|
+
while(c.superclass.respond_to? :get_existence_hash)
|
109
|
+
c = c.superclass
|
110
|
+
end
|
111
|
+
|
112
|
+
@_existence_hash_main_class = c
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
@_existence_hash_main_class
|
117
|
+
|
118
|
+
end
|
119
|
+
|
115
120
|
end
|
116
121
|
|
117
122
|
def existence_hash_save_update
|
@@ -122,41 +127,43 @@ module FlagpoleSitta
|
|
122
127
|
self.update_existence_hash(false)
|
123
128
|
end
|
124
129
|
|
130
|
+
#Updates the 'hash' on save of any of its records.
|
125
131
|
def update_existence_hash alive
|
126
|
-
|
127
|
-
dcname = c.name.downcase
|
132
|
+
superclazz = self.class.get_super_with_existence_hash
|
128
133
|
|
129
134
|
#Old key is where it was, and new is where it is going.
|
130
135
|
old_key = self.send("#{self.class.route_id}_was")
|
131
136
|
new_key = self.send("#{self.class.route_id}")
|
132
137
|
|
133
|
-
flag = Rails.cache.read("#{
|
138
|
+
flag = Rails.cache.read("#{superclazz}/ExistenceHash/Flag")
|
134
139
|
|
135
140
|
#If it had a route_id before it most of existed. So get its old values from the existence hash.
|
136
141
|
#If there was nothing it didn't exist so create a new one. Also it only creates a new one if alive is set to true.
|
137
142
|
#This check is overkill really, but its just to be safe.
|
138
|
-
|
139
|
-
|
140
|
-
Rails.cache.delete("#{dcname}_existence_hash/#{old_key}")
|
141
|
-
elsif alive
|
143
|
+
|
144
|
+
if self.new_record?
|
142
145
|
flag[:count] = flag[:count] + 1
|
143
146
|
flag[:space] = flag[:space] + 1
|
144
147
|
hash = {:type => self.has_attribute?('type') ? self.type : self.class, :num => 0, :pos => flag[:space]}
|
148
|
+
else
|
149
|
+
hash = self.class.get_existence_hash(self.send("#{self.class.route_id}_was"))
|
150
|
+
Rails.cache.delete("#{superclazz}/ExistenceHash/#{old_key}")
|
145
151
|
end
|
146
152
|
|
147
153
|
#If the record is not being destroyed add new route_id to existence hash
|
148
154
|
if alive
|
149
|
-
Rails.cache.write("#{
|
150
|
-
Rails.cache.write("#{
|
151
|
-
|
155
|
+
Rails.cache.write("#{superclazz}/ExistenceHash/#{new_key}", hash)
|
156
|
+
Rails.cache.write("#{superclazz}/ExistenceHash/#{hash[:pos]}", {:key => new_key})
|
157
|
+
#The following check is needed if for some reason someone does destroy on a none saved record.
|
158
|
+
elsif !self.new_record?
|
152
159
|
if hash[:pos] == flag[:space]
|
153
160
|
flag[:space] = flag[:space] - 1
|
154
161
|
end
|
155
162
|
flag[:count] = flag[:count] - 1
|
156
|
-
Rails.cache.delete("#{
|
163
|
+
Rails.cache.delete("#{superclazz}/ExistenceHash/#{hash[:pos]}")
|
157
164
|
end
|
158
165
|
|
159
|
-
Rails.cache.write("#{
|
166
|
+
Rails.cache.write("#{superclazz}/ExistenceHash/Flag", flag)
|
160
167
|
|
161
168
|
end
|
162
169
|
|
data/lib/flagpole_sitta.rb
CHANGED
@@ -16,5 +16,6 @@ require 'flagpole_sitta/cache_sitta'
|
|
16
16
|
require 'flagpole_sitta/existence_hash'
|
17
17
|
require 'flagpole_sitta/engine'
|
18
18
|
require 'flagpole_sitta/config_sitta'
|
19
|
+
require 'flagpole_sitta/controller_sitta'
|
19
20
|
|
20
21
|
ActiveRecord::Base.send(:include, FlagpoleSitta::ConfigSitta)
|
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.7.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-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: dalli
|
@@ -53,6 +53,7 @@ files:
|
|
53
53
|
- lib/flagpole_sitta/bracket_retrieval.rb
|
54
54
|
- lib/flagpole_sitta/cache_sitta.rb
|
55
55
|
- lib/flagpole_sitta/config_sitta.rb
|
56
|
+
- lib/flagpole_sitta/controller_sitta.rb
|
56
57
|
- lib/flagpole_sitta/engine.rb
|
57
58
|
- lib/flagpole_sitta/existence_hash.rb
|
58
59
|
- lib/flagpole_sitta/version.rb
|