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: 8c49c9bc175d4ab55f5507cc4a6c4db006a099c90819e71788ced4b799d510f9
4
- data.tar.gz: bb19f0043d46963c75b4ef71d30945c35156acb778b19d3f72e874b6c6dbdd15
3
+ metadata.gz: 7e51a19a8c47a1ea8bbdede0389a5768463081518ae322dba25155e1ce99eda9
4
+ data.tar.gz: 43c82003bf164a54f45ac022db12842e22da7eac45022e2f61a6a66779c243b3
5
5
  SHA512:
6
- metadata.gz: 478355a8ee8fed5b1a25fcb6c2ef258888f6507c8e6bc74e98b9c559470b9475b750e69c7e03a7f77b05324cfc7927076e3c6173e08d0dbe4e4247283ab87011
7
- data.tar.gz: c2029fb1379a12f03669b9a7dfa09858ab96a3cba755074ed1483e5a5239a890cd1c33dc9bfaf2973e7b76f5d1f42b166bb9a51b27e4c958d727d137d27437e4
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
- Specifie a cache on the model.
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
- ## Cache whatever you want
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: Clean the cache manually
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
- # Or calling the clean_* method
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.cacher_at(user_id).self
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, by: :account
261
+ cache_self by: :account
194
262
  end
195
263
 
196
- @user = User.cacher_at('khiav').self_by_account
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 exec_by(attr, primary_key, service_klasses, method)
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.cacher_at(id).peek_self if object.has_cacher?
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
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module ActiveModelCachers
3
- VERSION = "2.0.3"
3
+ VERSION = "2.1.0"
4
4
  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.3
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-14 00:00:00.000000000 Z
11
+ date: 2018-05-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler