shadow_model 0.1.2 → 0.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9518b18405e37c61c19150b09c2c4203592b6584
4
- data.tar.gz: cb61c047872eb147c663f91f17a2e4879e4370b7
3
+ metadata.gz: c83ab40b9ae9fcca01d524c4c8668680c7e15fcf
4
+ data.tar.gz: 48fe962f66e5408a852522337227f679b8859776
5
5
  SHA512:
6
- metadata.gz: dc810d648888fc744c8fc6f781e6fad8adb0102e19d89e2e9648a942c4d6cc1247f659b186360795446644782d2d55940a58f5acc16f675665a4efe16f76908e
7
- data.tar.gz: fd22eef1713aef85f2d4f7d1fc31aea29bc50c25f33feebab4e1d91ecf8bffc4269ea2eb70c95ed6613c3f1174a9b9de6a88812c7479431e44f8ea70df3bbea2
6
+ metadata.gz: d42b3640f6a22d7c34e79d9d8b3edb5182ec4fa11e68c8d841ac84cee945942d2666e1c8cb6664c29c3bd78a7f96a06c54931b0bcc6591f82b588c71634fd6f3
7
+ data.tar.gz: 81c2e002a0e49d2745e24da7b8148bf0a419b4dcb8afe87940941468484976b74fbaeb0bc9ef172eabf2d129aca1d0ae9fbafd06514ff81eac4ab75e6f45197a
data/README.md CHANGED
@@ -16,13 +16,16 @@ And then execute:
16
16
 
17
17
  ## Usage
18
18
 
19
- Add this to your model class, then the models will be cached with the assigned attributes and methods after the model saved or updated.
19
+ Add this to your model class, then the models will be cached with the assigned attributes and methods after saved or updated.
20
20
 
21
21
  shadow_model attribute_or_method1, attribute_or_method2, ..., options
22
22
 
23
23
  And use this to retrieve the model from redis.
24
24
 
25
- YourModelClass.find_by_shadow(primary_key)
25
+ model = YourModelClass.find_by_shadow(primary_key)
26
+
27
+ model.is_a?(YourModelClass) # true
28
+ model.readonly? # true
26
29
 
27
30
  ### options
28
31
 
@@ -31,14 +34,14 @@ And use this to retrieve the model from redis.
31
34
  <td>expiration</td><td>Set the timeout of each cache.</td>
32
35
  </tr>
33
36
  <tr>
34
- <td>&nbsp;&nbsp;update_expiration</td><td>Reset cache expiration after model updated.</td>
37
+ <td>update_expiration</td><td>Reset cache expiration after model updated (if expiration has been set).</td>
35
38
  </tr>
36
39
  <tr>
37
40
  <td>expireat</td><td>Set the absolute timeout timestamp of each cache.</td>
38
41
  </tr>
39
42
  </table>
40
43
 
41
- ## Example
44
+ ### Example
42
45
 
43
46
  # == Schema Information
44
47
  #
@@ -57,3 +60,27 @@ And use this to retrieve the model from redis.
57
60
  "result to cache"
58
61
  end
59
62
  end
63
+
64
+ ## Associations
65
+
66
+ ### has_many
67
+
68
+ You can set the **shadow** option of has_many association to allow shadow_model to cache all the related models.
69
+
70
+ class Game < ActiveRecord::Base
71
+ has_many :players, shadow: true
72
+ end
73
+
74
+ This will use hash data structure of redis to save the cache data, and you can retrieve all of them with one redis connection.
75
+
76
+ game = Game.create(name: "pikmin")
77
+ game.players.create(name: "player one")
78
+ game.players.create(name: "player two")
79
+
80
+ game.players_by_shadow # [#<Player id: 1, game_id: 1, name: "player one", ...>, #<Player id: 2, game_id: 1, name: "player two", ...>]
81
+
82
+ If you don't want to cache models seperately and use the association type only, you can set the **association_only** option to disable it.
83
+
84
+ class Player < ActiveRecord::Base
85
+ shadow_model ..., association_only: true
86
+ end
@@ -0,0 +1,48 @@
1
+ class ::ActiveRecord::Associations::Builder::HasMany
2
+ def valid_options_with_shadow_option
3
+ valid_options_without_shadow_option + [:shadow]
4
+ end
5
+ alias_method_chain :valid_options, :shadow_option
6
+
7
+ def build_with_shadow_option
8
+ reflection = build_without_shadow_option
9
+ if options[:shadow]
10
+ model_name = model.table_name.singularize
11
+ model.class_eval <<-RUBY
12
+ def #{name}_shadow_cache_key
13
+ "#{model_name}_\#{self[self.class.primary_key]}_#{name}_shadow_cache"
14
+ end
15
+
16
+ def #{name}_by_shadow
17
+ Redis.current.hvals(#{name}_shadow_cache_key).map do |val|
18
+ shadow_data = Marshal.load(val)
19
+ #{reflection.klass.name}.instantiate_shadow_model(shadow_data)
20
+ end
21
+ end
22
+
23
+ def clear_#{name}_shadow_cache
24
+ Redis.current.del(#{name}_shadow_cache_key)
25
+ end
26
+ RUBY
27
+
28
+ reflection.klass.class_eval <<-RUBY
29
+ after_save :update_shadow_cach_of_#{model_name}
30
+ after_destroy :delete_shadow_cach_of_#{model_name}
31
+
32
+ def belongs_to_#{model_name}_shadow_cache_key
33
+ "#{model_name}_\#{self[:#{reflection.foreign_key}]}_#{name}_shadow_cache"
34
+ end
35
+
36
+ def update_shadow_cach_of_#{model_name}
37
+ Redis.current.hset(belongs_to_#{model_name}_shadow_cache_key, self[self.class.primary_key], self.build_shadow_data)
38
+ end
39
+
40
+ def delete_shadow_cach_of_#{model_name}
41
+ Redis.current.hdel(belongs_to_#{model_name}_shadow_cache_key, self[self.class.primary_key])
42
+ end
43
+ RUBY
44
+ end
45
+ reflection
46
+ end
47
+ alias_method_chain :build, :shadow_option
48
+ end
@@ -5,6 +5,7 @@ module ShadowModel
5
5
  mattr_accessor :shadow_options
6
6
  extend ClassMethods
7
7
  after_save :update_shadow_cache
8
+ after_destroy :clear_shadow_data
8
9
  RUBY
9
10
  end
10
11
 
@@ -43,6 +44,7 @@ module ShadowModel
43
44
  end
44
45
 
45
46
  def update_shadow_cache
47
+ return if shadow_options[:association_only]
46
48
  Redis.current.set(shadow_cache_key, build_shadow_data)
47
49
  update_expiration
48
50
  end
@@ -110,11 +112,7 @@ module ShadowModel
110
112
 
111
113
  def find_by_shadow(id)
112
114
  if shadow_data = find_shadow_data(id)
113
- instance = self.new
114
- instance.shadow_model = true
115
- instance.shadow_data = shadow_data
116
- instance.readonly!
117
- instance
115
+ instantiate_shadow_model(shadow_data)
118
116
  else
119
117
  instance = self.find(id)
120
118
  instance.update_shadow_cache
@@ -127,6 +125,14 @@ module ShadowModel
127
125
  data ? Marshal.load(data) : nil
128
126
  end
129
127
 
128
+ def instantiate_shadow_model(shadow_data)
129
+ instance = self.new
130
+ instance.shadow_model = true
131
+ instance.shadow_data = shadow_data
132
+ instance.readonly!
133
+ instance
134
+ end
135
+
130
136
  def build_shadow_cache_key(id)
131
137
  "#{self.name.tableize}:Shadow:#{id}"
132
138
  end
@@ -1,3 +1,3 @@
1
1
  module ShadowModel
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/shadow_model.rb CHANGED
@@ -17,3 +17,5 @@ module ShadowModel
17
17
  end
18
18
 
19
19
  ActiveRecord::Base.send :include, ShadowModel
20
+
21
+ require 'shadow_model/associations/has_many'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shadow_model
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Weihu Chen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-25 00:00:00.000000000 Z
11
+ date: 2013-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -87,6 +87,7 @@ executables: []
87
87
  extensions: []
88
88
  extra_rdoc_files: []
89
89
  files:
90
+ - lib/shadow_model/associations/has_many.rb
90
91
  - lib/shadow_model/model_extension.rb
91
92
  - lib/shadow_model/version.rb
92
93
  - lib/shadow_model.rb
@@ -116,5 +117,5 @@ rubyforge_project:
116
117
  rubygems_version: 2.0.6
117
118
  signing_key:
118
119
  specification_version: 4
119
- summary: rails model cache with redis
120
+ summary: Rails model cache with redis
120
121
  test_files: []