rocket_pants 1.2.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/rocket_pants.rb +5 -1
- data/lib/rocket_pants/base.rb +2 -0
- data/lib/rocket_pants/cache_middleware.rb +3 -3
- data/lib/rocket_pants/controller/header_metadata.rb +38 -0
- data/lib/rocket_pants/controller/linking.rb +41 -0
- data/lib/rocket_pants/controller/respondable.rb +18 -4
- data/lib/rocket_pants/railtie.rb +4 -2
- data/lib/rocket_pants/test_helper.rb +1 -1
- metadata +4 -2
data/lib/rocket_pants.rb
CHANGED
@@ -32,17 +32,21 @@ module RocketPants
|
|
32
32
|
autoload :JSONP, 'rocket_pants/controller/jsonp'
|
33
33
|
autoload :Rescuable, 'rocket_pants/controller/rescuable'
|
34
34
|
autoload :Respondable, 'rocket_pants/controller/respondable'
|
35
|
+
autoload :HeaderMetadata, 'rocket_pants/controller/header_metadata'
|
36
|
+
autoload :Linking, 'rocket_pants/controller/linking'
|
35
37
|
autoload :Versioning, 'rocket_pants/controller/versioning'
|
36
38
|
autoload :FormatVerification, 'rocket_pants/controller/format_verification'
|
37
39
|
autoload :UrlFor, 'rocket_pants/controller/url_for'
|
38
40
|
|
39
|
-
mattr_accessor :caching_enabled
|
41
|
+
mattr_accessor :caching_enabled, :header_metadata
|
40
42
|
self.caching_enabled = false
|
43
|
+
self.header_metadata = false
|
41
44
|
|
42
45
|
mattr_writer :cache
|
43
46
|
|
44
47
|
class << self
|
45
48
|
alias caching_enabled? caching_enabled
|
49
|
+
alias header_metadata? header_metadata
|
46
50
|
|
47
51
|
def cache
|
48
52
|
@@cache ||= Moneta::Memory.new
|
data/lib/rocket_pants/base.rb
CHANGED
@@ -2,6 +2,7 @@ module RocketPants
|
|
2
2
|
class CacheMiddleware
|
3
3
|
|
4
4
|
NOT_MODIFIED = [304, {}, []]
|
5
|
+
DIVIDER = ":"
|
5
6
|
|
6
7
|
def initialize(app)
|
7
8
|
@app = app
|
@@ -29,7 +30,6 @@ module RocketPants
|
|
29
30
|
|
30
31
|
def has_valid_etag?
|
31
32
|
return false if (etags = request_etags).blank?
|
32
|
-
debug ""
|
33
33
|
etags.any? do |etag|
|
34
34
|
cache_key, value = extract_cache_key_and_value etag
|
35
35
|
debug "Processing cache key for path #{request_path}"
|
@@ -39,7 +39,7 @@ module RocketPants
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def extract_cache_key_and_value(etag)
|
42
|
-
etag.to_s.split(
|
42
|
+
etag.to_s.split(DIVIDER, 2)
|
43
43
|
end
|
44
44
|
|
45
45
|
def fresh?(key, value)
|
@@ -48,7 +48,7 @@ module RocketPants
|
|
48
48
|
|
49
49
|
def request_etags
|
50
50
|
stored = @env['HTTP_IF_NONE_MATCH']
|
51
|
-
stored.present? && stored.to_s.scan(/"([^"]+)"/)
|
51
|
+
stored.present? && stored.to_s.scan(/"([^"]+)"/).flatten.select { |i| i.include?(DIVIDER) }
|
52
52
|
end
|
53
53
|
|
54
54
|
def debug(message)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module RocketPants
|
2
|
+
module HeaderMetadata
|
3
|
+
|
4
|
+
# Given a hash of request metadata, will:
|
5
|
+
# 1. Write out the headers for the current metadata
|
6
|
+
# 2. Return the hash, suitable for merging into the response hash
|
7
|
+
# 3. Start a dance party.
|
8
|
+
#
|
9
|
+
# @param [Hash{Symbol => Object}] metadata the hash of the request metadata.
|
10
|
+
# @return [Hash{Symbol => Object}] the passed in metadata
|
11
|
+
def expose_metadata(metadata)
|
12
|
+
metadata_headers { build_header_hash(metadata) }
|
13
|
+
super # Call any other versions of the method.
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
# Given a block which returns a Hash, will call and merge the block iff header metadata
|
18
|
+
# is enabled. This is to avoid the overhead of generating headers on every request when
|
19
|
+
# it's disabled.
|
20
|
+
def metadata_headers(&blk)
|
21
|
+
headers.merge! blk.call if RocketPants.header_metadata?
|
22
|
+
end
|
23
|
+
|
24
|
+
def build_header_hash(options, hash = {}, prefix = 'X-Api')
|
25
|
+
options.each_pair do |k, v|
|
26
|
+
current = "#{prefix}-#{k.to_s.titleize.tr(" ", "-")}"
|
27
|
+
if v.is_a?(Hash)
|
28
|
+
build_header_hash v, hash, current
|
29
|
+
else
|
30
|
+
value = Array(v).join(", ")
|
31
|
+
hash[current] = value if value.present?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
hash
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module RocketPants
|
2
|
+
module Linking
|
3
|
+
|
4
|
+
# Generates a Link: header with the specified rel, uri and attributes.
|
5
|
+
# @param [String, Symbol] rel the relation of the given link
|
6
|
+
# @param [String] uri the full uri to the specified link resource
|
7
|
+
# @param [Hash] attributes any other attributes for the link
|
8
|
+
def link(rel, uri, attributes = {})
|
9
|
+
headers['Link'] ||= []
|
10
|
+
attributes = {:rel => rel}.merge(attributes)
|
11
|
+
link = "<#{uri}>"
|
12
|
+
attributes.each_pair { |k, v| link << "; #{k}=\"#{v}\"" }
|
13
|
+
headers['Link'] << link
|
14
|
+
end
|
15
|
+
|
16
|
+
# Lets you add a series of links for the current resource.
|
17
|
+
# @param [Hash{Symbol => String}] links a hash of links. Those with nil as the value are skipped.
|
18
|
+
def links(links = {})
|
19
|
+
links.each_pair do |rel, uri|
|
20
|
+
link rel, uri if uri
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Hook method - Implement this to link to the current resource and we'll automatically add header links.
|
25
|
+
def page_url(page)
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def expose_metadata(metadata)
|
30
|
+
super.tap do |meta|
|
31
|
+
if RocketPants.header_metadata? && (pagination = meta[:pagination])
|
32
|
+
links :next => (pagination[:next] && page_url(pagination[:next])),
|
33
|
+
:prev => (pagination[:previous] && page_url(pagination[:previous])),
|
34
|
+
:last => (pagination[:pages] && page_url(pagination[:pages])),
|
35
|
+
:first => page_url(1)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -96,10 +96,11 @@ module RocketPants
|
|
96
96
|
def collection(collection, options = {})
|
97
97
|
pre_process_exposed_object collection, :collection, false
|
98
98
|
options = options.reverse_merge(:compact => true)
|
99
|
+
meta = expose_metadata(:count => collection.length)
|
99
100
|
render_json({
|
100
101
|
:response => normalise_object(collection, options),
|
101
102
|
:count => collection.length
|
102
|
-
}, options)
|
103
|
+
}.merge(meta), options)
|
103
104
|
post_process_exposed_object collection, :collection, false
|
104
105
|
end
|
105
106
|
|
@@ -107,11 +108,13 @@ module RocketPants
|
|
107
108
|
def paginated(collection, options = {})
|
108
109
|
pre_process_exposed_object collection, :paginated, false
|
109
110
|
options = options.reverse_merge(:compact => true)
|
110
|
-
|
111
|
-
:response => normalise_object(collection, options),
|
111
|
+
meta = expose_metadata({
|
112
112
|
:count => collection.length,
|
113
113
|
:pagination => Respondable.extract_pagination(collection)
|
114
|
-
}
|
114
|
+
})
|
115
|
+
render_json({
|
116
|
+
:response => normalise_object(collection, options),
|
117
|
+
}.merge(meta), options)
|
115
118
|
post_process_exposed_object collection, :paginated, false
|
116
119
|
end
|
117
120
|
|
@@ -146,5 +149,16 @@ module RocketPants
|
|
146
149
|
def post_process_exposed_object(resource, type, singular)
|
147
150
|
end
|
148
151
|
|
152
|
+
# Given a hash of request metadata, will:
|
153
|
+
# 1. Do anything special with the request metadata
|
154
|
+
# 2. Return the hash, suitable for merging into the response hash
|
155
|
+
# 3. Start a dance party.
|
156
|
+
#
|
157
|
+
# @param [Hash{Symbol => Object}] metadata the hash of the request metadata.
|
158
|
+
# @return [Hash{Symbol => Object}] the passed in metadata
|
159
|
+
def expose_metadata(metadata)
|
160
|
+
metadata
|
161
|
+
end
|
162
|
+
|
149
163
|
end
|
150
164
|
end
|
data/lib/rocket_pants/railtie.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
module RocketPants
|
2
2
|
class Railtie < Rails::Railtie
|
3
3
|
|
4
|
-
config.rocket_pants
|
5
|
-
config.rocket_pants.use_caching
|
4
|
+
config.rocket_pants = ActiveSupport::OrderedOptions.new
|
5
|
+
config.rocket_pants.use_caching = nil
|
6
|
+
config.rocket_pants.header_metadata = nil
|
6
7
|
|
7
8
|
config.i18n.railties_load_path << File.expand_path('../locale/en.yml', __FILE__)
|
8
9
|
|
@@ -14,6 +15,7 @@ module RocketPants
|
|
14
15
|
rp_config = app.config.rocket_pants
|
15
16
|
rp_config.use_caching = Rails.env.production? if rp_config.use_caching.nil?
|
16
17
|
RocketPants.caching_enabled = rp_config.use_caching
|
18
|
+
RocketPants.header_metadata = rp_config.header_metadata unless rp_config.header_metadata.nil?
|
17
19
|
# Set the rocket pants cache if present.
|
18
20
|
RocketPants.cache = rp_config.cache if rp_config.cache
|
19
21
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rocket_pants
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-05-
|
12
|
+
date: 2012-05-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: actionpack
|
@@ -250,8 +250,10 @@ files:
|
|
250
250
|
- lib/rocket_pants/controller/caching.rb
|
251
251
|
- lib/rocket_pants/controller/error_handling.rb
|
252
252
|
- lib/rocket_pants/controller/format_verification.rb
|
253
|
+
- lib/rocket_pants/controller/header_metadata.rb
|
253
254
|
- lib/rocket_pants/controller/instrumentation.rb
|
254
255
|
- lib/rocket_pants/controller/jsonp.rb
|
256
|
+
- lib/rocket_pants/controller/linking.rb
|
255
257
|
- lib/rocket_pants/controller/rescuable.rb
|
256
258
|
- lib/rocket_pants/controller/respondable.rb
|
257
259
|
- lib/rocket_pants/controller/url_for.rb
|