retriever 0.1.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.
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .rvmrc
6
+ .DS_Store
7
+ dump.rdb
8
+ coverage
9
+ doc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in retriever.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2011 Nelvin Driz <ndriz@exist.com>
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.rdoc ADDED
@@ -0,0 +1,40 @@
1
+ = Retriever
2
+
3
+ A block result caching library.
4
+
5
+ == Installation
6
+
7
+ Either include to your <tt>Gemfile</tt> or install it.
8
+
9
+ # Bash
10
+ $ gem install retriever
11
+
12
+ # Gemfile
13
+ gem 'retriever'
14
+
15
+ == Rails Usage
16
+
17
+ Create file <tt>config/initializer/retriever.rb</tt> with your configuration.
18
+
19
+ === Example <tt>retriever.rb</tt>
20
+
21
+ Retriever.config.storage(:memory)
22
+ Retreiver.catch! do
23
+ target :bone do |parameters|
24
+ ...
25
+ end
26
+ end
27
+
28
+ === Example Usage (Controller)
29
+
30
+ def index
31
+ @bone = Retriever.fetch(:bone)
32
+ end
33
+
34
+ == {Documentation}[http://rubydoc.info/gems/retriever/frames]
35
+
36
+ == License
37
+
38
+ Copyright (c) 2011 Nelvin Driz.
39
+
40
+ Retriever is free software released under the MIT license.
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ gem 'rdoc'
5
+ require 'rdoc/task'
6
+
7
+ RDoc::Task.new do |rdoc|
8
+ rdoc.rdoc_dir = 'doc'
9
+ rdoc.title = "Retriever #{Retriever::VERSION}"
10
+ rdoc.rdoc_files.include('lib/**/*.rb')
11
+ rdoc.rdoc_files.include('README.rdoc')
12
+ rdoc.options << '--charset' << 'utf-8'
13
+ rdoc.options << '--line-numbers'
14
+ rdoc.main = 'README.rdoc'
15
+ end
16
+
17
+ RSpec::Core::RakeTask.new(:spec) do |t|
18
+ t.pattern = "./spec/**/*_spec.rb"
19
+ t.rspec_opts = ['--color']
20
+ end
@@ -0,0 +1,74 @@
1
+ module Retriever
2
+ # Configuration Namespace
3
+ module Config
4
+ class << self
5
+ # Boolean value to indicate whether or not key used for cache is encrypted or not.
6
+ attr_reader :encrypt
7
+
8
+ # Set encryption to boolean specified
9
+ #
10
+ # ==== Examples
11
+ #
12
+ # Retriever.config.encrypt = true
13
+ # Retriever.config.encrypt = false
14
+ #
15
+ def encrypt=(boolean)
16
+ require 'digest/sha1' if boolean
17
+ @encrypt = boolean
18
+ end
19
+
20
+ # Set storage handler to be used by retriever.
21
+ # This is a requirement to be set so that you
22
+ # can use retriever.
23
+ #
24
+ # ==== Storage Handlers (Built-in)
25
+ #
26
+ # * <tt>:ephemeral</tt> - Uses a ruby hash to store cache.
27
+ # * <tt>:redis</tt> - Use redis. (Requires <tt>redis</tt> gem.)
28
+ #
29
+ # ==== Custom Storage Handlers
30
+ # You can supply your own storage handler. In the class you supply,
31
+ # you need to specify the following methods:
32
+ #
33
+ # * <tt>set(key, value)</tt> - Used to set value in the cache store.
34
+ # * <tt>get(key)</tt> - Used to retrieve value from cache store.
35
+ # * <tt>delete(key)</tt> - Used to delete a record from cache store.
36
+ #
37
+ # ==== Examples
38
+ #
39
+ # Retriever.config.storage(:ephemeral) # Set storage to memory.
40
+ # Retriever.config.storage(:redis) # Set storage to redis.
41
+ #
42
+ # class CustomStorageHandler
43
+ # def set(key, value)
44
+ # ...
45
+ # end
46
+ #
47
+ # def get(key)
48
+ # ...
49
+ # end
50
+ #
51
+ # def delete(key)
52
+ # ...
53
+ # end
54
+ # end
55
+ #
56
+ # Retriever.config.storage(CustomStorageHandler) # Set storage to a custom storage.
57
+ #
58
+ def storage(type)
59
+ if type.is_a? Class
60
+ ::Retriever.storage = type.new if type.is_a?(Class)
61
+ else
62
+ case type
63
+ when :ephemeral
64
+ require File.join(File.dirname(__FILE__), 'storage', 'ephemeral')
65
+ ::Retriever.storage = Retriever::Storage::Ephemeral.new
66
+ when :redis
67
+ require File.join(File.dirname(__FILE__), 'storage', 'redis')
68
+ ::Retriever.storage = Retriever::Storage::Redis.new
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,63 @@
1
+ module Retriever
2
+ # Instruction is used by retriever as an object that would
3
+ # store set attributes and options while specifying your
4
+ # targets in <tt>Retriever.catch!</tt>
5
+ #
6
+ class Instruction
7
+ # Key used by instruction for storage manipulation.
8
+ attr_accessor :key
9
+
10
+ # Block executed to retrieve value to be cached.
11
+ attr_accessor :block
12
+
13
+ # Instantiate Instruction
14
+ #
15
+ # ==== Parameters
16
+ #
17
+ # * <tt>:key</tt> - Key used to store and retrieve value from cache.
18
+ # * <tt>:options</tt> - Options defined in <tt>Retriever.catch!</tt>
19
+ # * <tt>:block</tt> - Block is the <tt>Proc</tt> object to be executed.
20
+ # Resulting value would be the cached.
21
+ #
22
+ def initialize(key, options, block)
23
+ @key = key
24
+ @block = block
25
+ @validity = options[:validity] || 365.days
26
+ end
27
+
28
+ # Checks if value in storage is expired before trying to retrieve
29
+ # a new value. Value in storage is returned if value is still valid.
30
+ #
31
+ # ==== Parameters
32
+ #
33
+ # * <tt>:storage</tt> - Instance of the storage handler.
34
+ # * <tt>:block_parameters</tt> - Arguments sent to the block if value
35
+ # in storage is expired.
36
+ #
37
+ def execute(storage, block_parameters)
38
+ if expired? then execute!(storage, block_parameters) else storage.get(key) end
39
+ end
40
+
41
+ # Cache the result of the block. Just like <tt>execute</tt> but does not
42
+ # check cached value.
43
+ #
44
+ # ==== Parameters
45
+ #
46
+ # * <tt>:storage</tt> - Instance of the storage handler.
47
+ # * <tt>:block_parameters</tt> - Arguments sent to the block if value
48
+ # in storage is expired.
49
+ #
50
+ def execute!(storage, block_parameters)
51
+ @last_execution = Time.now
52
+ storage.set(key, block.call(*block_parameters))
53
+ end
54
+
55
+ private
56
+ # Check if cached value is expired
57
+ #
58
+ def expired?
59
+ return true unless @last_execution
60
+ Time.now - @last_execution > @validity
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,32 @@
1
+ # Storage handler namespace
2
+ module Retriever::Storage
3
+ # Storage handler for a Hash Backend
4
+ class Ephemeral
5
+ # Instance of Hash
6
+ attr_reader :storage
7
+
8
+ # Instantiate hash object as storage of cache.
9
+ #
10
+ def initialize
11
+ @storage = Hash.new
12
+ end
13
+
14
+ # Set record in hash.
15
+ #
16
+ def set(key, value)
17
+ storage[key] = value
18
+ end
19
+
20
+ # Get record from hash.
21
+ #
22
+ def get(key)
23
+ storage[key]
24
+ end
25
+
26
+ # Delete record in hash.
27
+ #
28
+ def delete(key)
29
+ storage.delete(key)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,51 @@
1
+ require 'redis'
2
+ require 'json'
3
+
4
+ module Retriever::Storage
5
+ # Storage handler for a Redis Backend
6
+ class Redis
7
+ # Instance of Redis
8
+ attr_reader :storage
9
+
10
+ # Instantiate Redis Connection (Default Settings Used)
11
+ #
12
+ def initialize
13
+ @storage = ::Redis.new
14
+ end
15
+
16
+ # Set record in storage.
17
+ # Serializes value to JSON if applicable.
18
+ #
19
+ def set(key, value)
20
+ value = serialize(value)
21
+ storage.set(key, value)
22
+ JSON.parse(value) rescue value
23
+ end
24
+
25
+ # Get record from storage.
26
+ # Deserialize value from JSON if applicable.
27
+ #
28
+ def get(key)
29
+ value = storage.get(key)
30
+ JSON.parse(value) rescue value
31
+ end
32
+
33
+ # Delete record from storage.
34
+ #
35
+ def delete(key)
36
+ storage.del key
37
+ end
38
+
39
+ private
40
+ # Serialize value by converting it to JSON if possible.
41
+ #
42
+ def serialize(value)
43
+ case value.class.to_s
44
+ when 'String' then value
45
+ else
46
+ value.to_json rescue value.to_s
47
+ end
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,4 @@
1
+ module Retriever
2
+ # Version of Retriever
3
+ VERSION = "0.1.0"
4
+ end
data/lib/retriever.rb ADDED
@@ -0,0 +1,149 @@
1
+ require File.join('retriever', 'version')
2
+ require File.join('retriever', 'config')
3
+ require File.join('retriever', 'instruction')
4
+
5
+ # Main Retriever Entry Point
6
+ module Retriever
7
+ class << self
8
+ # Instance of storage handler.
9
+ attr_accessor :storage
10
+
11
+ # Array of instructions.
12
+ attr_accessor :instructions
13
+
14
+ # Setup targets for retriever to cache.
15
+ #
16
+ # ==== Example
17
+ #
18
+ # Retriever.catch! do
19
+ # target :bone do
20
+ # 'wishbone'
21
+ # end
22
+ # end
23
+ #
24
+ def catch!(&block)
25
+ @instance_timestamp = Time.now
26
+ @instructions = Hash.new
27
+ self.instance_eval &block
28
+ end
29
+
30
+ # Setup a new <tt>target</tt> for retriever to catch.
31
+ #
32
+ # ==== Parameters
33
+ #
34
+ # * <tt>:name</tt> - Identifier used to call the block whenever you call
35
+ # <tt>fetch</tt> or <tt>fetch!</tt>.
36
+ # * <tt>:options</tt> - Options that modify basic instruction of simply
37
+ # caching the result of the block.
38
+ # * <tt>:block</tt> - The block to be executed with it's result being cached.
39
+ #
40
+ # ==== Options
41
+ #
42
+ # * <tt>:validity</tt> - Sets length of validity of a certain cache.
43
+ # After the cache expires, retriever simply executes the block again.
44
+ #
45
+ # target :bone, :validity => 10.minutes
46
+ #
47
+ # ==== Example
48
+ #
49
+ # Retriever.catch! do
50
+ # @counter = 0
51
+ # target :bone, :validity => 10.minutes do
52
+ # @counter += 1
53
+ # end
54
+ # end
55
+ #
56
+ # Retriever.fetch(:bone) # => 1
57
+ # # After 10 minutes
58
+ # Retreiver.fetch(:bone) # => 2
59
+ #
60
+ def target(name, options = {}, &block)
61
+ key = keyify(name)
62
+ instructions[key] = Instruction.new(key, options, block)
63
+ end
64
+
65
+ # Fetch data based upon the execution result of the corresponding
66
+ # instruction identified by the <tt>target_name</tt>. If data cached
67
+ # is still valid, that data would be returned.
68
+ #
69
+ # ==== Parameters
70
+ #
71
+ # * <tt>:target_name</tt> - The name used to identify the instruction.
72
+ # * <tt>:*block_parameters</tt> - Parameters passed on to the block
73
+ # that is part of the instruction.
74
+ #
75
+ # ==== Examples
76
+ #
77
+ # Retriever.fetch(:bone)
78
+ #
79
+ def fetch(target_name, *block_parameters)
80
+ key = keyify(target_name)
81
+ instruction = instructions[key]
82
+ instruction.execute(storage, block_parameters)
83
+ end
84
+
85
+ # Fetch data based upon the execution result of the corresponding
86
+ # instruction identified by the <tt>target_name</tt>.
87
+ #
88
+ # ==== Parameters
89
+ #
90
+ # * <tt>:target_name</tt> - The name used to identify the instruction.
91
+ # * <tt>:*block_parameters</tt> - Parameters passed on to the block
92
+ # that is part of the instruction.
93
+ #
94
+ # ==== Examples
95
+ #
96
+ # Retriever.fetch(:bone)
97
+ #
98
+ def fetch!(target_name, *block_parameters)
99
+ key = keyify(target_name)
100
+ instruction = instructions[key]
101
+ instruction.execute!(storage, block_parameters)
102
+ end
103
+
104
+ # Check if keys used for the cache store is encrypted or not encrypted.
105
+ # Basis of key is namespaced to retriever as well as timestamped.
106
+ # (Timestamp comes from the instance start.)
107
+ #
108
+ def encrypted?
109
+ config.encrypt || false
110
+ end
111
+
112
+ # Returns config namespace.
113
+ #
114
+ def config
115
+ Config
116
+ end
117
+
118
+ # Delete all cache. Automatically run on instance process termination.
119
+ #
120
+ def clean!
121
+ return unless instructions
122
+ instructions.keys.each do |key|
123
+ storage.delete(key)
124
+ end
125
+ end
126
+
127
+ private
128
+ # Namespaces <tt>target_name</tt> to retriever as well as timestamped
129
+ # with the instance start timestamp. This key is also encrypted using
130
+ # SHA1 if set to be encrypted.
131
+ #
132
+ # ==== Examples
133
+ #
134
+ # To set encryption:
135
+ # Retriever.config.encrypt = true # Set encryption to true
136
+ # Retriever.config.encrypt = false # Set encryption to false
137
+ #
138
+ def keyify(target_name)
139
+ key = "Retriever::#{target_name}::#{@instance_timestamp}"
140
+ key = Digest::SHA1.hexdigest(key) if encrypted?
141
+ return key
142
+ end
143
+
144
+ end
145
+ end
146
+
147
+ at_exit do
148
+ Retriever.clean!
149
+ end
data/retriever.gemspec ADDED
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "retriever/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'retriever'
7
+ s.version = Retriever::VERSION
8
+ s.authors = ['Nelvin Driz']
9
+ s.email = ['ndriz@exist.com']
10
+ s.homepage = "http://github.com/Keoven/Retriever"
11
+ s.summary = %q{Retriever is a block result caching library.}
12
+ s.description = %q{
13
+ Retriever allows caching of the result of a block. It currently supports ruby memory storage and redis.
14
+ }
15
+
16
+ s.rubyforge_project = 'retriever'
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ["lib"]
22
+
23
+ # Development
24
+ s.add_development_dependency 'rspec'
25
+ s.add_development_dependency 'redis'
26
+ s.add_development_dependency 'yajl-ruby'
27
+ s.add_development_dependency 'rails'
28
+ s.add_development_dependency 'timecop'
29
+ s.add_development_dependency 'ruby-debug19'
30
+ s.add_development_dependency 'simplecov'
31
+
32
+ # Runtime
33
+ s.add_runtime_dependency 'activesupport'
34
+ end
@@ -0,0 +1,107 @@
1
+ require 'spec_helper'
2
+
3
+ class Custom
4
+ attr_reader :storage
5
+
6
+ def initialize
7
+ @storage = Hash.new
8
+ end
9
+
10
+ def set(key, value)
11
+ storage[key] = value
12
+ end
13
+
14
+ def get(key)
15
+ storage[key]
16
+ end
17
+
18
+ def delete(key)
19
+ storage.delete(key)
20
+ end
21
+ end
22
+
23
+ describe Retriever do
24
+ before do
25
+ Retriever.config.storage(Custom)
26
+ end
27
+
28
+ it 'should fetch ball' do
29
+ Retriever.catch! do
30
+ target :ball do
31
+ 'ball'
32
+ end
33
+ end
34
+ Retriever.fetch(:ball).should be_eql('ball')
35
+ end
36
+
37
+ it 'should memoize ball' do
38
+ Retriever.catch! do
39
+ target :ball do
40
+ 'ball'
41
+ end
42
+ end
43
+ Retriever.storage.should_receive(:set).once.and_return('ball')
44
+ Retriever.fetch(:ball).should be_eql('ball')
45
+ Retriever.storage.stub!(:get).and_return('ball')
46
+ Retriever.fetch(:ball).should be_eql('ball')
47
+ end
48
+
49
+ it 'should only be valid in 10 minutes' do
50
+ now = Time.now
51
+ Timecop.freeze(now)
52
+ Retriever.catch! do
53
+ @counter = 0
54
+ target :ball, :validity => 10.minutes do
55
+ @counter += 1
56
+ end
57
+ end
58
+ Retriever.fetch(:ball).should be_eql(1)
59
+ Timecop.freeze(now + 5.minutes)
60
+ Retriever.fetch(:ball).should be_eql(1)
61
+ Timecop.freeze(now + 10.minutes)
62
+ Retriever.fetch(:ball).should be_eql(1)
63
+ Timecop.freeze(now + 10.minutes + 1.second)
64
+ Retriever.fetch(:ball).should be_eql(2)
65
+ Timecop.freeze(now + 15.minutes)
66
+ Retriever.fetch(:ball).should be_eql(2)
67
+ Timecop.freeze(now)
68
+ Retriever.fetch(:ball).should be_eql(2)
69
+ Timecop.freeze(now + 30.minutes)
70
+ Retriever.fetch(:ball).should be_eql(3)
71
+ end
72
+
73
+ it 'should be able to pass parameters' do
74
+ Retriever.catch! do
75
+ target :ball do |arg1, arg2|
76
+ arg1 + arg2
77
+ end
78
+ end
79
+
80
+ Retriever.fetch(:ball, 1, 2).should be_eql(3)
81
+ end
82
+
83
+ it 'should be able to fetch forcefully' do
84
+ now = Time.now
85
+ Timecop.freeze(now)
86
+ Retriever.catch! do
87
+ @counter = 0
88
+ target :ball, :validity => 10.minutes do
89
+ @counter += 1
90
+ end
91
+ end
92
+ Retriever.fetch(:ball).should be_eql(1)
93
+ Retriever.fetch!(:ball).should be_eql(2)
94
+ Retriever.fetch(:ball).should be_eql(2)
95
+ end
96
+
97
+ it 'should be encrypted' do
98
+ Retriever.config.encrypt = true
99
+ Retriever.should be_encrypted
100
+ Retriever.catch! do
101
+ target :ball do
102
+ 'ball'
103
+ end
104
+ end
105
+ Retriever.fetch(:ball).should be_eql('ball')
106
+ end
107
+ end
@@ -0,0 +1,87 @@
1
+ require 'spec_helper'
2
+
3
+ describe Retriever do
4
+ before do
5
+ Retriever.config.storage(:ephemeral)
6
+ end
7
+
8
+ it 'should fetch ball' do
9
+ Retriever.catch! do
10
+ target :ball do
11
+ 'ball'
12
+ end
13
+ end
14
+ Retriever.fetch(:ball).should be_eql('ball')
15
+ end
16
+
17
+ it 'should memoize ball' do
18
+ Retriever.catch! do
19
+ target :ball do
20
+ 'ball'
21
+ end
22
+ end
23
+ Retriever.storage.should_receive(:set).once.and_return('ball')
24
+ Retriever.fetch(:ball).should be_eql('ball')
25
+ Retriever.storage.stub!(:get).and_return('ball')
26
+ Retriever.fetch(:ball).should be_eql('ball')
27
+ end
28
+
29
+ it 'should only be valid in 10 minutes' do
30
+ now = Time.now
31
+ Timecop.freeze(now)
32
+ Retriever.catch! do
33
+ @counter = 0
34
+ target :ball, :validity => 10.minutes do
35
+ @counter += 1
36
+ end
37
+ end
38
+ Retriever.fetch(:ball).should be_eql(1)
39
+ Timecop.freeze(now + 5.minutes)
40
+ Retriever.fetch(:ball).should be_eql(1)
41
+ Timecop.freeze(now + 10.minutes)
42
+ Retriever.fetch(:ball).should be_eql(1)
43
+ Timecop.freeze(now + 10.minutes + 1.second)
44
+ Retriever.fetch(:ball).should be_eql(2)
45
+ Timecop.freeze(now + 15.minutes)
46
+ Retriever.fetch(:ball).should be_eql(2)
47
+ Timecop.freeze(now)
48
+ Retriever.fetch(:ball).should be_eql(2)
49
+ Timecop.freeze(now + 30.minutes)
50
+ Retriever.fetch(:ball).should be_eql(3)
51
+ end
52
+
53
+ it 'should be able to pass parameters' do
54
+ Retriever.catch! do
55
+ target :ball do |arg1, arg2|
56
+ arg1 + arg2
57
+ end
58
+ end
59
+
60
+ Retriever.fetch(:ball, 1, 2).should be_eql(3)
61
+ end
62
+
63
+ it 'should be able to fetch forcefully' do
64
+ now = Time.now
65
+ Timecop.freeze(now)
66
+ Retriever.catch! do
67
+ @counter = 0
68
+ target :ball, :validity => 10.minutes do
69
+ @counter += 1
70
+ end
71
+ end
72
+ Retriever.fetch(:ball).should be_eql(1)
73
+ Retriever.fetch!(:ball).should be_eql(2)
74
+ Retriever.fetch(:ball).should be_eql(2)
75
+ end
76
+
77
+ it 'should be encrypted' do
78
+ Retriever.config.encrypt = true
79
+ Retriever.should be_encrypted
80
+ Retriever.catch! do
81
+ target :ball do
82
+ 'ball'
83
+ end
84
+ end
85
+ Retriever.fetch(:ball).should be_eql('ball')
86
+ end
87
+ end
@@ -0,0 +1,87 @@
1
+ require 'spec_helper'
2
+
3
+ describe Retriever do
4
+ before do
5
+ Retriever.config.storage(:redis)
6
+ end
7
+
8
+ it 'should fetch ball' do
9
+ Retriever.catch! do
10
+ target :ball do
11
+ 'ball'
12
+ end
13
+ end
14
+ Retriever.fetch(:ball).should be_eql('ball')
15
+ end
16
+
17
+ it 'should memoize ball' do
18
+ Retriever.catch! do
19
+ target :ball do
20
+ 'ball'
21
+ end
22
+ end
23
+ Retriever.storage.should_receive(:set).once.and_return('ball')
24
+ Retriever.fetch(:ball).should be_eql('ball')
25
+ Retriever.storage.stub!(:get).and_return('ball')
26
+ Retriever.fetch(:ball).should be_eql('ball')
27
+ end
28
+
29
+ it 'should only be valid in 10 minutes' do
30
+ now = Time.now
31
+ Timecop.freeze(now)
32
+ Retriever.catch! do
33
+ @counter = 0
34
+ target :ball, :validity => 10.minutes do
35
+ @counter += 1
36
+ end
37
+ end
38
+ Retriever.fetch(:ball).should be_eql('1')
39
+ Timecop.freeze(now + 5.minutes)
40
+ Retriever.fetch(:ball).should be_eql('1')
41
+ Timecop.freeze(now + 10.minutes)
42
+ Retriever.fetch(:ball).should be_eql('1')
43
+ Timecop.freeze(now + 10.minutes + 1.second)
44
+ Retriever.fetch(:ball).should be_eql('2')
45
+ Timecop.freeze(now + 15.minutes)
46
+ Retriever.fetch(:ball).should be_eql('2')
47
+ Timecop.freeze(now)
48
+ Retriever.fetch(:ball).should be_eql('2')
49
+ Timecop.freeze(now + 30.minutes)
50
+ Retriever.fetch(:ball).should be_eql('3')
51
+ end
52
+
53
+ it 'should be able to pass parameters' do
54
+ Retriever.catch! do
55
+ target :ball do |arg1, arg2|
56
+ arg1 + arg2
57
+ end
58
+ end
59
+
60
+ Retriever.fetch(:ball, 1, 2).should be_eql('3')
61
+ end
62
+
63
+ it 'should be able to fetch forcefully' do
64
+ now = Time.now
65
+ Timecop.freeze(now)
66
+ Retriever.catch! do
67
+ @counter = 0
68
+ target :ball, :validity => 10.minutes do
69
+ @counter += 1
70
+ end
71
+ end
72
+ Retriever.fetch(:ball).should be_eql('1')
73
+ Retriever.fetch!(:ball).should be_eql('2')
74
+ Retriever.fetch(:ball).should be_eql('2')
75
+ end
76
+
77
+ it 'should be encrypted' do
78
+ Retriever.config.encrypt = true
79
+ Retriever.should be_encrypted
80
+ Retriever.catch! do
81
+ target :ball do
82
+ 'ball'
83
+ end
84
+ end
85
+ Retriever.fetch(:ball).should be_eql('ball')
86
+ end
87
+ end
@@ -0,0 +1,19 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter '/spec/'
4
+ end
5
+
6
+ require File.join(
7
+ File.dirname(__FILE__),
8
+ '..', 'lib', 'retriever')
9
+ require 'timecop'
10
+ require 'active_support'
11
+ require 'active_support/time'
12
+
13
+ RSpec.configure do |config|
14
+ [:all, :each].each do |x|
15
+ config.after(x) do
16
+ Retriever.clean!
17
+ end
18
+ end
19
+ end
metadata ADDED
@@ -0,0 +1,154 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: retriever
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Nelvin Driz
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-09-25 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &70342454584380 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70342454584380
25
+ - !ruby/object:Gem::Dependency
26
+ name: redis
27
+ requirement: &70342454583340 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70342454583340
36
+ - !ruby/object:Gem::Dependency
37
+ name: yajl-ruby
38
+ requirement: &70342454582340 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70342454582340
47
+ - !ruby/object:Gem::Dependency
48
+ name: rails
49
+ requirement: &70342454580180 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70342454580180
58
+ - !ruby/object:Gem::Dependency
59
+ name: timecop
60
+ requirement: &70342454579060 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70342454579060
69
+ - !ruby/object:Gem::Dependency
70
+ name: ruby-debug19
71
+ requirement: &70342454578320 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70342454578320
80
+ - !ruby/object:Gem::Dependency
81
+ name: simplecov
82
+ requirement: &70342454577260 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *70342454577260
91
+ - !ruby/object:Gem::Dependency
92
+ name: activesupport
93
+ requirement: &70342454576500 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ type: :runtime
100
+ prerelease: false
101
+ version_requirements: *70342454576500
102
+ description: ! "\n Retriever allows caching of the result of a block. It currently
103
+ supports ruby memory storage and redis.\n "
104
+ email:
105
+ - ndriz@exist.com
106
+ executables: []
107
+ extensions: []
108
+ extra_rdoc_files: []
109
+ files:
110
+ - .gitignore
111
+ - Gemfile
112
+ - LICENSE.txt
113
+ - README.rdoc
114
+ - Rakefile
115
+ - lib/retriever.rb
116
+ - lib/retriever/config.rb
117
+ - lib/retriever/instruction.rb
118
+ - lib/retriever/storage/ephemeral.rb
119
+ - lib/retriever/storage/redis.rb
120
+ - lib/retriever/version.rb
121
+ - retriever.gemspec
122
+ - spec/lib/custom_storage_spec.rb
123
+ - spec/lib/default_spec.rb
124
+ - spec/lib/redis_spec.rb
125
+ - spec/spec_helper.rb
126
+ homepage: http://github.com/Keoven/Retriever
127
+ licenses: []
128
+ post_install_message:
129
+ rdoc_options: []
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ none: false
134
+ requirements:
135
+ - - ! '>='
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ! '>='
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ requirements: []
145
+ rubyforge_project: retriever
146
+ rubygems_version: 1.8.10
147
+ signing_key:
148
+ specification_version: 3
149
+ summary: Retriever is a block result caching library.
150
+ test_files:
151
+ - spec/lib/custom_storage_spec.rb
152
+ - spec/lib/default_spec.rb
153
+ - spec/lib/redis_spec.rb
154
+ - spec/spec_helper.rb