cachely 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +22 -3
- data/db/migrate/002_create_dummy_model_2.rb +8 -0
- data/lib/cachely.rb +4 -4
- data/lib/cachely/mechanics.rb +80 -16
- data/lib/cachely/version.rb +1 -1
- data/test/models/dummy_class.rb +19 -2
- data/test/models/dummy_class_2.rb +8 -0
- data/test/models/dummy_model.rb +7 -0
- data/test/models/dummy_model_two.rb +20 -0
- data/test/unit/base_test.rb +7 -5
- data/test/unit/cachely_test.rb +20 -1
- data/test/unit/conversions_test.rb +19 -2
- data/test/unit/mechanics_test.rb +16 -1
- metadata +15 -10
data/README.md
CHANGED
@@ -43,8 +43,8 @@ In order to make this work, you must connect to a redis store using the method:
|
|
43
43
|
|
44
44
|
Cachely::Mechanics.connect(opts = {})
|
45
45
|
|
46
|
-
Opts accepts keys :host, :port, :password, :driver. See redis-rb documentation for which drivers you want,
|
47
|
-
including whether or not you wish it to be evented.
|
46
|
+
Opts accepts keys :host, :port, :password, :driver, and :logging. See redis-rb documentation for which drivers you want,
|
47
|
+
including whether or not you wish it to be evented. The :logging key is cachely only, it turns on performance logging.
|
48
48
|
|
49
49
|
I'd recommend doing this in a Rails initializer, or if you're using sinatra or other rack app, in config.ru.
|
50
50
|
|
@@ -85,6 +85,22 @@ Want to wipe all keys?
|
|
85
85
|
|
86
86
|
And done.
|
87
87
|
|
88
|
+
## to_json, the all important method
|
89
|
+
|
90
|
+
Cachely relies on the to_json method of objects extensively to work. ActiveRecord to_json methods are supported, as well as to_jsons
|
91
|
+
on primitives and what not. If you deign to write your own to_json for your objects, including ARs, good for you, you should. But you should know
|
92
|
+
that cachely works partially by instantiating a new instance of your class and calling to_json on it without setting any associations. So, if your to_json method is
|
93
|
+
|
94
|
+
def to_json
|
95
|
+
{
|
96
|
+
"stuff": self.stuff.id
|
97
|
+
}.to_json
|
98
|
+
end
|
99
|
+
|
100
|
+
Where stuff is some kind of association, it will destroy cachely, because when cachely instantiates this new object with no fields just to get a look at it's field structure,
|
101
|
+
it's going to call id on a nil class(stuff is unset.) So think about this when you write to_json methods. I can't protect you from your own stupidity, you really should
|
102
|
+
be checking for nilness before you call id. I recommend the gem andand.
|
103
|
+
|
88
104
|
## Caveats
|
89
105
|
|
90
106
|
CAVEAT 1: Do NOT use Cachely for functions that depend on time of day or random numbers, as these are inherently uncachable.
|
@@ -105,7 +121,10 @@ has circular references to itself, don't use cachely then, either.
|
|
105
121
|
One exception is ActiveRecord objects, which have already been fixed in this regard. There are three tests in conversion_tests.rb that fail still that deal with this
|
106
122
|
caveat. I'll be fixing them in the future and we'll be one caveat shorter.
|
107
123
|
|
108
|
-
|
124
|
+
CAVEAT 3: Do not use Cachely if you are altering arguments that you pass into the method. Cachely isn't running the method if it has a response already stored, so obviously your argument will remain unchanged. I guess I could add support for this in the future, but this is a bit of a complex, nuanced addition and I'd rather not worry about it now.
|
125
|
+
|
126
|
+
CAVEAT 4: Do not use on functions that return ActiveRecord::Relation objects, or use them as arguments. They can't be instantiated normally and I haven't added support for them yet. I have added two tests for them, and they still fail. So if you can write a fix, and it passes these tests, go for it!
|
127
|
+
|
109
128
|
## Installation
|
110
129
|
|
111
130
|
Add this line to your application's Gemfile:
|
data/lib/cachely.rb
CHANGED
@@ -13,9 +13,9 @@ module Cachely
|
|
13
13
|
# @name [Symbol] fcn name
|
14
14
|
# @return nil
|
15
15
|
def singleton_method_added(name)
|
16
|
-
if(@cachely_fcns and @cachely_fcns.include?(name) and !self.respond_to?("#{name.to_s}_old".to_sym))
|
16
|
+
if(@cachely_fcns and @cachely_fcns.include?(name) and !self.respond_to?("#{name.to_s.gsub("?",'')}_old".to_sym))
|
17
17
|
unless(@cachely_opts[name][:type] and @cachely_opts[name][:type] == "instance")
|
18
|
-
self.instance_eval("alias :#{"#{name.to_s}_old".to_sym} :#{name}")
|
18
|
+
self.instance_eval("alias :#{"#{name.to_s.gsub("?",'')}_old".to_sym} :#{name}")
|
19
19
|
Cachely::Mechanics.setup_method(self,name, @cachely_opts[name][:time_to_expiry], true)
|
20
20
|
end
|
21
21
|
end
|
@@ -28,10 +28,10 @@ module Cachely
|
|
28
28
|
# @name [Symbol] fcn name
|
29
29
|
# @return nil
|
30
30
|
def method_added(name)
|
31
|
-
if(@cachely_fcns and @cachely_fcns.include?(name) and !self.new.respond_to?("#{name.to_s}_old".to_sym))
|
31
|
+
if(@cachely_fcns and @cachely_fcns.include?(name) and !self.new.respond_to?("#{name.to_s.gsub("?",'')}_old".to_sym))
|
32
32
|
# only do this if we either haven't explicitly labeled fcn type, or it's not class.
|
33
33
|
unless(@cachely_opts[name][:type] and @cachely_opts[name][:type] == "class")
|
34
|
-
self.class_eval("alias :#{"#{name.to_s}_old".to_sym} :#{name}") #alias old function out
|
34
|
+
self.class_eval("alias :#{"#{name.to_s.gsub("?",'')}_old".to_sym} :#{name}") #alias old function out
|
35
35
|
Cachely::Mechanics.setup_method(self,name, @cachely_opts[name][:time_to_expiry])
|
36
36
|
end
|
37
37
|
end
|
data/lib/cachely/mechanics.rb
CHANGED
@@ -7,11 +7,24 @@ module Cachely
|
|
7
7
|
# @opt [Hash<Symbol>]
|
8
8
|
# @return [Boolean] success or not
|
9
9
|
def self.connect(opts = {})
|
10
|
+
@opts ||= opts.symbolize_keys
|
10
11
|
@redis ||= Redis.new(
|
11
|
-
:host => opts[:host],
|
12
|
-
:port => opts[:port],
|
13
|
-
:password => opts[:password],
|
14
|
-
:driver => opts[:driver])
|
12
|
+
:host => @opts[:host],
|
13
|
+
:port => @opts[:port],
|
14
|
+
:password => @opts[:password],
|
15
|
+
:driver => @opts[:driver])
|
16
|
+
@logging = @opts[:logging]
|
17
|
+
@logged_cached_calls_avg = 0
|
18
|
+
@logged_cached_calls_amt = 0
|
19
|
+
@logged_uncached_calls_avg = 0
|
20
|
+
@logged_uncached_calls_amt = 0
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns whether logging is present.
|
24
|
+
#
|
25
|
+
# @return [Boolean] Logging on or not
|
26
|
+
def self.logging
|
27
|
+
@logging
|
15
28
|
end
|
16
29
|
|
17
30
|
# Flush the Redis store of all keys.
|
@@ -46,17 +59,32 @@ module Cachely
|
|
46
59
|
# @return nil
|
47
60
|
def self.setup_method(klazz, name, time_to_expire_in_s, is_class_method = false)
|
48
61
|
context = (is_class_method ? klazz : klazz.new)
|
49
|
-
args_str = context.method("#{name.to_s}_old".to_sym).parameters.map { |k| k.last}.join(',')
|
62
|
+
args_str = context.method("#{name.to_s.gsub("?",'')}_old".to_sym).parameters.map { |k| k.last}.join(',')
|
50
63
|
args_to_use_in_def = args_str.empty? ? "" : "," + args_str
|
51
64
|
time_exp_str = time_to_expire_in_s.nil? ? ",nil" : ",time_to_expire_in_s"
|
52
|
-
|
53
|
-
|
65
|
+
|
66
|
+
to_def_header=nil
|
67
|
+
|
68
|
+
if is_class_method
|
69
|
+
to_def_header = "klazz.define_singleton_method(:#{name}) do"
|
70
|
+
else
|
71
|
+
to_def_header = "klazz.send(:define_method, :#{name}) do"
|
72
|
+
end
|
73
|
+
|
74
|
+
to_def = ("#{to_def_header} #{args_str.empty? ? "" : "|#{args_str}|"}; " +
|
75
|
+
"time_1 = Time.now;" +
|
76
|
+
"result = Cachely::Mechanics.get(self,:#{name}#{time_exp_str}#{args_to_use_in_def});" +
|
77
|
+
"time_2 = Time.now;" +
|
78
|
+
"total_time = time_2-time_1; p 'Whole call took ' + total_time.to_s if Cachely::Mechanics.logging and result.is_a?(Array);" +
|
54
79
|
"return result.first if result.is_a?(Array);" +
|
55
|
-
"result =
|
56
|
-
"Cachely::Mechanics.store(
|
80
|
+
"result = self.send(:#{"#{name.to_s.gsub("?",'')}_old"}#{args_to_use_in_def});" +
|
81
|
+
"Cachely::Mechanics.store(self,:#{"#{name.to_s}"}, result#{time_exp_str}#{args_to_use_in_def});" +
|
82
|
+
"time_2 = Time.now;" +
|
83
|
+
"total_time = time_2-time_1; p 'Whole call took ' + total_time.to_s if Cachely::Mechanics.logging;" +
|
57
84
|
"return result;" +
|
58
85
|
"end"
|
59
86
|
)
|
87
|
+
eval(to_def)
|
60
88
|
end
|
61
89
|
|
62
90
|
# Force-expires a result to a method with this signature given by obj, method, args.
|
@@ -64,14 +92,23 @@ module Cachely
|
|
64
92
|
# @obj [Object] the object you're calling method on
|
65
93
|
# @method [String,Symbol] the method name
|
66
94
|
# @args The arguments of the method
|
67
|
-
# @return The original response of the method back, whatever it may be.
|
95
|
+
# @return The original response of the method back, whatever it may be, or nil.
|
68
96
|
def self.expire(obj, method, *args)
|
69
97
|
key = redis_key(obj, method, *args)
|
70
98
|
result = get(obj,method,1,*args)
|
71
99
|
redis.del(key)
|
72
|
-
|
100
|
+
result.nil? ? nil : result.first
|
73
101
|
end
|
74
102
|
|
103
|
+
# returns avg cached and uncached response times for methods.
|
104
|
+
#
|
105
|
+
#
|
106
|
+
# @return [String] Info on methods
|
107
|
+
def self.monitoring
|
108
|
+
return "Avg cached call is currently #{@logged_cached_calls_avg.to_f/@logged_cached_calls_amt.to_f}" +
|
109
|
+
"Avg uncached call is currently #{@logged_uncached_calls_avg.to_f/@logged_uncached_calls_amt.to_f}"
|
110
|
+
end
|
111
|
+
|
75
112
|
# Gets a cached response to a method.
|
76
113
|
#
|
77
114
|
# @obj [Object] the object you're calling method on
|
@@ -81,9 +118,16 @@ module Cachely
|
|
81
118
|
# @return The original response of the method back, whatever it may be.
|
82
119
|
def self.get(obj, method, time_to_exp_in_s, *args)
|
83
120
|
key = redis_key(obj, method, *args)
|
121
|
+
time_1 = Time.now
|
84
122
|
result = redis.get(key)
|
123
|
+
time_2 = Time.now
|
124
|
+
p "GET for #{method} took #{time_2-time_1}" if @logging
|
85
125
|
if result
|
86
126
|
redis.expire(key, time_to_exp_in_s) if time_to_exp_in_s #reset the expiry
|
127
|
+
|
128
|
+
@logged_cached_calls_amt +=1
|
129
|
+
@logged_cached_calls_avg+=(time_2-time_1)
|
130
|
+
|
87
131
|
#return an array, bc if the result stored was nil, it looks the same as if
|
88
132
|
#we got no result back(which we would return nil) so we differentiate by putting
|
89
133
|
#our return value always in an array. Easy to check.
|
@@ -100,9 +144,17 @@ module Cachely
|
|
100
144
|
# @time_to_exp_in_s time in seconds before it expires
|
101
145
|
# @args Arguments of the method
|
102
146
|
# @return [String] Should be "Ok" or something similar.
|
103
|
-
def self.store(obj, method, result, time_to_exp_in_sec, *args)
|
147
|
+
def self.store(obj, method, result, time_to_exp_in_sec, *args)
|
148
|
+
time_1 = Time.now
|
104
149
|
redis.set(redis_key(obj, method, *args), map_param_to_s(result))
|
105
|
-
redis.expire(redis_key(obj, method, *args), time_to_exp_in_sec) if time_to_exp_in_sec
|
150
|
+
to_ret = redis.expire(redis_key(obj, method, *args), time_to_exp_in_sec) if time_to_exp_in_sec
|
151
|
+
time_2 = Time.now
|
152
|
+
p "STORE for #{method} took #{time_2-time_1}" if @logging
|
153
|
+
|
154
|
+
@logged_uncached_calls_amt+=1
|
155
|
+
@logged_uncached_calls_avg+=(time_2-time_1)
|
156
|
+
|
157
|
+
return to_ret
|
106
158
|
end
|
107
159
|
|
108
160
|
# Converts method name and arguments into a coherent key. Creates a hash and to_jsons it
|
@@ -172,9 +224,14 @@ module Cachely
|
|
172
224
|
return data
|
173
225
|
when "NilClass"
|
174
226
|
return nil
|
227
|
+
when "Time"
|
228
|
+
return DateTime.parse(data).to_time
|
229
|
+
when "DateTime"
|
230
|
+
return DateTime.parse(data)
|
231
|
+
when "Date"
|
232
|
+
return DateTime.parse(data).to_date
|
175
233
|
else
|
176
234
|
class_or_instance == "instance" ? obj = Object.const_get(type).new : obj = Object.const_get(type)
|
177
|
-
|
178
235
|
JSON.parse(data).each do |key, value|
|
179
236
|
obj.send(key+"=",value) if obj.respond_to?(key+"=")
|
180
237
|
end
|
@@ -211,9 +268,17 @@ module Cachely
|
|
211
268
|
translated = "instance|Fixnum|" + p.to_s
|
212
269
|
elsif p.is_a?(Float)
|
213
270
|
translated = "instance|Float|" + p.to_s
|
214
|
-
elsif p.is_a?(
|
271
|
+
elsif p.is_a?(Time)
|
272
|
+
translated = "instance|Time|" + p.to_s
|
273
|
+
elsif p.is_a?(DateTime)
|
274
|
+
translated = "instance|DateTime|" + p.to_s
|
275
|
+
elsif p.is_a?(Date)
|
276
|
+
translated = "instance|Date|" + p.to_s
|
277
|
+
elsif p.is_a?(ActiveRecord::Base) and JSON.parse(p.to_json)[p.class.to_s.underscore]
|
215
278
|
#don't want { "dummy_model" = > {:attributes => 1}}
|
216
279
|
#want {:attributes => 1}
|
280
|
+
#this is default AR to_json
|
281
|
+
#we use normal else below if own to_json method defined.
|
217
282
|
translated = "instance|#{p.class.to_s}|#{JSON.parse(p.to_json)[p.class.to_s.underscore].to_json}"
|
218
283
|
else
|
219
284
|
my_json = nil
|
@@ -222,7 +287,6 @@ module Cachely
|
|
222
287
|
rescue ActiveSupport::JSON::Encoding::CircularReferenceError => e
|
223
288
|
my_json = "{}"
|
224
289
|
end
|
225
|
-
|
226
290
|
translated = (p.to_s.match(/^#</) ? "instance|#{p.class}" : "class|#{p.to_s}") + "|"+ my_json
|
227
291
|
end
|
228
292
|
|
data/lib/cachely/version.rb
CHANGED
data/test/models/dummy_class.rb
CHANGED
@@ -6,7 +6,9 @@ class DummyClass
|
|
6
6
|
cachely :cache_expiry_3, time_to_expiry: 3.seconds
|
7
7
|
|
8
8
|
cachely :class_diff, time_to_expiry: 3.minutes
|
9
|
-
|
9
|
+
|
10
|
+
cachely :question_mark?
|
11
|
+
|
10
12
|
cachely :instance_only_cache, time_to_expiry: 3.minutes, type: "instance"
|
11
13
|
cachely :class_only_cache, time_to_expiry: 3.minutes, type: "class"
|
12
14
|
|
@@ -97,12 +99,27 @@ class DummyClass
|
|
97
99
|
cachely :class_to_json, time_to_expiry: 3.minutes
|
98
100
|
cachely :class_to_json_one, time_to_expiry: 3.minutes
|
99
101
|
cachely :class_to_json_two, time_to_expiry: 3.minutes
|
100
|
-
|
102
|
+
|
103
|
+
cachely :get_ar_relations
|
104
|
+
|
101
105
|
def to_json
|
102
106
|
{
|
103
107
|
"random_no" => self.random_no
|
104
108
|
}.to_json
|
105
109
|
end
|
110
|
+
|
111
|
+
def question_mark?
|
112
|
+
rand(500)
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.get_ar_relations
|
116
|
+
DummyModel.create!(:attr_1 => 1)
|
117
|
+
DummyModel.where(:attr_1=>1)
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.question_mark?
|
121
|
+
rand(500)
|
122
|
+
end
|
106
123
|
|
107
124
|
def instance_only_cache
|
108
125
|
rand(500)
|
data/test/models/dummy_model.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
class DummyModel < ActiveRecord::Base
|
2
|
+
include Cachely
|
3
|
+
cachely :use_attributes
|
4
|
+
|
2
5
|
attr_accessible :attr_1, :attr_2, :dummy_model_id
|
3
6
|
|
4
7
|
belongs_to :dummy_model, :foreign_key => :dummy_model_id
|
@@ -6,4 +9,8 @@ class DummyModel < ActiveRecord::Base
|
|
6
9
|
def instance_fixnum
|
7
10
|
rand(500)
|
8
11
|
end
|
12
|
+
|
13
|
+
def use_attributes
|
14
|
+
rand(500)/self.attr_1.to_i # if attr_1 is nil, this thing will throw a ZeroDivisionError. ;)
|
15
|
+
end
|
9
16
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class DummyModelTwo < ActiveRecord::Base
|
2
|
+
include Cachely
|
3
|
+
cachely :random
|
4
|
+
attr_accessible :attr_1
|
5
|
+
|
6
|
+
def random(arg)
|
7
|
+
rand(500)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.random(arg)
|
11
|
+
rand(500)
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_json
|
15
|
+
{
|
16
|
+
:id => self.id,
|
17
|
+
:attr_1 => self.attr_1
|
18
|
+
}.to_json
|
19
|
+
end
|
20
|
+
end
|
data/test/unit/base_test.rb
CHANGED
@@ -4,6 +4,13 @@ Bundler.require(:default, :test)
|
|
4
4
|
require 'yaml'
|
5
5
|
base_dir = File.expand_path(File.join(File.dirname(__FILE__), "../.."))
|
6
6
|
require base_dir + "/lib/cachely.rb"
|
7
|
+
|
8
|
+
database_config ||= YAML.load(File.open(File.dirname(__FILE__)+'/../../config/database.yml', 'r'))
|
9
|
+
ActiveRecord::Base.configurations = database_config
|
10
|
+
ActiveRecord::Base.establish_connection("test")
|
11
|
+
conf = YAML.load(File.read('./config/redis.yml'))
|
12
|
+
Cachely::Mechanics.connect(conf["test"])
|
13
|
+
|
7
14
|
require_relative '../models/dummy_model.rb'
|
8
15
|
require_relative '../models/dummy_model_two.rb'
|
9
16
|
require_relative '../models/dummy_class.rb'
|
@@ -11,11 +18,6 @@ require_relative '../models/dummy_class_2.rb'
|
|
11
18
|
|
12
19
|
class BaseTest < ActiveSupport::TestCase
|
13
20
|
def setup
|
14
|
-
database_config ||= YAML.load(File.open(File.dirname(__FILE__)+'/../../config/database.yml', 'r'))
|
15
|
-
ActiveRecord::Base.configurations = database_config
|
16
|
-
ActiveRecord::Base.establish_connection("test")
|
17
|
-
conf = YAML.load(File.read('./config/redis.yml'))
|
18
|
-
Cachely::Mechanics.connect(conf["test"])
|
19
21
|
Cachely::Mechanics.flush_all_keys
|
20
22
|
DummyModel.destroy_all
|
21
23
|
end
|
data/test/unit/cachely_test.rb
CHANGED
@@ -2,7 +2,26 @@ require_relative 'base_test.rb'
|
|
2
2
|
#This test level is for functionality that occurs at the cachely.rb level. Things that interact
|
3
3
|
#With the model.
|
4
4
|
class CachelyTest < BaseTest
|
5
|
-
|
5
|
+
|
6
|
+
test "caches output of methods in orm object" do
|
7
|
+
d = DummyModelTwo.create!(:attr_1 => rand(500))
|
8
|
+
assert_equal(d.random(5), d.random(5))
|
9
|
+
assert_equal(DummyModelTwo.random(5), DummyModelTwo.random(5))
|
10
|
+
end
|
11
|
+
|
12
|
+
test "caches output when its an ar relations object" do
|
13
|
+
assert_nothing_raised(NameError) do
|
14
|
+
DummyClass.get_ar_relations
|
15
|
+
DummyClass.get_ar_relations
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
test "caches output of question mark methods" do
|
20
|
+
d = DummyClass.new
|
21
|
+
assert_equal(d.question_mark?, d.question_mark?)
|
22
|
+
assert_equal(DummyClass.question_mark?, DummyClass.question_mark?)
|
23
|
+
end
|
24
|
+
|
6
25
|
test "caches output of instance and class methods primitive" do
|
7
26
|
["instance","class"].each do |preset|
|
8
27
|
[
|
@@ -92,7 +92,18 @@ class ConversionsTest < BaseTest
|
|
92
92
|
reformed = Cachely::Mechanics.map_s_to_param(str)
|
93
93
|
assert_equal(reformed, DummyClass)
|
94
94
|
end
|
95
|
-
|
95
|
+
|
96
|
+
test "orm where conversion" do
|
97
|
+
d = DummyModel.create!(:attr_1 => 1, :attr_2 => 2)
|
98
|
+
str = Cachely::Mechanics.map_param_to_s(DummyModel.where(:attr_1 => 1))
|
99
|
+
assert_nothing_raised(NameError) do
|
100
|
+
respawned = Cachely::Mechanics.map_s_to_param(str)
|
101
|
+
first = respawned.first
|
102
|
+
assert_equal(d.id, first.id)
|
103
|
+
assert_equal(d.attr_1, first.attr_1)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
96
107
|
test "orm conversion" do
|
97
108
|
d = DummyModel.create!(:attr_1 => rand(500), :attr_2 => rand(500))
|
98
109
|
str = Cachely::Mechanics.map_param_to_s(d)
|
@@ -110,6 +121,9 @@ class ConversionsTest < BaseTest
|
|
110
121
|
assert_equal("instance|String|1", Cachely::Mechanics.map_param_to_s("1"))
|
111
122
|
assert_equal("instance|NilClass|nil", Cachely::Mechanics.map_param_to_s(nil))
|
112
123
|
assert_equal("instance|Symbol|shit", Cachely::Mechanics.map_param_to_s(:shit))
|
124
|
+
assert_equal("instance|Time|2013-03-04 16:16:14 -0600", Cachely::Mechanics.map_param_to_s(Time.new(2013,03,04,16,16,14)))
|
125
|
+
assert_equal("instance|DateTime|2013-03-04T16:16:14-06:00", Cachely::Mechanics.map_param_to_s(DateTime.parse("2013-03-04T16:16:14-0600")))
|
126
|
+
assert_equal("instance|Date|2013-03-04", Cachely::Mechanics.map_param_to_s(Date.new(2013,03,04)))
|
113
127
|
assert_equal(true, Cachely::Mechanics.map_s_to_param("instance|TrueClass|true"))
|
114
128
|
assert_equal(false, Cachely::Mechanics.map_s_to_param("instance|FalseClass|false"))
|
115
129
|
assert_equal(1, Cachely::Mechanics.map_s_to_param("instance|Fixnum|1"))
|
@@ -118,6 +132,9 @@ class ConversionsTest < BaseTest
|
|
118
132
|
assert_equal("1|2", Cachely::Mechanics.map_s_to_param("instance|String|1|2"))
|
119
133
|
assert_equal(:shit, Cachely::Mechanics.map_s_to_param("instance|Symbol|shit"))
|
120
134
|
assert_equal(nil, Cachely::Mechanics.map_s_to_param("instance|NilClass|nil"))
|
121
|
-
|
135
|
+
assert_equal(Time.new(2013,03,04,16,16,14), Cachely::Mechanics.map_s_to_param("instance|Time|2013-03-04 16:16:14 -0600"))
|
136
|
+
assert_equal(DateTime.parse("2013-03-04T16:16:14-0600"), Cachely::Mechanics.map_s_to_param("instance|DateTime|2013-03-04T16:16:14-06:00"))
|
137
|
+
assert_equal(Date.new(2013,03,04), Cachely::Mechanics.map_s_to_param("instance|Date|2013-03-04"))
|
138
|
+
|
122
139
|
end
|
123
140
|
end
|
data/test/unit/mechanics_test.rb
CHANGED
@@ -14,7 +14,22 @@ class MechanicsTest < BaseTest
|
|
14
14
|
assert_equal(1, respawned.keys.size)
|
15
15
|
assert_equal("baz", respawned[:bar])
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
|
+
test "get/store orm with predefined to_json" do
|
19
|
+
d = DummyModelTwo.create!(:attr_1 => 1)
|
20
|
+
Cachely::Mechanics.store(DummyClass,:foo, d,nil,[3,4])
|
21
|
+
respawned = Cachely::Mechanics.get(DummyClass,:foo, nil, [3,4]).first
|
22
|
+
assert_equal(d.id, respawned.id)
|
23
|
+
assert_equal(d.attr_1, respawned.attr_1)
|
24
|
+
end
|
25
|
+
|
26
|
+
test "orm with method that depends on its attributes has its attributes set when called" do
|
27
|
+
d = DummyModel.create!(:attr_1 => 1, :attr_2 => 3)
|
28
|
+
assert_nothing_raised(ZeroDivisionError) do
|
29
|
+
assert_equal(d.use_attributes, d.use_attributes)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
18
33
|
test "get/store orm" do
|
19
34
|
d = DummyModel.create!(:attr_1 => 1, :attr_2 => 3)
|
20
35
|
Cachely::Mechanics.store(DummyClass,:foo, d,nil,[3,4])
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cachely
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-03-
|
12
|
+
date: 2013-03-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: redis
|
16
|
-
requirement: &
|
16
|
+
requirement: &19218640 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 3.0.1
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *19218640
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: hiredis
|
27
|
-
requirement: &
|
27
|
+
requirement: &19233140 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 0.4.5
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *19233140
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: em-synchrony
|
38
|
-
requirement: &
|
38
|
+
requirement: &19232120 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *19232120
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: json
|
49
|
-
requirement: &
|
49
|
+
requirement: &19231420 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,7 +54,7 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *19231420
|
58
58
|
description: Transparently cache the results of methods using redis.
|
59
59
|
email:
|
60
60
|
- jordanmprince@gmail.com
|
@@ -71,11 +71,14 @@ files:
|
|
71
71
|
- config/database.yml
|
72
72
|
- config/redis.yml
|
73
73
|
- db/migrate/001_create_dummy_model.rb
|
74
|
+
- db/migrate/002_create_dummy_model_2.rb
|
74
75
|
- lib/cachely.rb
|
75
76
|
- lib/cachely/mechanics.rb
|
76
77
|
- lib/cachely/version.rb
|
77
78
|
- test/models/dummy_class.rb
|
79
|
+
- test/models/dummy_class_2.rb
|
78
80
|
- test/models/dummy_model.rb
|
81
|
+
- test/models/dummy_model_two.rb
|
79
82
|
- test/unit/base_test.rb
|
80
83
|
- test/unit/cachely_test.rb
|
81
84
|
- test/unit/conversions_test.rb
|
@@ -106,7 +109,9 @@ specification_version: 3
|
|
106
109
|
summary: Transparently cache the results of methods using redis.
|
107
110
|
test_files:
|
108
111
|
- test/models/dummy_class.rb
|
112
|
+
- test/models/dummy_class_2.rb
|
109
113
|
- test/models/dummy_model.rb
|
114
|
+
- test/models/dummy_model_two.rb
|
110
115
|
- test/unit/base_test.rb
|
111
116
|
- test/unit/cachely_test.rb
|
112
117
|
- test/unit/conversions_test.rb
|