grape-shaman_cache 0.1.1

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,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in grape-shaman_cache.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Victor Wang
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,71 @@
1
+ # Grape::ShamanCache
2
+
3
+ ## Features
4
+
5
+ HTTP and server side cache integration for Grape and Jbuilder without Rails application.
6
+
7
+ If you're not familiar with HTTP caching, ETags and If-Modified-Since, here are some resources.
8
+
9
+ * [From Zero to API Cache w/ Grape & MongoDB in 10 Minutes](http://www.confreaks.com/videos/986-goruco2012-from-zero-to-api-cache-w-grape-mongodb-in-10-minutes)
10
+ * [Doing HTTP Caching Right: Introducing httplib2](http://www.xml.com/lpt/a/1642)
11
+ * [Introducing Rack::Cache](http://tomayko.com/writings/rack-cache-announce)
12
+
13
+
14
+ ## Installation
15
+
16
+ Add this line to your application's Gemfile:
17
+
18
+ gem 'grape-shaman_cache'
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install grape-shaman_cache
27
+
28
+ remember to modify your config.ru file:
29
+
30
+ ```
31
+ use Rack::ConditionalGet
32
+ use Rack::ETag
33
+ ```
34
+
35
+ ## Usage
36
+
37
+ ```
38
+ class Welcome < Grape::API
39
+
40
+ include Grape::ShamanCache
41
+
42
+ format :json
43
+ formatter :json, Grape::Formatter::Jbuilder
44
+
45
+ get :home, jbuilder: 'welcome/home' do
46
+ @banners = Article.banner.without_gifts
47
+ cache(key: [:v2, :home, @banners.last], expires_in: 2.hours) do
48
+ @banners
49
+ end
50
+ end
51
+
52
+ end
53
+ ```
54
+
55
+ ## Configuration
56
+
57
+ By default `Grape::ShamanCache` will use an instance of `ActiveSupport::Cache::MemoryStore` in a non-Rails application. You can configure it to use any other cache store.
58
+
59
+ ```
60
+ Grape::ShamanCache.configure do |config|
61
+ config.cache = ActiveSupport::Cache::FileStore.new("tmp/cache")
62
+ end
63
+ ```
64
+
65
+ ## Contributing
66
+
67
+ 1. Fork it
68
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
69
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
70
+ 4. Push to the branch (`git push origin my-new-feature`)
71
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'grape-shaman_cache/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.authors = ["Victor Wang"]
8
+ gem.email = ["wjp2013@gmail.com"]
9
+ gem.description = %q{HTTP and server side cache integration for Grape and Rack applications}
10
+ gem.summary = %q{HTTP and server side cache integration for Grape and Rack applications}
11
+ gem.homepage = ""
12
+
13
+ gem.files = `git ls-files`.split($\)
14
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
15
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
16
+ gem.name = "grape-shaman_cache"
17
+ gem.require_paths = ["lib"]
18
+ gem.version = Grape::ShamanCache::VERSION
19
+
20
+ gem.add_dependency "grape", ">= 0.6.1"
21
+ gem.add_dependency "jbuilder"
22
+ gem.add_dependency "activesupport"
23
+
24
+ gem.add_development_dependency "bundler", "~> 1.3"
25
+ gem.add_development_dependency "rake"
26
+ end
@@ -0,0 +1,4 @@
1
+ require "grape-shaman_cache/version"
2
+ require "grape-shaman_cache/config"
3
+ require "grape-shaman_cache/formatter"
4
+ require "grape-shaman_cache/shaman_cache"
@@ -0,0 +1,103 @@
1
+ module Grape
2
+ module ShamanCache
3
+
4
+ class << self
5
+ # Set the configuration options. Best used by passing a block.
6
+ #
7
+ # @example Set up configuration options.
8
+ # ShamanCache.configure do |config|
9
+ # config.cache = Rails.cache
10
+ # end
11
+ #
12
+ # @return [Config] The configuration object.
13
+ def configure
14
+ block_given? ? yield(ShamanCache::Config) : ShamanCache::Config
15
+ end
16
+ alias :config :configure
17
+ end
18
+
19
+ module Config
20
+ extend self
21
+
22
+ # Current configuration settings.
23
+ attr_accessor :settings
24
+
25
+ # Default configuration settings.
26
+ attr_accessor :defaults
27
+
28
+ @settings = {}
29
+ @defaults = {}
30
+
31
+ # Define a configuration option with a default.
32
+ #
33
+ # @example Define the option.
34
+ # Config.option(:cache, :default => nil)
35
+ #
36
+ # @param [Symbol] name The name of the configuration option.
37
+ # @param [Hash] options Extras for the option.
38
+ #
39
+ # @option options [Object] :default The default value.
40
+ def option(name, options = {})
41
+ defaults[name] = settings[name] = options[:default]
42
+
43
+ class_eval <<-RUBY
44
+ def #{name}
45
+ settings[#{name.inspect}]
46
+ end
47
+
48
+ def #{name}=(value)
49
+ settings[#{name.inspect}] = value
50
+ end
51
+
52
+ def #{name}?
53
+ #{name}
54
+ end
55
+ RUBY
56
+ end
57
+
58
+ # Returns the default cache store, either Rails.cache or an instance
59
+ # of ActiveSupport::Cache::MemoryStore.
60
+ #
61
+ # @example Get the default cache store
62
+ # config.default_cache
63
+ #
64
+ # @return [Cache] The default cache store instance.
65
+ def default_cache
66
+ if defined?(Rails) && Rails.respond_to?(:cache)
67
+ Rails.cache
68
+ else
69
+ ::ActiveSupport::Cache::MemoryStore.new
70
+ end
71
+ end
72
+
73
+ # Returns the cache, or defaults to Rails cache when running in Rails
74
+ # or an instance of ActiveSupport::Cache::MemoryStore otherwise.
75
+ #
76
+ # @example Get the cache.
77
+ # config.cache
78
+ #
79
+ # @return [Cache] The configured cache or a default cache instance.
80
+ def cache
81
+ settings[:cache] = default_cache unless settings.has_key?(:cache)
82
+ settings[:cache]
83
+ end
84
+
85
+ # Sets the cache to use.
86
+ #
87
+ # @example Set the cache.
88
+ # config.cache = Rails.cache
89
+ #
90
+ # @return [Cache] The newly set cache.
91
+ def cache=(cache)
92
+ settings[:cache] = cache
93
+ end
94
+
95
+ # Default cache options
96
+ option(:global_cache_options, :default => {})
97
+
98
+ # Default cache expiration time.
99
+ option(:expires_in, :default => nil)
100
+ end
101
+
102
+ end
103
+ end
@@ -0,0 +1,23 @@
1
+ # Rewrite Grape::Formatter::Jbuilder.call defined by 'grape-jbuilder' gem.
2
+ module Grape
3
+ module Formatter
4
+ # For maximum performance we are fetching string from redis and return them with no parsing at all
5
+ module Jbuilder
6
+ def self.call(object, env)
7
+ @env = env
8
+ @endpoint = env['api.endpoint']
9
+ # object is string means that we need to use cache
10
+ return object if object.is_a?(String)
11
+
12
+ if jbuilderable?
13
+ jbuilder do |template|
14
+ engine = ::Tilt.new(view_path(template), nil, view_path: env['api.tilt.root'])
15
+ engine.render(endpoint, {})
16
+ end
17
+ else
18
+ Grape::Formatter::Json.call object, env
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,56 @@
1
+ module Grape
2
+ module ShamanCache
3
+
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ helpers do
8
+
9
+ # Based on actionpack/lib/action_controller/base.rb, line 1216
10
+ def expires_in(seconds, options = {})
11
+ cache_control = []
12
+ cache_control << "max-age=#{seconds}"
13
+ cache_control.delete("no-cache")
14
+ if options[:public]
15
+ cache_control.delete("private")
16
+ cache_control << "public"
17
+ else
18
+ cache_control << "private"
19
+ end
20
+
21
+ # This allows for additional headers to be passed through like 'max-stale' => 5.hours
22
+ cache_control += options.symbolize_keys.reject{|k,v| k == :public || k == :private }.map{ |k,v| v == true ? k.to_s : "#{k.to_s}=#{v.to_s}"}
23
+
24
+ header "Cache-Control", cache_control.join(', ')
25
+ end
26
+
27
+ def default_expire_time
28
+ 2.hours
29
+ end
30
+
31
+ def cache(opts = {}, &block)
32
+ # HTTP Cache
33
+ cache_key = ActiveSupport::Cache.expand_cache_key(opts[:key])
34
+
35
+ # compare_etag(opts[:etag]) # Check if client has fresh version
36
+ # Check if client has fresh version
37
+
38
+ # Set Cache-Control
39
+ expire_time = opts[:expires_in] || default_expire_time
40
+ expires_in(expire_time, public: true)
41
+
42
+ # Try to fetch from server side cache
43
+ # MemCacheStore's write method supports the :raw option
44
+ # which tells the memcached server to store all values as strings.
45
+ cache = Grape::ShamanCache.config.cache
46
+ cache.fetch(cache_key, raw: true, expires_in: expire_time) do
47
+ Grape::Formatter::Jbuilder.call block, env
48
+ end
49
+ end
50
+
51
+ end
52
+ end
53
+
54
+
55
+ end
56
+ end
@@ -0,0 +1,5 @@
1
+ module Grape
2
+ module ShamanCache
3
+ VERSION = "0.1.1"
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: grape-shaman_cache
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Victor Wang
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-12-19 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: grape
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.6.1
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.6.1
30
+ - !ruby/object:Gem::Dependency
31
+ name: jbuilder
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: activesupport
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
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: bundler
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '1.3'
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: '1.3'
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
+ description: HTTP and server side cache integration for Grape and Rack applications
95
+ email:
96
+ - wjp2013@gmail.com
97
+ executables: []
98
+ extensions: []
99
+ extra_rdoc_files: []
100
+ files:
101
+ - .gitignore
102
+ - Gemfile
103
+ - LICENSE
104
+ - README.md
105
+ - Rakefile
106
+ - grape-shaman_cache.gemspec
107
+ - lib/grape-shaman_cache.rb
108
+ - lib/grape-shaman_cache/config.rb
109
+ - lib/grape-shaman_cache/formatter.rb
110
+ - lib/grape-shaman_cache/shaman_cache.rb
111
+ - lib/grape-shaman_cache/version.rb
112
+ homepage: ''
113
+ licenses: []
114
+ post_install_message:
115
+ rdoc_options: []
116
+ require_paths:
117
+ - lib
118
+ required_ruby_version: !ruby/object:Gem::Requirement
119
+ none: false
120
+ requirements:
121
+ - - ! '>='
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ none: false
126
+ requirements:
127
+ - - ! '>='
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ requirements: []
131
+ rubyforge_project:
132
+ rubygems_version: 1.8.24
133
+ signing_key:
134
+ specification_version: 3
135
+ summary: HTTP and server side cache integration for Grape and Rack applications
136
+ test_files: []