covercache 0.1.0 → 0.2
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.
- checksums.yaml +8 -8
- data/README.md +7 -2
- data/covercache.gemspec +1 -1
- data/lib/covercache/version.rb +1 -1
- data/lib/covercache.rb +105 -69
- data/spec/covercache.sqlite3 +0 -0
- data/spec/libs/covercache_spec.rb +8 -4
- data/spec/spec_helper.rb +9 -6
- metadata +3 -4
- data/lib/where.rb +0 -69
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YjlhOGViNGViNzYwZDEyNjg3ZjQ1N2ZhNjFiYWY3OGJmMTY5ODVmNw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MmE3MDFlNmU0ZDQ4NDVjNjEwN2EwOWQxMjI5NDVmY2FiODA3ZjVmYQ==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NjM3YmJmN2NjMzI2NzBlYjU5MDQ5ZmI5YjBhY2E4MDllY2I1MTM4YzdhMWE0
|
10
|
+
YjQ4M2EzYTk3ZjJjODZkMGYwYTYwMDIxY2Y0Yzk3OGI0ZTczOWI5NWE3N2Vj
|
11
|
+
ZTJjZDEyZThjMDNmOTY1MGMyYzE2YTY3ZGJkMjllMDlmZmEwZWY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MmQ5OTllYzMwZmUyMmZlYzk2MmUyNzMyOGEyMmI1ZWY2OTg3ZDkxNjBiYzBk
|
14
|
+
NmNjMTE4ZDA1ZGMxMjU1MGFhZGE0ZDIwZjZiZDY1ZGQ3Zjc4OTEzM2EzMzlk
|
15
|
+
N2YxOTRkYjY2ZjE3ZTFkMjhiMjEyYjE3MjcyYjRhMmM2OWNiOTY=
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Covercache
|
2
2
|
|
3
|
+
[](https://codeclimate.com/github/estum/covercache)
|
4
|
+
|
3
5
|
Covercache is a helper for Rails.cache, based on [PackRat](https://github.com/cpuguy83/pack_rat) gem, and, as it says: <br />
|
4
6
|
> When included in your class it makes caching trivial.
|
5
7
|
|
@@ -59,7 +61,7 @@ You can easily wrap methods with the <tt>define_cached</tt> helper.<br />
|
|
59
61
|
Note, that Relation objects couldn't be cached, so wrapped method or block
|
60
62
|
should return an array or single instance of your model.
|
61
63
|
|
62
|
-
To wrap instance methods you should use a name of already defined method:
|
64
|
+
To wrap instance methods you should use a name of already defined method or set block with the first argument as record:
|
63
65
|
|
64
66
|
class Post < ActiveRecord::Base
|
65
67
|
def all_comments
|
@@ -72,7 +74,10 @@ To wrap instance methods you should use a name of already defined method:
|
|
72
74
|
# You can add arguments like for covercache:
|
73
75
|
# [keys], debug: true, expires_in: 10.minutes
|
74
76
|
define_cached :all_comments, expires_in: 1.minute
|
75
|
-
|
77
|
+
|
78
|
+
define_cached :all_comments_authors, debug: true, do |record|
|
79
|
+
record.author
|
80
|
+
end
|
76
81
|
# ...
|
77
82
|
end
|
78
83
|
|
data/covercache.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["anton.estum@gmail.com"]
|
11
11
|
spec.description = %q{Helper method to simplify Rails caching, based on PackRat}
|
12
12
|
spec.summary = %q{Rails cache helper based on PackRat gem}
|
13
|
-
spec.homepage = "http://github.com/
|
13
|
+
spec.homepage = "http://github.com/estum/covercache"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
16
|
spec.files = `git ls-files`.split($/)
|
data/lib/covercache/version.rb
CHANGED
data/lib/covercache.rb
CHANGED
@@ -4,8 +4,6 @@ require 'active_support/core_ext'
|
|
4
4
|
require 'active_support/concern'
|
5
5
|
require 'active_record'
|
6
6
|
|
7
|
-
require "where"
|
8
|
-
|
9
7
|
# == Motivation
|
10
8
|
#
|
11
9
|
# * Quickly use <tt>Rails.cache</tt> for some tasks without rubbish code in models.
|
@@ -22,7 +20,7 @@ require "where"
|
|
22
20
|
# Note, that Relation objects couldn't be cached, so wrapped method or block
|
23
21
|
# should return an array or single instance of your model.
|
24
22
|
#
|
25
|
-
# To wrap instance methods you should use a name of already defined method:
|
23
|
+
# To wrap instance methods you should use a name of already defined method or set block with the first argument as record:
|
26
24
|
#
|
27
25
|
# class Post < ActiveRecord::Base
|
28
26
|
# def all_comments
|
@@ -35,13 +33,16 @@ require "where"
|
|
35
33
|
# # You can add arguments like for covercache: [keys], debug: true, expires_in: 10.minutes
|
36
34
|
# define_cached :all_comments, expires_in: 1.minute
|
37
35
|
#
|
36
|
+
# define_cached :all_comments_authors, expires_in: 1.minute do |record|
|
37
|
+
# record.author
|
38
|
+
# end
|
38
39
|
# # ...
|
39
40
|
# end
|
40
41
|
#
|
41
42
|
# post = Post.find(1)
|
42
43
|
# post.cached_all_comments
|
43
44
|
#
|
44
|
-
# To wrap class methods
|
45
|
+
# To wrap class methods:
|
45
46
|
#
|
46
47
|
# class_define_cached :for_post_ids, debug: true, expires_in: 10.minutes do |post_ids|
|
47
48
|
# where(post_id: post_ids).all
|
@@ -52,85 +53,119 @@ require "where"
|
|
52
53
|
#
|
53
54
|
module Covercache
|
54
55
|
# General helper method (ex <tt>cache</tt> helper in PackRat)
|
55
|
-
module Base
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
56
|
+
module Base
|
57
|
+
# Arguments:
|
58
|
+
#
|
59
|
+
# [1..] any count of custom *keys
|
60
|
+
# :debug #=>
|
61
|
+
# :without_auto_key #=> don't generate cache_key
|
62
|
+
# any option for Rails.cache.fetch
|
63
|
+
#
|
64
|
+
# Example:
|
65
|
+
#
|
66
|
+
# scope :published, -> { where published: true }
|
67
|
+
# has_many :comments
|
68
|
+
#
|
69
|
+
# def cached_comments
|
70
|
+
# covercache do
|
71
|
+
# comments.all
|
72
|
+
# end
|
73
|
+
# end
|
74
|
+
#
|
75
|
+
# def self.cached_published
|
76
|
+
# covercache debug:true do
|
77
|
+
# published.all
|
78
|
+
# end
|
79
|
+
# end
|
80
|
+
#
|
81
|
+
private
|
82
|
+
def covercache(*keys, &block)
|
83
|
+
klass = class_or_instance_class
|
84
|
+
options = keys.extract_options!
|
85
|
+
cover_opts = options.extract! :debug, :without_auto_key
|
66
86
|
|
67
|
-
# if
|
68
|
-
unless
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
key << cache_key if self.respond_to?(:cache_key)
|
76
|
-
key += args
|
77
|
-
end
|
78
|
-
# Output the generated cache key to the console if debug is set
|
79
|
-
puts key.inspect if should_debug
|
80
|
-
# Make the actual Rails.cache call
|
81
|
-
Rails.cache.fetch key, filtered_options do
|
82
|
-
klass.covercache_keys << key unless key.in?(klass.covercache_keys)
|
87
|
+
# if :no_auto_cache_keys was set, we skip creating our own key
|
88
|
+
keys.prepend get_auto_cache_key(klass.name, caller) unless cover_opts[:without_auto_key]
|
89
|
+
keys.flatten!
|
90
|
+
puts keys.inspect if !!cover_opts[:debug]
|
91
|
+
# puts caller.inspect if !!cover_opts[:debug],
|
92
|
+
|
93
|
+
Rails.cache.fetch keys, options do
|
94
|
+
klass.covercache_keys |= [ keys ]
|
83
95
|
block.call
|
84
96
|
end
|
85
97
|
end
|
86
|
-
|
87
|
-
def
|
88
|
-
|
98
|
+
|
99
|
+
def get_auto_cache_key(class_name, _caller)
|
100
|
+
caller_method = _caller.map {|c| c[/`([^']*)'/, 1] }.detect {|m| !m.start_with?('block') }
|
101
|
+
puts caller_method.inspect
|
102
|
+
[ class_name, covercache_model_digest, caller_method, (cache_key if self.respond_to?(:cache_key?)) ].compact
|
103
|
+
end
|
104
|
+
|
105
|
+
def class_or_instance_class
|
106
|
+
self.is_a?(Class) ? self : self.class
|
89
107
|
end
|
90
108
|
|
91
|
-
def
|
92
|
-
|
109
|
+
def extract_cache_key_from(*args)
|
110
|
+
Array.wrap((args.last.delete(:cache_key) if args.last.is_a?(Hash)))
|
93
111
|
end
|
94
112
|
end
|
95
113
|
|
96
114
|
# == Defining Helper
|
97
115
|
#
|
98
|
-
# TODO: share logic
|
99
|
-
#
|
100
116
|
module DefiningHelper
|
101
117
|
# Define and wrap methods or blocks
|
102
|
-
def define_cached(*args)
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
118
|
+
def define_cached(method, *args, &block)
|
119
|
+
options = args.extract_options!
|
120
|
+
is_class_method = !!options.delete(:is_class_method)
|
121
|
+
|
122
|
+
file, line = caller[is_class_method ? 1 : 0].split ':', 2
|
123
|
+
line = line.to_i
|
124
|
+
|
125
|
+
covercache_method_arguments method, args, options, &block
|
126
|
+
covercache_define_wrapper method, file, line, block_given?, is_class_method
|
127
|
+
end
|
128
|
+
|
129
|
+
def class_define_cached(method, *args, &block)
|
130
|
+
options = args.extract_options!
|
131
|
+
options[:is_class_method] = true
|
132
|
+
self.send :define_cached, method, *args, options, &block
|
113
133
|
end
|
114
134
|
|
115
|
-
|
116
|
-
def
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
#
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
135
|
+
private
|
136
|
+
def covercache_define_wrapper(method, file, line, with_block=false, is_class_method=false)
|
137
|
+
cached_method = "cached_#{method}"
|
138
|
+
|
139
|
+
class_eval(<<-EOS, file, line - 2)
|
140
|
+
def #{'self.' if is_class_method}#{cached_method}(*args, &block)
|
141
|
+
settings = Array.wrap(#{cached_method}_settings[:args]) + extract_cache_key_from(*args)
|
142
|
+
covercache(*settings, #{cached_method}_settings[:opts]) do
|
143
|
+
if #{with_block}
|
144
|
+
#{cached_method}_settings[:block].call(#{'self,' unless is_class_method}*args)
|
145
|
+
else
|
146
|
+
self.__send__ :#{method}, *args, &block
|
147
|
+
end
|
128
148
|
end
|
129
149
|
end
|
130
|
-
|
150
|
+
EOS
|
151
|
+
end
|
152
|
+
|
153
|
+
def covercache_method_arguments(method, *args, &block)
|
154
|
+
settings = collect_method_args_to_hash(*args, &block)
|
155
|
+
puts settings.inspect
|
156
|
+
class_attribute :"cached_#{method}_settings"
|
157
|
+
self.send(:"cached_#{method}_settings=", settings)
|
158
|
+
end
|
159
|
+
|
160
|
+
def collect_method_args_to_hash(*args, &block)
|
161
|
+
puts args.inspect
|
162
|
+
Hash[ %w{args opts block}.map do |x|
|
163
|
+
[ x, (args.shift || block) ]
|
164
|
+
end].to_options
|
131
165
|
end
|
132
166
|
end
|
133
167
|
|
168
|
+
|
134
169
|
# Extend and Include to model Base helper so cache method is available in all contexts.
|
135
170
|
# <em>(yes, it is form PackRat too)</em>
|
136
171
|
module ModelConcern
|
@@ -143,7 +178,7 @@ module Covercache
|
|
143
178
|
end
|
144
179
|
|
145
180
|
self.covercache_keys ||= []
|
146
|
-
self.covercache_model_source
|
181
|
+
self.covercache_model_source ||= @covercache_caller_source #Where.is_class self, of: 'app/models'
|
147
182
|
|
148
183
|
generate_model_digest!
|
149
184
|
|
@@ -165,14 +200,12 @@ module Covercache
|
|
165
200
|
|
166
201
|
# Generates and sets file_digest attribute
|
167
202
|
def generate_model_digest!
|
168
|
-
self.covercache_model_digest =
|
203
|
+
self.covercache_model_digest = generate_model_digest
|
169
204
|
end
|
170
205
|
|
171
206
|
def covercache_flush!
|
172
|
-
self.covercache_keys.each
|
173
|
-
|
174
|
-
end.clear
|
175
|
-
self.covercache_keys.empty?
|
207
|
+
self.covercache_keys.each { |key| Rails.cache.delete(key) }.clear # if Rails.cache.exist?(key)
|
208
|
+
covercache_keys.empty?
|
176
209
|
end
|
177
210
|
end
|
178
211
|
|
@@ -185,7 +218,10 @@ module Covercache
|
|
185
218
|
# module CoversWithCache
|
186
219
|
# add Covercache supporting to model
|
187
220
|
def covers_with_cache
|
221
|
+
caller_source = caller.first[/[^:]+/]
|
222
|
+
|
188
223
|
class_eval do
|
224
|
+
@covercache_caller_source = caller_source
|
189
225
|
include Covercache::ModelConcern
|
190
226
|
extend Covercache::DefiningHelper
|
191
227
|
end
|
data/spec/covercache.sqlite3
CHANGED
Binary file
|
@@ -5,10 +5,6 @@ describe "covercache" do
|
|
5
5
|
it 'should respond to covers_with_cache' do
|
6
6
|
Post.should respond_to(:covers_with_cache)
|
7
7
|
end
|
8
|
-
it 'should hove class keys storage' do
|
9
|
-
pp Post.covercache_keys
|
10
|
-
Post.covercache_keys.should be_an(Array)
|
11
|
-
end
|
12
8
|
it 'should have covercache_model_source attribute' do
|
13
9
|
pp Post.covercache_model_source
|
14
10
|
Post.covercache_model_source.should be_an(String)
|
@@ -36,4 +32,12 @@ describe "covercache" do
|
|
36
32
|
pp test.cached_comments.inspect
|
37
33
|
test.cached_comments.count.should == test.comments.count
|
38
34
|
end
|
35
|
+
it 'post should have class keys storage' do
|
36
|
+
pp Post.covercache_keys
|
37
|
+
Post.covercache_keys.should be_an(Array)
|
38
|
+
end
|
39
|
+
it 'comments should have class keys storage' do
|
40
|
+
pp Comment.covercache_keys
|
41
|
+
Comment.covercache_keys.should be_an(Array)
|
42
|
+
end
|
39
43
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -62,17 +62,20 @@ end
|
|
62
62
|
class Post < ActiveRecord::Base
|
63
63
|
has_many :comments
|
64
64
|
covers_with_cache
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
end
|
65
|
+
define_cached :comments, debug: true
|
66
|
+
# def cached_comments
|
67
|
+
# covercache debug: true do
|
68
|
+
# comments.all
|
69
|
+
# end
|
70
|
+
# end
|
70
71
|
end
|
71
72
|
|
72
73
|
class Comment < ActiveRecord::Base
|
73
74
|
belongs_to :post
|
74
75
|
covers_with_cache
|
75
|
-
define_cached :post, debug: true
|
76
|
+
define_cached :post, debug: true do |record|
|
77
|
+
record.post
|
78
|
+
end
|
76
79
|
class_define_cached :for_post, debug: true do |post_id|
|
77
80
|
where(post_id: post_id).all
|
78
81
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: covercache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: '0.2'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tõnis Simo
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-05-
|
12
|
+
date: 2013-05-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -139,11 +139,10 @@ files:
|
|
139
139
|
- covercache.gemspec
|
140
140
|
- lib/covercache.rb
|
141
141
|
- lib/covercache/version.rb
|
142
|
-
- lib/where.rb
|
143
142
|
- spec/covercache.sqlite3
|
144
143
|
- spec/libs/covercache_spec.rb
|
145
144
|
- spec/spec_helper.rb
|
146
|
-
homepage: http://github.com/
|
145
|
+
homepage: http://github.com/estum/covercache
|
147
146
|
licenses:
|
148
147
|
- MIT
|
149
148
|
metadata: {}
|
data/lib/where.rb
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
# A little Ruby module for finding the source location where class and methods are defined.
|
2
|
-
# https://gist.github.com/wtaysom/1236979
|
3
|
-
|
4
|
-
module Where
|
5
|
-
#== Example
|
6
|
-
#
|
7
|
-
# Where.is_class Post, of: 'app/models'
|
8
|
-
#
|
9
|
-
class <<self
|
10
|
-
def is_class(klass, opts={})
|
11
|
-
methods = defined_methods(klass)
|
12
|
-
file_groups = methods.group_by{|sl| sl[0]}
|
13
|
-
file_counts = file_groups.map do |file, sls|
|
14
|
-
lines = sls.map{|sl| sl[1]}
|
15
|
-
count = lines.size
|
16
|
-
line = lines.min
|
17
|
-
{file: file, count: count, line: line}
|
18
|
-
end
|
19
|
-
file_counts.sort_by!{|fc| fc[:count]}
|
20
|
-
|
21
|
-
if opts[:of].present?
|
22
|
-
path_expand = joins_path(opts[:of])
|
23
|
-
return File.expand_path("../../spec/spec_helper.rb", __FILE__) unless !!path_expand
|
24
|
-
pattern = Regexp.new "^#{path_expand}/.*"
|
25
|
-
matches = file_counts.select do |fc|
|
26
|
-
!!fc[:file][pattern]
|
27
|
-
end
|
28
|
-
return matches.first[:file] if matches.first.present?
|
29
|
-
end
|
30
|
-
|
31
|
-
source_locations = file_counts.map{|fc| [fc[:file], fc[:line]]}
|
32
|
-
source_locations
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
def joins_path(of)
|
37
|
-
Rails.root.join(of).to_s
|
38
|
-
rescue NameError
|
39
|
-
return false
|
40
|
-
end
|
41
|
-
|
42
|
-
def source_location(method)
|
43
|
-
method.source_location || (
|
44
|
-
method.to_s =~ /: (.*)>/
|
45
|
-
$1
|
46
|
-
)
|
47
|
-
end
|
48
|
-
|
49
|
-
def defined_methods(klass)
|
50
|
-
methods = klass.methods(false).map{|m| klass.method(m)} +
|
51
|
-
klass.instance_methods(false).map{|m| klass.instance_method(m)}
|
52
|
-
methods.map!(&:source_location)
|
53
|
-
methods.compact!
|
54
|
-
methods
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def where_is(klass, method = nil)
|
60
|
-
Where.edit(if method
|
61
|
-
begin
|
62
|
-
Where.is_instance_method(klass, method)
|
63
|
-
rescue NameError
|
64
|
-
Where.is_method(klass, method)
|
65
|
-
end
|
66
|
-
else
|
67
|
-
Where.is_class_primarily(klass)
|
68
|
-
end)
|
69
|
-
end
|