representable-cache 0.0.2
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.
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +73 -0
- data/Rakefile +1 -0
- data/lib/representable/cache/version.rb +5 -0
- data/lib/representable/cache.rb +118 -0
- data/representable-cache.gemspec +27 -0
- data/spec/representable/configuration_spec.rb +43 -0
- data/spec/representable/single_representable_spec.rb +273 -0
- data/spec/spec_helper.rb +20 -0
- metadata +165 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-gemset
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
representable-cache
|
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ruby-1.9.3-p327
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2013 Allen Wei
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Representable::Cache
|
|
2
|
+
|
|
3
|
+
provide cache feature for Representable
|
|
4
|
+
|
|
5
|
+
[representable](https://github.com/apotonick/representable)
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Add this line to your application's Gemfile:
|
|
10
|
+
|
|
11
|
+
gem 'representable-cache'
|
|
12
|
+
|
|
13
|
+
And then execute:
|
|
14
|
+
|
|
15
|
+
$ bundle
|
|
16
|
+
|
|
17
|
+
Or install it yourself as:
|
|
18
|
+
|
|
19
|
+
$ gem install representable-cache
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
### Default Configuration
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
Representable::Cache.cache_engine = Dalli::Client.new('localhost:11211', :namespace => "app_v1")
|
|
28
|
+
Representable::Cache.default_cache_key = [:id, :updated_at]
|
|
29
|
+
Representable::Cache.enable = false # Default: true
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Setup
|
|
33
|
+
|
|
34
|
+
```ruby
|
|
35
|
+
require 'representable/json'
|
|
36
|
+
require 'representable/cache'
|
|
37
|
+
|
|
38
|
+
module SongRepresenter
|
|
39
|
+
include Representable::JSON
|
|
40
|
+
include Representable::Cache
|
|
41
|
+
|
|
42
|
+
property :title
|
|
43
|
+
property :track
|
|
44
|
+
end
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### settings
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
module SongRepresenter
|
|
51
|
+
include Representable::JSON
|
|
52
|
+
include Representable::Cache
|
|
53
|
+
|
|
54
|
+
property :title
|
|
55
|
+
property :track
|
|
56
|
+
representable_cache :cache_key => :id, :cache_name => "Brand",
|
|
57
|
+
:version => "v1"
|
|
58
|
+
end
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
options:
|
|
62
|
+
* cache_key: could be symble or array, will use default_cache_key if not
|
|
63
|
+
set
|
|
64
|
+
* cache_name: default: module or class name
|
|
65
|
+
* version: version name, you can invalid old cache by bump cache version
|
|
66
|
+
|
|
67
|
+
## Contributing
|
|
68
|
+
|
|
69
|
+
1. Fork it
|
|
70
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
71
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
72
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
73
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
require "representable/cache/version"
|
|
2
|
+
require 'representable/binding'
|
|
3
|
+
|
|
4
|
+
module Representable::Cache
|
|
5
|
+
def self.reset
|
|
6
|
+
@default_cache_key = nil
|
|
7
|
+
@engine = nil
|
|
8
|
+
@enable = nil
|
|
9
|
+
end
|
|
10
|
+
def self.cache_engine=(engine)
|
|
11
|
+
raise "engine doesn't response to get" if !engine.respond_to?(:get)
|
|
12
|
+
raise "engine doesn't response to set" if !engine.respond_to?(:set)
|
|
13
|
+
@engine = engine
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.default_cache_key=(default_cache_key)
|
|
17
|
+
@default_cache_key = default_cache_key
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.default_cache_key
|
|
21
|
+
@default_cache_key
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.enable=(enable)
|
|
25
|
+
@enable = enable
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.enable
|
|
29
|
+
return true if @enable.nil?
|
|
30
|
+
@enable
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.cache
|
|
34
|
+
@engine
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# include presenter in model
|
|
38
|
+
def self.included(base)
|
|
39
|
+
base.send(:include, InstanceMethods)
|
|
40
|
+
base.extend ClassMethods
|
|
41
|
+
base.representable_cache_options[:cache_name] ||= base.name
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
module ClassMethods
|
|
45
|
+
# DCI
|
|
46
|
+
def extended(base)
|
|
47
|
+
super(base)
|
|
48
|
+
base.instance_eval do
|
|
49
|
+
def representable_cache_options
|
|
50
|
+
@representable_cache_options
|
|
51
|
+
end
|
|
52
|
+
def representable_cache_options=(options)
|
|
53
|
+
@representable_cache_options = options
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
base.representable_cache_options ||= self.representable_cache_options
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# inherited representable
|
|
61
|
+
def included(base)
|
|
62
|
+
super(base)
|
|
63
|
+
base.instance_eval do
|
|
64
|
+
def representable_cache_options
|
|
65
|
+
@representable_cache_options
|
|
66
|
+
end
|
|
67
|
+
def representable_cache_options=(options)
|
|
68
|
+
@representable_cache_options = options
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
base.representable_cache_options = self.representable_cache_options
|
|
72
|
+
base.representable_cache_options[:cache_name] ||= base.name
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def representable_cache(options={})
|
|
76
|
+
@representable_cache_options = @representable_cache_options.merge options
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def representable_cache_options
|
|
80
|
+
@representable_cache_options ||={}
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
module InstanceMethods
|
|
84
|
+
def to_hash(options={}, binding_builder=Representable::Hash::PropertyBinding)
|
|
85
|
+
return super(options, binding_builder) if !Representable::Cache.enable
|
|
86
|
+
if hash = Representable::Cache.cache.get(self.representable_cache_key)
|
|
87
|
+
return hash
|
|
88
|
+
end
|
|
89
|
+
hash = super(options, binding_builder)
|
|
90
|
+
Representable::Cache.cache.set(self.representable_cache_key, hash)
|
|
91
|
+
hash
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def representable_cache_options
|
|
95
|
+
@representable_cache_options || self.class.representable_cache_options
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def representable_cache_key
|
|
99
|
+
self.representable_cache_options[:cache_key] ||= Representable::Cache.default_cache_key
|
|
100
|
+
self.representable_cache_options[:cache_version] ||= "v1"
|
|
101
|
+
self.representable_cache_options[:cache_name] ||= self.class.name
|
|
102
|
+
|
|
103
|
+
keys = [
|
|
104
|
+
self.representable_cache_options[:cache_version],
|
|
105
|
+
self.representable_cache_options[:cache_name]
|
|
106
|
+
]
|
|
107
|
+
raise "cache_key or default_cache_key is required" if self.representable_cache_options[:cache_key].nil?
|
|
108
|
+
if self.representable_cache_options[:cache_key].kind_of? Array
|
|
109
|
+
keys += self.representable_cache_options[:cache_key].map do |k|
|
|
110
|
+
self.send(k).to_s.gsub(/\s+/,'')
|
|
111
|
+
end
|
|
112
|
+
else
|
|
113
|
+
self.send(self.representable_cache_options[:cache_key]).to_s.gsub(/\s+/,'')
|
|
114
|
+
end
|
|
115
|
+
keys.compact.join("-")
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'representable/cache/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "representable-cache"
|
|
8
|
+
spec.version = Representable::Cache::VERSION
|
|
9
|
+
spec.authors = ["Allen Wei"]
|
|
10
|
+
spec.email = ["digruby@gmail.com"]
|
|
11
|
+
spec.description = %q{cache solution for representable}
|
|
12
|
+
spec.summary = %q{cache solution for representable}
|
|
13
|
+
spec.homepage = ""
|
|
14
|
+
spec.license = "MIT"
|
|
15
|
+
|
|
16
|
+
spec.files = `git ls-files`.split($/)
|
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
|
+
spec.require_paths = ["lib"]
|
|
20
|
+
|
|
21
|
+
spec.add_runtime_dependency "representable"
|
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
|
23
|
+
spec.add_development_dependency "dalli"
|
|
24
|
+
spec.add_development_dependency "rspec"
|
|
25
|
+
spec.add_development_dependency "rake"
|
|
26
|
+
spec.add_development_dependency "debugger"
|
|
27
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'dalli'
|
|
3
|
+
require 'representable/cache'
|
|
4
|
+
|
|
5
|
+
describe "configuration" do
|
|
6
|
+
context "cache engine" do
|
|
7
|
+
it "should be able to set cache engine" do
|
|
8
|
+
Representable::Cache.cache_engine = Dalli::Client.new('localhost:11211', :namespace => "app_v1", :compress => true)
|
|
9
|
+
Representable::Cache.cache.should be_kind_of Dalli::Client
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should raise error if engine not resposne to get/set" do
|
|
13
|
+
expect {
|
|
14
|
+
Representable::Cache.cache_engine = "123"
|
|
15
|
+
}.to raise_error RuntimeError
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "cache" do
|
|
21
|
+
it "should be able to set and get from cache" do
|
|
22
|
+
Representable::Cache.cache_engine = Dalli::Client.new('localhost:11211', :namespace => "Representable::CacheTest", :compress => true)
|
|
23
|
+
Representable::Cache.cache.set("test_set", "test_set")
|
|
24
|
+
Representable::Cache.cache.get("test_set").should eq "test_set"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context "default_cache_key" do
|
|
29
|
+
it "should support default cache key" do
|
|
30
|
+
Representable::Cache.default_cache_key = [:id, :updated_at]
|
|
31
|
+
Representable::Cache.default_cache_key.should eq [:id, :updated_at]
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context "enable" do
|
|
36
|
+
it "should support enable or disable it" do
|
|
37
|
+
Representable::Cache.enable = false
|
|
38
|
+
Representable::Cache.enable.should be_false
|
|
39
|
+
Representable::Cache.enable = true
|
|
40
|
+
Representable::Cache.enable.should be_true
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'dalli'
|
|
3
|
+
require 'representable'
|
|
4
|
+
require 'representable/json'
|
|
5
|
+
require 'representable/cache'
|
|
6
|
+
|
|
7
|
+
describe Representable::Cache do
|
|
8
|
+
before do
|
|
9
|
+
Representable::Cache.cache_engine = Dalli::Client.new('localhost:11211', :namespace => "Representable::CacheTest", :compress => true)
|
|
10
|
+
Representable::Cache.cache.flush
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
let(:cache) { Representable::Cache.cache }
|
|
14
|
+
|
|
15
|
+
context "cache configuration" do
|
|
16
|
+
it "should allow multiple cache_key" do
|
|
17
|
+
@Brand = Class.new(Object) do
|
|
18
|
+
include Representable::JSON
|
|
19
|
+
include Representable::Cache
|
|
20
|
+
attr_accessor :name, :label, :updated_at
|
|
21
|
+
property :name
|
|
22
|
+
property :label
|
|
23
|
+
property :updated_at
|
|
24
|
+
representable_cache :cache_key => [:name, :label]
|
|
25
|
+
end
|
|
26
|
+
brand = @Brand.new
|
|
27
|
+
brand.name = "123"
|
|
28
|
+
brand.label = "321"
|
|
29
|
+
brand.representable_cache_key.should be_include("123-321")
|
|
30
|
+
end
|
|
31
|
+
it "should allow set cache_name" do
|
|
32
|
+
@Brand = Class.new(Object) do
|
|
33
|
+
include Representable::JSON
|
|
34
|
+
include Representable::Cache
|
|
35
|
+
attr_accessor :name, :label, :updated_at
|
|
36
|
+
property :name
|
|
37
|
+
property :label
|
|
38
|
+
property :updated_at
|
|
39
|
+
representable_cache :cache_key => :name, :cache_name => "cache_name_123"
|
|
40
|
+
end
|
|
41
|
+
brand = @Brand.new
|
|
42
|
+
brand.name = "123"
|
|
43
|
+
brand.label = "321"
|
|
44
|
+
brand.representable_cache_key.should be_include("cache_name_123")
|
|
45
|
+
end
|
|
46
|
+
it "should not read from cache if disable it" do
|
|
47
|
+
@Brand = Class.new(Object) do
|
|
48
|
+
include Representable::JSON
|
|
49
|
+
include Representable::Cache
|
|
50
|
+
attr_accessor :name, :label, :updated_at
|
|
51
|
+
property :name
|
|
52
|
+
property :label
|
|
53
|
+
property :updated_at
|
|
54
|
+
representable_cache :cache_key => :updated_at
|
|
55
|
+
end
|
|
56
|
+
Representable::Cache.enable = false
|
|
57
|
+
b = @Brand.new
|
|
58
|
+
b.name = "b1"
|
|
59
|
+
b.label = "l 1"
|
|
60
|
+
b.updated_at = Time.now
|
|
61
|
+
Representable::Cache.cache.set(b.representable_cache_key, {"brand" => {"name"=>"b 2", "label"=>"l 2", "updated_at"=>"2013-08-04 08:55:50 +0800"}})
|
|
62
|
+
json = b.to_json(:wrap => "brand")
|
|
63
|
+
hash = MultiJson.decode(json)
|
|
64
|
+
hash["brand"]["name"].should eq "b1"
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
context "simple representable" do
|
|
69
|
+
before do
|
|
70
|
+
@Brand = Class.new(Object) do
|
|
71
|
+
include Representable::JSON
|
|
72
|
+
include Representable::Cache
|
|
73
|
+
attr_accessor :name, :label, :updated_at
|
|
74
|
+
property :name
|
|
75
|
+
property :label
|
|
76
|
+
property :updated_at
|
|
77
|
+
representable_cache :cache_key => :updated_at
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
it "should write cache" do
|
|
81
|
+
b = @Brand.new
|
|
82
|
+
b.name = "b1"
|
|
83
|
+
b.label = "l 1"
|
|
84
|
+
b.updated_at = Time.now
|
|
85
|
+
hash = b.to_hash(:wrap => "brand")
|
|
86
|
+
Representable::Cache.cache.get(b.representable_cache_key).should eq hash
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it "to_json should use cache" do
|
|
90
|
+
b = @Brand.new
|
|
91
|
+
b.name = "b1"
|
|
92
|
+
b.label = "l 1"
|
|
93
|
+
b.updated_at = Time.now
|
|
94
|
+
Representable::Cache.cache.set(b.representable_cache_key, {"brand" => {"name"=>"b 2", "label"=>"l 2", "updated_at"=>"2013-08-04 08:55:50 +0800"}})
|
|
95
|
+
json = b.to_json(:wrap => "brand")
|
|
96
|
+
hash = MultiJson.decode(json)
|
|
97
|
+
hash["brand"]["name"].should eq "b 2"
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
context "simple DCI" do
|
|
102
|
+
before do
|
|
103
|
+
@Brand = Class.new do
|
|
104
|
+
attr_accessor :name, :label, :updated_at
|
|
105
|
+
end
|
|
106
|
+
@BrandPresenter = Module.new do
|
|
107
|
+
include Representable::JSON
|
|
108
|
+
include Representable::Cache
|
|
109
|
+
property :name
|
|
110
|
+
property :label
|
|
111
|
+
property :updated_at
|
|
112
|
+
representable_cache :cache_key => :updated_at
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
it "should write cache" do
|
|
116
|
+
b = @Brand.new
|
|
117
|
+
b.extend @BrandPresenter
|
|
118
|
+
b.name = "b1"
|
|
119
|
+
b.label = "l 1"
|
|
120
|
+
b.updated_at = Time.now
|
|
121
|
+
hash = b.to_hash(:wrap => "brand")
|
|
122
|
+
Representable::Cache.cache.get(b.representable_cache_key).should eq hash
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it "to_json should use cache" do
|
|
126
|
+
b = @Brand.new
|
|
127
|
+
b.extend @BrandPresenter
|
|
128
|
+
b.name = "b1"
|
|
129
|
+
b.label = "l 1"
|
|
130
|
+
b.updated_at = Time.now
|
|
131
|
+
Representable::Cache.cache.set(b.representable_cache_key, {"brand" => {"name"=>"b 2", "label"=>"l 2", "updated_at"=>"2013-08-04 08:55:50 +0800"}})
|
|
132
|
+
json = b.to_json(:wrap => "brand")
|
|
133
|
+
hash = MultiJson.decode(json)
|
|
134
|
+
hash["brand"]["name"].should eq "b 2"
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
context "extend DCI" do
|
|
139
|
+
before do
|
|
140
|
+
@Brand = Class.new do
|
|
141
|
+
attr_accessor :name, :label, :updated_at
|
|
142
|
+
end
|
|
143
|
+
brandPresenter = Module.new do
|
|
144
|
+
include Representable::JSON
|
|
145
|
+
include Representable::Cache
|
|
146
|
+
property :name
|
|
147
|
+
property :updated_at
|
|
148
|
+
representable_cache :cache_key => :updated_at
|
|
149
|
+
end
|
|
150
|
+
@BrandPresenter2 = Module.new do
|
|
151
|
+
include Representable::JSON
|
|
152
|
+
include Representable::Cache
|
|
153
|
+
include brandPresenter
|
|
154
|
+
property :label
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
it "should write cache" do
|
|
158
|
+
b = @Brand.new
|
|
159
|
+
b.extend @BrandPresenter2
|
|
160
|
+
b.name = "b1"
|
|
161
|
+
b.label = "l 1"
|
|
162
|
+
b.updated_at = Time.now
|
|
163
|
+
hash = b.to_hash(:wrap => "brand")
|
|
164
|
+
Representable::Cache.cache.get(b.representable_cache_key).should eq hash
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
it "to_json should use cache" do
|
|
168
|
+
b = @Brand.new
|
|
169
|
+
b.extend @BrandPresenter2
|
|
170
|
+
b.name = "b1"
|
|
171
|
+
b.label = "l 1"
|
|
172
|
+
b.updated_at = Time.now
|
|
173
|
+
Representable::Cache.cache.set(b.representable_cache_key, {"brand" => {"name"=>"b 2", "label"=>"l 2", "updated_at"=>"2013-08-04 08:55:50 +0800"}})
|
|
174
|
+
json = b.to_json(:wrap => "brand")
|
|
175
|
+
hash = MultiJson.decode(json)
|
|
176
|
+
hash["brand"]["name"].should eq "b 2"
|
|
177
|
+
hash["brand"]["label"].should eq "l 2"
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
context "collections" do
|
|
182
|
+
let(:product_class) do
|
|
183
|
+
Class.new do
|
|
184
|
+
attr_accessor :name,:updated_at
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
let(:product_presenter_class) do
|
|
188
|
+
Module.new do
|
|
189
|
+
include Representable::JSON
|
|
190
|
+
include Representable::Cache
|
|
191
|
+
property :name
|
|
192
|
+
property :updated_at
|
|
193
|
+
representable_cache :cache_key => :updated_at, :cache_name => "Product"
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
before do
|
|
198
|
+
product_class = product_class
|
|
199
|
+
productPresenter = product_presenter_class
|
|
200
|
+
@Brand = Class.new do
|
|
201
|
+
attr_accessor :name, :label, :updated_at,:products
|
|
202
|
+
end
|
|
203
|
+
@BrandPresenter = Module.new do
|
|
204
|
+
include Representable::JSON
|
|
205
|
+
include Representable::Cache
|
|
206
|
+
property :name
|
|
207
|
+
property :label
|
|
208
|
+
property :updated_at
|
|
209
|
+
collection :products, :extend => productPresenter, :class => product_class
|
|
210
|
+
representable_cache :cache_key => :updated_at, :cache_name => "Brand"
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
it "should cache each collection object" do
|
|
215
|
+
p1 = product_class.new
|
|
216
|
+
p1.name = "p1"
|
|
217
|
+
p1.updated_at = Time.now
|
|
218
|
+
p2 = product_class.new
|
|
219
|
+
p2.name = "p2"
|
|
220
|
+
p2.updated_at = Time.now
|
|
221
|
+
b = @Brand.new
|
|
222
|
+
b.name = "b1"
|
|
223
|
+
b.label = "l 1"
|
|
224
|
+
b.products = [p1, p2]
|
|
225
|
+
b.updated_at = Time.now
|
|
226
|
+
|
|
227
|
+
b.extend @BrandPresenter
|
|
228
|
+
hash = b.to_hash(:wrap => "brand")
|
|
229
|
+
Representable::Cache.cache.get(b.representable_cache_key).should eq hash
|
|
230
|
+
p1_hash = Representable::Cache.cache.get(p1.representable_cache_key)
|
|
231
|
+
p1_hash["name"].should eq "p1"
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
it "should get collection object from cache" do
|
|
235
|
+
p1 = product_class.new
|
|
236
|
+
p1.name = "p1"
|
|
237
|
+
p1.updated_at = Time.now
|
|
238
|
+
p1.extend product_presenter_class
|
|
239
|
+
|
|
240
|
+
b = @Brand.new
|
|
241
|
+
b.name = "b1"
|
|
242
|
+
b.label = "l 1"
|
|
243
|
+
b.updated_at = Time.now
|
|
244
|
+
b.extend @BrandPresenter
|
|
245
|
+
b.products = [p1]
|
|
246
|
+
Representable::Cache.cache.set(p1.representable_cache_key, {"name"=>"p 2","updated_at"=>"2013-08-04 08:55:50 +0800"})
|
|
247
|
+
json = b.to_json(:wrap => "brand")
|
|
248
|
+
hash = MultiJson.decode(json)
|
|
249
|
+
hash["brand"]["products"].first["name"].should eq "p 2"
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
describe "default_cache_key" do
|
|
254
|
+
it "should use default cache_key" do
|
|
255
|
+
Representable::Cache.default_cache_key = [:id, :name]
|
|
256
|
+
@Brand = Class.new(Object) do
|
|
257
|
+
include Representable::JSON
|
|
258
|
+
include Representable::Cache
|
|
259
|
+
attr_accessor :id, :name, :label, :updated_at
|
|
260
|
+
property :id
|
|
261
|
+
property :name
|
|
262
|
+
property :label
|
|
263
|
+
property :updated_at
|
|
264
|
+
end
|
|
265
|
+
brand = @Brand.new
|
|
266
|
+
brand.id = "1"
|
|
267
|
+
brand.name = "123"
|
|
268
|
+
brand.label = "321"
|
|
269
|
+
brand.representable_cache_key.should be_include("1-123")
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
|
4
|
+
# loaded once.
|
|
5
|
+
#
|
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
|
7
|
+
RSpec.configure do |config|
|
|
8
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
|
9
|
+
config.run_all_when_everything_filtered = true
|
|
10
|
+
#config.filter_run :focus
|
|
11
|
+
|
|
12
|
+
# Run specs in random order to surface order dependencies. If you find an
|
|
13
|
+
# order dependency and want to debug it, you can fix the order by providing
|
|
14
|
+
# the seed, which is printed after each run.
|
|
15
|
+
# --seed 1234
|
|
16
|
+
#config.order = 'random'
|
|
17
|
+
config.before do
|
|
18
|
+
Representable::Cache.reset
|
|
19
|
+
end
|
|
20
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: representable-cache
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.2
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- Allen Wei
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2013-08-04 00:00:00.000000000 Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: representable
|
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
|
17
|
+
none: false
|
|
18
|
+
requirements:
|
|
19
|
+
- - ! '>='
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '0'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
none: false
|
|
26
|
+
requirements:
|
|
27
|
+
- - ! '>='
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: '0'
|
|
30
|
+
- !ruby/object:Gem::Dependency
|
|
31
|
+
name: bundler
|
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
|
33
|
+
none: false
|
|
34
|
+
requirements:
|
|
35
|
+
- - ~>
|
|
36
|
+
- !ruby/object:Gem::Version
|
|
37
|
+
version: '1.3'
|
|
38
|
+
type: :development
|
|
39
|
+
prerelease: false
|
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
41
|
+
none: false
|
|
42
|
+
requirements:
|
|
43
|
+
- - ~>
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '1.3'
|
|
46
|
+
- !ruby/object:Gem::Dependency
|
|
47
|
+
name: dalli
|
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
|
49
|
+
none: false
|
|
50
|
+
requirements:
|
|
51
|
+
- - ! '>='
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
type: :development
|
|
55
|
+
prerelease: false
|
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
57
|
+
none: false
|
|
58
|
+
requirements:
|
|
59
|
+
- - ! '>='
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
- !ruby/object:Gem::Dependency
|
|
63
|
+
name: rspec
|
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
|
65
|
+
none: false
|
|
66
|
+
requirements:
|
|
67
|
+
- - ! '>='
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
69
|
+
version: '0'
|
|
70
|
+
type: :development
|
|
71
|
+
prerelease: false
|
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
73
|
+
none: false
|
|
74
|
+
requirements:
|
|
75
|
+
- - ! '>='
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: '0'
|
|
78
|
+
- !ruby/object:Gem::Dependency
|
|
79
|
+
name: rake
|
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
|
81
|
+
none: false
|
|
82
|
+
requirements:
|
|
83
|
+
- - ! '>='
|
|
84
|
+
- !ruby/object:Gem::Version
|
|
85
|
+
version: '0'
|
|
86
|
+
type: :development
|
|
87
|
+
prerelease: false
|
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
89
|
+
none: false
|
|
90
|
+
requirements:
|
|
91
|
+
- - ! '>='
|
|
92
|
+
- !ruby/object:Gem::Version
|
|
93
|
+
version: '0'
|
|
94
|
+
- !ruby/object:Gem::Dependency
|
|
95
|
+
name: debugger
|
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
|
97
|
+
none: false
|
|
98
|
+
requirements:
|
|
99
|
+
- - ! '>='
|
|
100
|
+
- !ruby/object:Gem::Version
|
|
101
|
+
version: '0'
|
|
102
|
+
type: :development
|
|
103
|
+
prerelease: false
|
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
105
|
+
none: false
|
|
106
|
+
requirements:
|
|
107
|
+
- - ! '>='
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '0'
|
|
110
|
+
description: cache solution for representable
|
|
111
|
+
email:
|
|
112
|
+
- digruby@gmail.com
|
|
113
|
+
executables: []
|
|
114
|
+
extensions: []
|
|
115
|
+
extra_rdoc_files: []
|
|
116
|
+
files:
|
|
117
|
+
- .gitignore
|
|
118
|
+
- .rspec
|
|
119
|
+
- .ruby-gemset
|
|
120
|
+
- .ruby-version
|
|
121
|
+
- Gemfile
|
|
122
|
+
- LICENSE.txt
|
|
123
|
+
- README.md
|
|
124
|
+
- Rakefile
|
|
125
|
+
- lib/representable/cache.rb
|
|
126
|
+
- lib/representable/cache/version.rb
|
|
127
|
+
- representable-cache.gemspec
|
|
128
|
+
- spec/representable/configuration_spec.rb
|
|
129
|
+
- spec/representable/single_representable_spec.rb
|
|
130
|
+
- spec/spec_helper.rb
|
|
131
|
+
homepage: ''
|
|
132
|
+
licenses:
|
|
133
|
+
- MIT
|
|
134
|
+
post_install_message:
|
|
135
|
+
rdoc_options: []
|
|
136
|
+
require_paths:
|
|
137
|
+
- lib
|
|
138
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
139
|
+
none: false
|
|
140
|
+
requirements:
|
|
141
|
+
- - ! '>='
|
|
142
|
+
- !ruby/object:Gem::Version
|
|
143
|
+
version: '0'
|
|
144
|
+
segments:
|
|
145
|
+
- 0
|
|
146
|
+
hash: 624065444298100772
|
|
147
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
|
+
none: false
|
|
149
|
+
requirements:
|
|
150
|
+
- - ! '>='
|
|
151
|
+
- !ruby/object:Gem::Version
|
|
152
|
+
version: '0'
|
|
153
|
+
segments:
|
|
154
|
+
- 0
|
|
155
|
+
hash: 624065444298100772
|
|
156
|
+
requirements: []
|
|
157
|
+
rubyforge_project:
|
|
158
|
+
rubygems_version: 1.8.23
|
|
159
|
+
signing_key:
|
|
160
|
+
specification_version: 3
|
|
161
|
+
summary: cache solution for representable
|
|
162
|
+
test_files:
|
|
163
|
+
- spec/representable/configuration_spec.rb
|
|
164
|
+
- spec/representable/single_representable_spec.rb
|
|
165
|
+
- spec/spec_helper.rb
|