httparty-icebox-delooks 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .DS_Store
6
+ vendor/
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/History ADDED
@@ -0,0 +1,16 @@
1
+ == 0.0.4 2012-01-03
2
+ * minor enhancements
3
+ * Update gemspec to depend on HTTParty 0.8.X to fix YAML issues.
4
+
5
+ == 0.0.3
6
+ * minor enhancements
7
+ * Remove the output from setting a cache.
8
+
9
+ == 0.0.2
10
+ * minor enhancements
11
+ * Return a cached result if network fails. [Andreas Garnæs]
12
+
13
+ == 0.0.1
14
+
15
+ * major enhancements
16
+ * Initial release.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Kristoffer Sachse
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # HTTParty-Icebox - Caching for HTTParty
2
+
3
+ ## Description
4
+
5
+ Cache responses in HTTParty models
6
+
7
+ ## Installation
8
+
9
+ ### RubyGems
10
+
11
+ You can install the latest Film Buff gem using RubyGems
12
+
13
+ gem install httparty-icebox
14
+
15
+ ### GitHub
16
+
17
+ Alternatively you can check out the latest code directly from Github
18
+
19
+ git clone http://github.com/sachse/httparty-icebox.git
20
+
21
+ ## Usage
22
+
23
+
24
+
25
+ ### Examples
26
+
27
+ Enable caching with default values:
28
+
29
+ require 'httparty-icebox'
30
+
31
+ include HTTParty::Icebox
32
+
33
+ cache
34
+ # Use HTTParty's .get method as usual, the response will now be cached
35
+ cached_response = HTTParty.get("https://github.com/sachse/httparty-icebox")
36
+
37
+ Cache responses for 5 minutes on the system in the directory "/tmp":
38
+
39
+ require 'httparty-icebox'
40
+
41
+ include HTTParty::Icebox
42
+
43
+ cache :store => 'file', :timeout => 300, :location => '/tmp/'
44
+ # Use HTTParty's .get method as usual, the response will now be cached
45
+ cached_response = HTTParty.get("https://github.com/sachse/httparty-icebox")
46
+
47
+ ## Authors
48
+
49
+ - [Kristoffer Sachse](https://github.com/sachse) (Current maintainer)
50
+
51
+ - [Karel Minarik](http://karmi.cz) (Original creator through [a gist](https://gist.github.com/209521/))
52
+
53
+ ## Contribute
54
+
55
+ Fork the project, implement your changes in it's own branch, and send
56
+ a pull request to me. I'll gladly consider any help or ideas.
57
+
58
+ ### Contributors
59
+
60
+ - [Martyn Loughran](https://github.com/mloughran) - Major parts of this code are based on the architecture of ApiCache.
61
+ - [David Heinemeier Hansson](https://github.com/dhh) - Other parts are inspired by the ActiveSupport::Cache in Ruby On Rails.
62
+ - [Amit Chakradeo](https://github.com/amit) - For pointing out response objects have to be stored marshalled on FS.
63
+ - Marlin Forbes - For pointing out the query parameters have to be included in the cache key.
64
+ - [ramieblatt](https://github.com/ramieblatt) - Original Memcached store.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "httparty-icebox/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "httparty-icebox-delooks"
7
+ s.version = Httparty::Icebox::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Kristoffer Sachse", "Karel Minarik"]
10
+ s.email = ["kristoffer@sachse.nu"]
11
+ s.homepage = "https://github.com/sachse/httparty-icebox"
12
+ s.summary = %q{Caching for HTTParty}
13
+ s.description = %q{Cache responses in HTTParty models}
14
+
15
+ s.rubyforge_project = "httparty-icebox"
16
+
17
+ s.add_dependency("httparty", "~> 0.8.1")
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.require_paths = ["lib"]
21
+ end
@@ -0,0 +1,5 @@
1
+ module Httparty
2
+ module Icebox
3
+ VERSION = "0.0.4"
4
+ end
5
+ end
@@ -0,0 +1,233 @@
1
+ require 'logger'
2
+ require 'fileutils'
3
+ require 'tmpdir'
4
+ require 'pathname'
5
+ require 'digest/md5'
6
+
7
+ module HTTParty #:nodoc:
8
+ # == Caching for HTTParty
9
+ # See documentation in HTTParty::Icebox::ClassMethods.cache
10
+ #
11
+ module Icebox
12
+
13
+ module ClassMethods
14
+
15
+ # Enable caching and set cache options
16
+ # Returns memoized cache object
17
+ #
18
+ # Following options are available, default values are in []:
19
+ #
20
+ # +store+:: Storage mechanism for cached data (memory, filesystem, your own) [memory]
21
+ # +timeout+:: Cache expiration in seconds [60]
22
+ # +logger+:: Path to logfile or logger instance [nil, silent]
23
+ #
24
+ # Any additional options are passed to the Cache constructor
25
+ #
26
+ # Usage:
27
+ #
28
+ # # Enable caching in HTTParty, in memory, for 1 minute
29
+ # cache # Use default values
30
+ #
31
+ # # Enable caching in HTTParty, on filesystem (/tmp), for 10 minutes
32
+ # cache :store => 'file', :timeout => 600, :location => '/tmp/'
33
+ #
34
+ # # Use your own cache store (see +AbstractStore+ class below)
35
+ # cache :store => 'memcached', :timeout => 600, :server => '192.168.1.1:1001'
36
+ #
37
+ def cache(options={})
38
+ options[:store] ||= 'memory'
39
+ options[:timeout] ||= 60
40
+ logger = options[:logger]
41
+ @cache ||= Cache.new( options.delete(:store), options )
42
+ end
43
+
44
+ end
45
+
46
+ # When included, extend class with +cache+ method
47
+ # and redefine +get+ method to use cache
48
+ #
49
+ def self.included(receiver) #:nodoc:
50
+ receiver.extend ClassMethods
51
+ receiver.class_eval do
52
+
53
+ # Get reponse from network
54
+ #
55
+ # TODO: Why alias :new :old is not working here? Returns NoMethodError
56
+ #
57
+ def self.get_without_caching(path, options={})
58
+ perform_request Net::HTTP::Get, path, options
59
+ end
60
+
61
+ # Get response from cache, if available
62
+ #
63
+ def self.get_with_caching(path, options={})
64
+ key = path.downcase # this makes a copy of path
65
+ key << options[:query].to_s if defined? options[:query]
66
+ if cache.exists?(key) and not cache.stale?(key)
67
+ Cache.logger.debug "CACHE -- GET #{path}#{options[:query]}"
68
+ return cache.get(key)
69
+ else
70
+ Cache.logger.debug "/!\\ NETWORK -- GET #{path}#{options[:query]}"
71
+
72
+ begin
73
+ response = get_without_caching(path, options)
74
+ cache.set(key, response) if response.code.to_s == "200" # this works for string and integer response codes
75
+ return response
76
+ rescue
77
+ if cache.exists?(key)
78
+ Cache.logger.debug "!!! NETWORK FAILED -- RETURNING STALE CACHE"
79
+ return cache.get(key, true)
80
+ else
81
+ raise
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ # Redefine original HTTParty +get+ method to use cache
88
+ #
89
+ def self.get(path, options={})
90
+ self.get_with_caching(path, options)
91
+ end
92
+
93
+ end
94
+ end
95
+
96
+ # === Cache container
97
+ #
98
+ # Pass a store name ('memory', etc) to new
99
+ #
100
+ class Cache
101
+ attr_accessor :store
102
+
103
+ def initialize(store, options={})
104
+ self.class.logger = options[:logger]
105
+ @store = self.class.lookup_store(store).new(options)
106
+ end
107
+
108
+ def get(key, force=false)
109
+ @store.get encode(key) if !stale?(key) || force
110
+ end
111
+
112
+ def set(key, value)
113
+ @store.set encode(key), value
114
+ end
115
+
116
+ def exists?(key)
117
+ @store.exists? encode(key)
118
+ end
119
+
120
+ def stale?(key)
121
+ @store.stale? encode(key)
122
+ end
123
+
124
+ def self.logger; @logger || default_logger; end
125
+ def self.default_logger; logger = ::Logger.new(STDERR); end
126
+
127
+ # Pass a filename (String), IO object, Logger instance or +nil+ to silence the logger
128
+ def self.logger=(device); @logger = device.kind_of?(::Logger) ? device : ::Logger.new(device); end
129
+
130
+ private
131
+
132
+ # Return store class based on passed name
133
+ def self.lookup_store(name)
134
+ store_name = "#{name.capitalize}Store"
135
+ return Store::const_get(store_name)
136
+ rescue NameError => e
137
+ raise Store::StoreNotFound, "The cache store '#{store_name}' was not found. Did you load any such class?"
138
+ end
139
+
140
+ def encode(key); Digest::MD5.hexdigest(key); end
141
+ end
142
+
143
+
144
+ # === Cache stores
145
+ #
146
+ module Store
147
+
148
+ class StoreNotFound < StandardError; end #:nodoc:
149
+
150
+ # ==== Abstract Store
151
+ # Inherit your store from this class
152
+ # *IMPORTANT*: Do not forget to call +super+ in your +initialize+ method!
153
+ #
154
+ class AbstractStore
155
+ def initialize(options={})
156
+ raise ArgumentError, "You need to set the :timeout parameter" unless options[:timeout]
157
+ @timeout = options[:timeout]
158
+ message = "Cache: Using #{self.class.to_s.split('::').last}"
159
+ message << " in location: #{options[:location]}" if options[:location]
160
+ message << " with timeout #{options[:timeout]} sec"
161
+ Cache.logger.info message unless options[:logger].nil?
162
+ return self
163
+ end
164
+ %w{set get exists? stale?}.each do |method_name|
165
+ define_method(method_name) { raise NoMethodError, "Please implement method #{method_name} in your store class" }
166
+ end
167
+ end
168
+
169
+ # ==== Store objects in memory
170
+ # See HTTParty::Icebox::ClassMethods.cache
171
+ #
172
+ class MemoryStore < AbstractStore
173
+ def initialize(options={})
174
+ super; @store = {}; self
175
+ end
176
+ def set(key, value)
177
+ Cache.logger.info("Cache: set (#{key})")
178
+ @store[key] = [Time.now, value]; true
179
+ end
180
+ def get(key)
181
+ data = @store[key][1]
182
+ Cache.logger.info("Cache: #{data.nil? ? "miss" : "hit"} (#{key})")
183
+ data
184
+ end
185
+ def exists?(key)
186
+ !@store[key].nil?
187
+ end
188
+ def stale?(key)
189
+ return true unless exists?(key)
190
+ Time.now - created(key) > @timeout
191
+ end
192
+ private
193
+ def created(key)
194
+ @store[key][0]
195
+ end
196
+ end
197
+
198
+ # ==== Store objects on the filesystem
199
+ # See HTTParty::Icebox::ClassMethods.cache
200
+ #
201
+ class FileStore < AbstractStore
202
+ def initialize(options={})
203
+ super
204
+ options[:location] ||= Dir::tmpdir
205
+ @path = Pathname.new( options[:location] )
206
+ FileUtils.mkdir_p( @path )
207
+ self
208
+ end
209
+ def set(key, value)
210
+ Cache.logger.info("Cache: set (#{key})")
211
+ File.open( @path.join(key), 'w' ) { |file| file << Marshal.dump(value) }
212
+ true
213
+ end
214
+ def get(key)
215
+ data = Marshal.load(File.read( @path.join(key)))
216
+ Cache.logger.info("Cache: #{data.nil? ? "miss" : "hit"} (#{key})")
217
+ data
218
+ end
219
+ def exists?(key)
220
+ File.exists?( @path.join(key) )
221
+ end
222
+ def stale?(key)
223
+ return true unless exists?(key)
224
+ Time.now - created(key) > @timeout
225
+ end
226
+ private
227
+ def created(key)
228
+ File.mtime( @path.join(key) )
229
+ end
230
+ end
231
+ end
232
+ end
233
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: httparty-icebox-delooks
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Kristoffer Sachse
9
+ - Karel Minarik
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-06-06 00:00:00.000000000Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: httparty
17
+ requirement: &70275493267740 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: 0.8.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *70275493267740
26
+ description: Cache responses in HTTParty models
27
+ email:
28
+ - kristoffer@sachse.nu
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - .gitignore
34
+ - Gemfile
35
+ - History
36
+ - LICENSE
37
+ - README.md
38
+ - Rakefile
39
+ - httparty-icebox.gemspec
40
+ - lib/httparty-icebox.rb
41
+ - lib/httparty-icebox/version.rb
42
+ homepage: https://github.com/sachse/httparty-icebox
43
+ licenses: []
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ requirements: []
61
+ rubyforge_project: httparty-icebox
62
+ rubygems_version: 1.8.17
63
+ signing_key:
64
+ specification_version: 3
65
+ summary: Caching for HTTParty
66
+ test_files: []