active_model_cachers 2.0.3 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e51a19a8c47a1ea8bbdede0389a5768463081518ae322dba25155e1ce99eda9
|
4
|
+
data.tar.gz: 43c82003bf164a54f45ac022db12842e22da7eac45022e2f61a6a66779c243b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e79837432ad52125b04f80761068dc366764e6ea944729f45bc2e2231629991645c6798369964f2adf27646c315e24190e31189cb349d3cad7fbb48813e3fbc
|
7
|
+
data.tar.gz: 2788c31af2ded6965ab755a72d8e0160421e7c4057d6c221d7b39485cc768a53ae1192ab4329e503b576de205e07ac4be6c546d628da993e54bbcf341a1adade
|
data/README.md
CHANGED
@@ -40,14 +40,31 @@ end
|
|
40
40
|
|
41
41
|
## Usage
|
42
42
|
|
43
|
+
### Cache whatever you want by `cache_at` method
|
44
|
+
|
43
45
|
`cache_at(name, query = nil, options = {})`
|
44
46
|
|
45
|
-
|
47
|
+
Specify a cache on the model.
|
46
48
|
- name: the attribute name.
|
47
49
|
- query: how to get data on cache miss. It will be set automatically if the name match an association or an attribute.
|
48
50
|
- options: see [here](#options)
|
49
51
|
|
50
|
-
|
52
|
+
### Asscess the cached attributes
|
53
|
+
|
54
|
+
The `cacher` is defined as `class method` and `instance method` of Model. You could call the method and get the cacher instance, e.g. `User.cacher` or `user.cacher`. An attribute will define a method on cacher, cached attributes are asscessable via it, e.g. `user.cacher.the_attribute_name`.
|
55
|
+
|
56
|
+
|
57
|
+
### Basic Example
|
58
|
+
```rb
|
59
|
+
class User < ActiveRecord::Base
|
60
|
+
cache_at :something_you_want_to_cache, ->{ get_the_data_on_cache_miss }
|
61
|
+
end
|
62
|
+
|
63
|
+
user.cacher.something_you_want_to_cache
|
64
|
+
```
|
65
|
+
|
66
|
+
|
67
|
+
## Examples
|
51
68
|
|
52
69
|
### Example 1: Cache the number of active user
|
53
70
|
|
@@ -117,7 +134,31 @@ render_error if not current_user.cacher.email_valid?
|
|
117
134
|
|
118
135
|
It can also be accessed from instance cacher. But you have to set [`primary_key`](#primary_key), which is needed to know which attribute should be passed to the parameter.
|
119
136
|
|
120
|
-
### Example 5:
|
137
|
+
### Example 5: Store all data in hash
|
138
|
+
|
139
|
+
Sometimes you may need to query multiple objects. Although the query results will be cached, the application still needs to query the cache server multiple times. If one communication take 0.1 ms, 1000 communications will take 100ms! For example:
|
140
|
+
|
141
|
+
```rb
|
142
|
+
class Skill < ActiveRecord::Base
|
143
|
+
cache_at :atk_power
|
144
|
+
end
|
145
|
+
|
146
|
+
# This will retrieve the data from cache servers multiple times.
|
147
|
+
@attack = skill_ids.inject(0){|sum, id| sum + Skill.cacher_at(id).atk_power }
|
148
|
+
```
|
149
|
+
|
150
|
+
One of the solution is that you could store a lookup table into cache, so that only one cache object is stored and you can retrieve all of the needed data in one query.
|
151
|
+
|
152
|
+
```rb
|
153
|
+
class Skill < ActiveRecord::Base
|
154
|
+
cache_at :atk_powers, ->{ Skill.pluck(:id, :atk_power).to_h }, expire_by: 'Skill#atk_power'
|
155
|
+
end
|
156
|
+
|
157
|
+
# This will retrieve the data from cache servers only 1 times.
|
158
|
+
@attack = skill_ids.inject(0){|sum, id| sum + Skill.cacher.atk_powers[id] }
|
159
|
+
```
|
160
|
+
|
161
|
+
### Example 6: Clean the cache manually
|
121
162
|
|
122
163
|
Sometimes it needs to maintain the cache manually. For example, after calling `update_all`, `delete_all` or `import` records without calling callbacks.
|
123
164
|
|
@@ -130,13 +171,34 @@ end
|
|
130
171
|
# clean the cache by name
|
131
172
|
current_user.cacher.clean(:profile)
|
132
173
|
|
133
|
-
#
|
174
|
+
# or calling the clean_* method
|
134
175
|
current_user.cacher.clean_profile
|
135
176
|
|
136
177
|
# clean the cache without loading model
|
137
178
|
User.cacher_at(user_id).clean_profile
|
138
179
|
```
|
139
180
|
|
181
|
+
### Example 7: Peek the data stored in cache
|
182
|
+
|
183
|
+
If you just want to check the cached objects, but don't want it to load from database automatically when there is no cache. You could use `peek` method on `cacher`.
|
184
|
+
|
185
|
+
```rb
|
186
|
+
class User < ActiveRecord::Base
|
187
|
+
has_one :profile
|
188
|
+
cache_at :profile
|
189
|
+
end
|
190
|
+
|
191
|
+
# peek the cache by name
|
192
|
+
current_user.cacher.peek(:profile)
|
193
|
+
|
194
|
+
# or calling the peek_* method
|
195
|
+
current_user.cacher.peek_profile
|
196
|
+
|
197
|
+
# peek the cache without loading model
|
198
|
+
User.cacher_at(user_id).peek_profile
|
199
|
+
```
|
200
|
+
|
201
|
+
|
140
202
|
## Smart Caching
|
141
203
|
|
142
204
|
### Multi-level Cache
|
@@ -184,16 +246,28 @@ class User < ActiveRecord::Base
|
|
184
246
|
cache_self
|
185
247
|
end
|
186
248
|
|
187
|
-
@user = User.
|
249
|
+
@user = User.cacher.find_by(id: user_id)
|
250
|
+
|
251
|
+
# peek cache
|
252
|
+
User.cacher.peek_by(id: user_id)
|
253
|
+
|
254
|
+
# clean cache
|
255
|
+
User.cacher.clean_by(id: user_id)
|
188
256
|
```
|
189
257
|
|
190
258
|
Also support caching self by other columns.
|
191
259
|
```rb
|
192
260
|
class User < ActiveRecord::Base
|
193
|
-
cache_self
|
261
|
+
cache_self by: :account
|
194
262
|
end
|
195
263
|
|
196
|
-
@user = User.
|
264
|
+
@user = User.cacher.find_by(account: 'khiav')
|
265
|
+
|
266
|
+
# peek cache
|
267
|
+
User.cacher.peek_by(account: 'khiav')
|
268
|
+
|
269
|
+
# clean cache
|
270
|
+
User.cacher.clean_by(account: 'khiav')
|
197
271
|
```
|
198
272
|
|
199
273
|
### Caching Attributes
|
@@ -250,5 +324,17 @@ This option is needed to know which attribute should be passed to the parameter
|
|
250
324
|
|
251
325
|
- Default value is `:id`
|
252
326
|
|
327
|
+
## Development
|
328
|
+
|
329
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
330
|
+
|
331
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
332
|
+
|
333
|
+
## Contributing
|
334
|
+
|
335
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/khiav223577/active_model_cachers. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
336
|
+
|
253
337
|
|
338
|
+
## License
|
254
339
|
|
340
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
@@ -6,8 +6,9 @@ module ActiveModelCachers
|
|
6
6
|
|
7
7
|
class << self
|
8
8
|
def define_cacher_method(attr, primary_key, service_klasses)
|
9
|
-
method = attr.column || (primary_key == :id ? :self : :"self_by_#{primary_key}")
|
10
9
|
cacher_klass = get_cacher_klass(attr.klass)
|
10
|
+
method = attr.column
|
11
|
+
return cacher_klass.define_find_by(attr, primary_key, service_klasses) if method == nil
|
11
12
|
cacher_klass.attributes << method
|
12
13
|
cacher_klass.send(:define_method, method){ exec_by(attr, primary_key, service_klasses, :get) }
|
13
14
|
cacher_klass.send(:define_method, "peek_#{method}"){ exec_by(attr, primary_key, service_klasses, :peek) }
|
@@ -18,10 +19,27 @@ module ActiveModelCachers
|
|
18
19
|
@defined_map[klass] ||= create_cacher_klass_at(klass)
|
19
20
|
end
|
20
21
|
|
22
|
+
def define_find_by(attr, primary_key, service_klasses)
|
23
|
+
if @find_by_mapping == nil
|
24
|
+
@find_by_mapping = {}
|
25
|
+
attributes << :find_by
|
26
|
+
define_method(:find_by){|args| exec_find_by(args, :get) }
|
27
|
+
define_method(:peek_by){|args| exec_find_by(args, :peek) }
|
28
|
+
define_method(:clean_by){|args| exec_find_by(args, :clean_cache) }
|
29
|
+
end
|
30
|
+
@find_by_mapping[primary_key] = [attr, service_klasses]
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_data_from_find_by_mapping(primary_key)
|
34
|
+
return if @find_by_mapping == nil
|
35
|
+
return @find_by_mapping[primary_key]
|
36
|
+
end
|
37
|
+
|
21
38
|
private
|
22
39
|
|
23
40
|
def create_cacher_klass_at(target)
|
24
41
|
cacher_klass = Class.new(self)
|
42
|
+
cacher_klass.instance_variable_set(:@find_by_mapping, nil) # to remove warning: instance variable @find_by_mapping not initialized
|
25
43
|
cacher_klass.define_singleton_method(:attributes){ @attributes ||= [] }
|
26
44
|
cacher_klass.send(:define_method, 'peek'){|column| send("peek_#{column}") }
|
27
45
|
cacher_klass.send(:define_method, 'clean'){|column| send("clean_#{column}") }
|
@@ -40,7 +58,14 @@ module ActiveModelCachers
|
|
40
58
|
|
41
59
|
private
|
42
60
|
|
43
|
-
def
|
61
|
+
def exec_find_by(args, method) # e.g. args = {course_id: xx}
|
62
|
+
primary_key = args.keys.sort.first # Support only one key now.
|
63
|
+
attr, service_klasses = self.class.get_data_from_find_by_mapping(primary_key)
|
64
|
+
return if service_klasses == nil
|
65
|
+
return exec_by(attr, primary_key, service_klasses, method, data: args[primary_key])
|
66
|
+
end
|
67
|
+
|
68
|
+
def exec_by(attr, primary_key, service_klasses, method, data: nil)
|
44
69
|
bindings = [@model]
|
45
70
|
if @model and attr.association?
|
46
71
|
if attr.belongs_to? and method != :clean_cache # no need to load binding when just cleaning cache
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
class ActiveModelCachers::ColumnValueCache
|
2
3
|
def initialize
|
3
4
|
@cache1 = Hash.new{|h, k| h[k] = {} }
|
@@ -38,7 +39,7 @@ class ActiveModelCachers::ColumnValueCache
|
|
38
39
|
|
39
40
|
def get_id_from(object, id, column, model)
|
40
41
|
return id if column == 'id'
|
41
|
-
model ||= object.
|
42
|
+
model ||= object.cacher.peek_by(id: id) if object.has_cacher?
|
42
43
|
return model.send(column) if model
|
43
44
|
return :not_set
|
44
45
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_model_cachers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- khiav reoy
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-05-
|
11
|
+
date: 2018-05-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|