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 +4 -4
- data/README.md +31 -4
- data/lib/shadow_model/associations/has_many.rb +48 -0
- data/lib/shadow_model/model_extension.rb +11 -5
- data/lib/shadow_model/version.rb +1 -1
- data/lib/shadow_model.rb +2 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c83ab40b9ae9fcca01d524c4c8668680c7e15fcf
|
4
|
+
data.tar.gz: 48fe962f66e5408a852522337227f679b8859776
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
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
|
-
|
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
|
-
|
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
|
data/lib/shadow_model/version.rb
CHANGED
data/lib/shadow_model.rb
CHANGED
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.
|
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-
|
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:
|
120
|
+
summary: Rails model cache with redis
|
120
121
|
test_files: []
|