shadow_model 0.1.2 → 0.2.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
  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: []