cachely 0.0.5 → 0.0.6
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/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
|