rack-action 0.5.1 → 0.7.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.
- checksums.yaml +5 -5
- data/.ruby-version +1 -0
- data/README.md +21 -11
- data/config.ru +2 -2
- data/lib/rack-action.rb +1 -1
- data/lib/rack/action.rb +231 -230
- data/lib/rack/filters.rb +22 -23
- data/lib/rack_action.rb +1 -1
- data/rack-action.gemspec +5 -7
- data/test/rack/action_test.rb +16 -40
- data/test/rack_test.rb +10 -9
- metadata +5 -6
- data/.rvmrc +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 03a0d1b48c3ca9e035024d5dabf9c428149985a3e06505476ae3489f6c940f97
|
4
|
+
data.tar.gz: 033546be4fbd8556aaa176997d9233c85a042d893665369cbd14945a34aa6f59
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d6600e20be07734a3630f3ca4f880fe70fe573ce824f09fbd18ad83011bcd84fad610b45cfad52afa9b5e4e0f0fad4a3842512ec894a46d3d11c56d23ba1d6ce
|
7
|
+
data.tar.gz: a4d754d4828cca5eab3fe8fdcb689e1598dbbc76997ec9fe27bfd8303920aa6807751f7893f80d12911ac6d47ae19e6614773ca99cce274aee891208b8f40499
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.6.6
|
data/README.md
CHANGED
@@ -18,10 +18,10 @@ Or install it yourself as:
|
|
18
18
|
|
19
19
|
## Usage
|
20
20
|
|
21
|
-
Rack::Action provides functionality to generate a Rack response. To use Rack::Action, you should subclass Rack::Action and provide your own implementation of `respond`.
|
21
|
+
Rack::Action provides functionality to generate a Rack response. To use Rack::Action, you should subclass Rack::Action and provide your own implementation of `respond`. The simplest Rack action is
|
22
22
|
one that just returns a string from respond:
|
23
23
|
|
24
|
-
```
|
24
|
+
```ruby
|
25
25
|
require 'rack/action'
|
26
26
|
|
27
27
|
class MyAction < Rack::Action
|
@@ -38,7 +38,7 @@ rackup file. Rack::Action is meant to be used with one action per
|
|
38
38
|
page/endpoint in your application, so it is typically used in conjuction
|
39
39
|
with something like [Rack::Router][rack-router], which would look something like this:
|
40
40
|
|
41
|
-
```
|
41
|
+
```ruby
|
42
42
|
require 'rack/action'
|
43
43
|
require 'rack/router'
|
44
44
|
|
@@ -65,19 +65,29 @@ run router
|
|
65
65
|
Rack::Action makes an instance of [Rack::Request][rack-req] and [Rack::Response][rack-res] available
|
66
66
|
which can be used to set headers, cookies, etc.
|
67
67
|
|
68
|
-
```
|
68
|
+
```ruby
|
69
69
|
class ArticleAction < Rack::Action
|
70
70
|
def respond
|
71
71
|
article = Article.find(params["id"])
|
72
|
-
response['Content-Type'] = "
|
73
|
-
article.
|
72
|
+
response['Content-Type'] = "application/json"
|
73
|
+
article.to_json
|
74
|
+
end
|
75
|
+
end
|
76
|
+
```
|
77
|
+
|
78
|
+
Because responding with JSON is so common, Rack::Action will automatically convert the response to JSON unless the response is a String or an Array. Therefore, the following code snippet provides the same result as the previous:
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
class ArticleAction < Rack::Action
|
82
|
+
def respond
|
83
|
+
Article.find(params["id"])
|
74
84
|
end
|
75
85
|
end
|
76
86
|
```
|
77
87
|
|
78
88
|
You can use before filters to do things before respond is called:
|
79
89
|
|
80
|
-
```
|
90
|
+
```ruby
|
81
91
|
class AccountAction < Rack::Action
|
82
92
|
before_filter :load_current_user
|
83
93
|
|
@@ -93,7 +103,7 @@ end
|
|
93
103
|
|
94
104
|
and you can of course share functionality across actions with inheritance:
|
95
105
|
|
96
|
-
```
|
106
|
+
```ruby
|
97
107
|
class ApplicationAction < Rack::Action
|
98
108
|
before_filter :login_required
|
99
109
|
|
@@ -117,9 +127,9 @@ class PrivateAction < ApplicationAction
|
|
117
127
|
end
|
118
128
|
```
|
119
129
|
|
120
|
-
Before filters will execute in the order they are defined.
|
130
|
+
Before filters will execute in the order they are defined. If a before
|
121
131
|
filter writes to the response, subsequent filters will not be executed
|
122
|
-
and the respond method will not be executed.
|
132
|
+
and the respond method will not be executed. As long as no before filters
|
123
133
|
write to the response, subsequent filters and the respond
|
124
134
|
method will be called.
|
125
135
|
|
@@ -134,4 +144,4 @@ method will be called.
|
|
134
144
|
[rack]: http://rack.github.com/
|
135
145
|
[rack-req]: http://rubydoc.info/gems/rack/Rack/Request
|
136
146
|
[rack-res]: http://rubydoc.info/gems/rack/Rack/Response
|
137
|
-
[rack-router]: https://github.com/pjb3/rack-router
|
147
|
+
[rack-router]: https://github.com/pjb3/rack-router
|
data/config.ru
CHANGED
data/lib/rack-action.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require
|
1
|
+
require "rack/action"
|
data/lib/rack/action.rb
CHANGED
@@ -1,215 +1,224 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
1
|
+
require "time"
|
2
|
+
require "json"
|
3
|
+
require "rack"
|
4
|
+
require_relative "filters"
|
5
|
+
|
6
|
+
class Rack::Action
|
7
|
+
VERSION = "0.7.0".freeze
|
8
|
+
|
9
|
+
extend Rack::Filters
|
10
|
+
|
11
|
+
# @private
|
12
|
+
RACK_ROUTE_PARAMS = "rack.route_params".freeze
|
13
|
+
# @private
|
14
|
+
CONTENT_TYPE = "Content-Type".freeze
|
15
|
+
# @private
|
16
|
+
HTTP_ACCEPT = "HTTP_ACCEPT".freeze
|
17
|
+
# @private
|
18
|
+
TEXT_HTML = "text/html".freeze
|
19
|
+
# @private
|
20
|
+
APPLICATION_JSON = "application/json".freeze
|
21
|
+
# @private
|
22
|
+
LOCATION = "Location".freeze
|
23
|
+
# @private
|
24
|
+
DEFAULT_RESPONSE = "Default Rack::Action Response".freeze
|
25
|
+
# @private
|
26
|
+
RACK_INPUT = "rack.input".freeze
|
27
|
+
|
28
|
+
# This implements the Rack interface
|
29
|
+
#
|
30
|
+
# @param [Hash] env The Rack environment
|
31
|
+
# @return [Array<Numeric, Hash, #each>] A Rack response
|
32
|
+
def self.call(env)
|
33
|
+
new(env).call
|
34
|
+
end
|
36
35
|
|
37
|
-
|
36
|
+
attr_accessor :env
|
37
|
+
attr_writer :request, :response, :params
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
def initialize(env)
|
40
|
+
@env = env
|
41
|
+
end
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
def request
|
44
|
+
@request ||= Rack::Request.new(env)
|
45
|
+
end
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
def response
|
48
|
+
@response ||= Rack::Response.new
|
49
|
+
end
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
end
|
59
|
-
p.respond_to?(:with_indifferent_access) ? p.with_indifferent_access : p
|
51
|
+
def params
|
52
|
+
@params ||= begin
|
53
|
+
p = request.params.merge(env[RACK_ROUTE_PARAMS] || {})
|
54
|
+
if request.content_type.to_s.include?(APPLICATION_JSON)
|
55
|
+
body = env[RACK_INPUT].read
|
56
|
+
env[RACK_INPUT].rewind
|
57
|
+
p.merge!(self.class.json_serializer.load(body)) if body.present?
|
60
58
|
end
|
59
|
+
p.respond_to?(:with_indifferent_access) ? p.with_indifferent_access : p
|
61
60
|
end
|
61
|
+
end
|
62
62
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
end
|
63
|
+
def format
|
64
|
+
if params[:format]
|
65
|
+
params[:format]
|
66
|
+
elsif env[HTTP_ACCEPT] == APPLICATION_JSON
|
67
|
+
"json"
|
68
|
+
else
|
69
|
+
"html"
|
71
70
|
end
|
71
|
+
end
|
72
72
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
73
|
+
# This is the main method responsible for generating a Rack response.
|
74
|
+
# You typically won't need to override this method or call it directly.
|
75
|
+
# First this will run the before filters for this action.
|
76
|
+
# If none of the before filters generate a response, this will call
|
77
|
+
# {#respond} to generate a response.
|
78
|
+
# All after filters for this action are called once the response
|
79
|
+
# is genenated. Finally the response is returned.
|
80
|
+
#
|
81
|
+
# @return [Array<Numeric, Hash, #each>] A Rack response
|
82
|
+
def call
|
83
|
+
log_call
|
84
|
+
set_default_headers
|
85
|
+
run_before_filters
|
86
|
+
run_respond
|
87
|
+
run_after_filters
|
88
|
+
finish_response
|
89
|
+
end
|
90
90
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
91
|
+
# This is the main method that you should override in your action.
|
92
|
+
# You can either write to the response during this method, or simply
|
93
|
+
# return a string, which will be written to the response if the
|
94
|
+
# response is still empty after this is called.
|
95
|
+
#
|
96
|
+
# @return [String] The Rack response or a String
|
97
|
+
def respond
|
98
|
+
DEFAULT_RESPONSE
|
99
|
+
end
|
100
100
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
101
|
+
# This is a convenience method that sets the Content-Type headers
|
102
|
+
# and writes the JSON String to the response.
|
103
|
+
#
|
104
|
+
# @param [Hash] data The data
|
105
|
+
# @param [Hash] options The options
|
106
|
+
# @option options [Fixnum] :status The response status code
|
107
|
+
# @return [String] The JSON
|
108
|
+
def json(data={}, options={})
|
109
|
+
response[CONTENT_TYPE] = APPLICATION_JSON
|
110
|
+
response.status = options[:status] if options.has_key?(:status)
|
111
|
+
response.write self.class.json_serializer.dump(data)
|
112
|
+
end
|
113
113
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
114
|
+
# This is a convenience method that forms an absolute URL based on the
|
115
|
+
# url parameter, which can be a relative or absolute URL, and then
|
116
|
+
# sets the headers and the body appropriately to do a 302 redirect.
|
117
|
+
#
|
118
|
+
# @see #absolute_url
|
119
|
+
# @return [String] The absolute url
|
120
|
+
def redirect_to(url, options={})
|
121
|
+
full_url = absolute_url(url, options)
|
122
|
+
response[LOCATION] = full_url
|
123
|
+
respond_with 302
|
124
|
+
full_url
|
125
|
+
end
|
126
126
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
127
|
+
# Convenience method to return a 404
|
128
|
+
def not_found
|
129
|
+
respond_with 404
|
130
|
+
end
|
131
131
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
132
|
+
# Convenience method to return a 403
|
133
|
+
def forbidden
|
134
|
+
respond_with 403
|
135
|
+
end
|
136
136
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
137
|
+
# This is a convenience method to set the response code and
|
138
|
+
# set the response so that it stops respond process.
|
139
|
+
#
|
140
|
+
# @param [Fixnum] status_code The HTTP status code to use in the response
|
141
|
+
def respond_with(status_code)
|
142
|
+
response.status = status_code
|
143
|
+
response.write ""
|
144
|
+
nil
|
145
|
+
end
|
146
146
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
147
|
+
# Generate an absolute url from the url. If the url is already
|
148
|
+
# an absolute url, this will return it unchanged.
|
149
|
+
#
|
150
|
+
# @param [String] url The URL
|
151
|
+
# @param [Hash] options The options to use to generate the absolute URL
|
152
|
+
# @option options [true, false] :https If https should be used,
|
153
|
+
# uses rack.url_scheme from the Rack env to determine the default
|
154
|
+
# @option options [String] :host The host to use,
|
155
|
+
# uses SERVER_NAME form the Rack env for the default
|
156
|
+
# @option options [String, Numeric] :port The port to use,
|
157
|
+
# users SERVER_PORT from the Rack env for the default
|
158
|
+
# @return [String] The absolute url
|
159
|
+
def absolute_url(url, options={})
|
160
|
+
URL.new(env, url, options).to_absolute
|
161
|
+
end
|
162
162
|
|
163
|
-
|
164
|
-
def log_call
|
165
|
-
if logger
|
166
|
-
logger.debug do
|
167
|
-
"#{self.class} #{request.env["REQUEST_METHOD"]} format: #{format.inspect}, params: #{params.inspect}"
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
163
|
+
protected
|
171
164
|
|
172
|
-
|
173
|
-
|
165
|
+
def log_call
|
166
|
+
logger&.debug do
|
167
|
+
"#{self.class} #{request.env["REQUEST_METHOD"]} format: #{format.inspect}, params: #{params.inspect}"
|
174
168
|
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def set_default_headers
|
172
|
+
response[CONTENT_TYPE] = TEXT_HTML
|
173
|
+
end
|
175
174
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
end
|
175
|
+
def run_before_filters
|
176
|
+
self.class.before_filters.each do |filter|
|
177
|
+
logger&.debug "Running #{filter} before filter"
|
178
|
+
send(filter)
|
179
|
+
unless response.empty?
|
180
|
+
logger&.debug "#{filter} responded, halting filter chain"
|
181
|
+
return
|
184
182
|
end
|
185
183
|
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def run_respond
|
187
|
+
return unless response.empty?
|
186
188
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
if
|
189
|
+
body = respond
|
190
|
+
|
191
|
+
if response.empty?
|
192
|
+
if body.is_a?(String) || body.is_a?(Array)
|
191
193
|
response.write body
|
192
194
|
else
|
193
|
-
body
|
195
|
+
json body
|
194
196
|
end
|
197
|
+
else
|
198
|
+
body
|
195
199
|
end
|
200
|
+
end
|
196
201
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
end
|
202
|
+
def run_after_filters
|
203
|
+
self.class.after_filters.each do |filter|
|
204
|
+
logger&.debug "Running #{filter} after filter"
|
205
|
+
send(filter)
|
202
206
|
end
|
207
|
+
end
|
203
208
|
|
204
|
-
|
205
|
-
|
206
|
-
|
209
|
+
def finish_response
|
210
|
+
response.finish
|
211
|
+
end
|
207
212
|
|
208
|
-
|
209
|
-
|
210
|
-
|
213
|
+
def logger
|
214
|
+
self.class.logger
|
215
|
+
end
|
211
216
|
|
212
|
-
|
217
|
+
class << self
|
218
|
+
attr_writer :logger
|
219
|
+
attr_writer :json_serializer
|
220
|
+
|
221
|
+
def logger
|
213
222
|
if defined? @logger
|
214
223
|
@logger
|
215
224
|
else
|
@@ -217,68 +226,60 @@ module Rack
|
|
217
226
|
end
|
218
227
|
end
|
219
228
|
|
220
|
-
def
|
221
|
-
@logger = logger
|
222
|
-
end
|
223
|
-
|
224
|
-
def self.json_serializer
|
229
|
+
def json_serializer
|
225
230
|
if defined? @json_serializer
|
226
231
|
@json_serializer
|
227
232
|
else
|
228
|
-
@json_serializer =
|
229
|
-
superclass.json_serializer
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
+
@json_serializer =
|
234
|
+
if superclass.respond_to?(:json_serializer)
|
235
|
+
superclass.json_serializer
|
236
|
+
else
|
237
|
+
JSON
|
238
|
+
end
|
233
239
|
end
|
234
240
|
end
|
241
|
+
end
|
235
242
|
|
236
|
-
|
237
|
-
|
243
|
+
# @private
|
244
|
+
class URL
|
245
|
+
HTTPS = "https".freeze
|
246
|
+
HTTP_PREFIX = "http://".freeze
|
247
|
+
HTTPS_PREFIX = "https://".freeze
|
248
|
+
ABSOLUTE_URL_REGEX = %r{\Ahttps?://}.freeze
|
249
|
+
RACK_URL_SCHEME = "rack.url_scheme".freeze
|
250
|
+
SERVER_NAME = "SERVER_NAME".freeze
|
251
|
+
SERVER_PORT = "SERVER_PORT".freeze
|
252
|
+
DEFAULT_HTTP_PORT = 80
|
253
|
+
DEFAULT_HTTPS_PORT = 443
|
254
|
+
|
255
|
+
attr_accessor :env, :url, :https, :host, :port
|
256
|
+
|
257
|
+
def initialize(env, url, options={})
|
258
|
+
@env = env
|
259
|
+
@url = url.to_s
|
260
|
+
@options = options || {}
|
261
|
+
@https = options.fetch(:https, env[RACK_URL_SCHEME] == HTTPS)
|
262
|
+
@host = options.fetch(:host, env[SERVER_NAME])
|
263
|
+
@port = Integer(options.fetch(:port, env[SERVER_PORT]))
|
238
264
|
end
|
239
265
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
SERVER_PORT = 'SERVER_PORT'.freeze
|
249
|
-
DEFAULT_HTTP_PORT = 80
|
250
|
-
DEFAULT_HTTPS_PORT = 443
|
251
|
-
|
252
|
-
attr_accessor :env, :url, :https, :host, :port
|
253
|
-
|
254
|
-
def initialize(env, url, options={})
|
255
|
-
@env = env
|
256
|
-
@url = url.to_s
|
257
|
-
@options = options || {}
|
258
|
-
@https = options.fetch(:https, env[RACK_URL_SCHEME] == HTTPS)
|
259
|
-
@host = options.fetch(:host, env[SERVER_NAME])
|
260
|
-
@port = Integer(options.fetch(:port, env[SERVER_PORT]))
|
261
|
-
end
|
262
|
-
|
263
|
-
def to_absolute
|
264
|
-
if url =~ ABSOLUTE_URL_REGEX
|
265
|
-
url
|
266
|
-
else
|
267
|
-
absolute_url = [prefix]
|
268
|
-
absolute_url << (port == default_port ? host : "#{host}:#{port}")
|
269
|
-
absolute_url << url
|
270
|
-
::File.join(*absolute_url)
|
271
|
-
end
|
272
|
-
end
|
273
|
-
|
274
|
-
def prefix
|
275
|
-
https ? HTTPS_PREFIX : HTTP_PREFIX
|
266
|
+
def to_absolute
|
267
|
+
if url =~ ABSOLUTE_URL_REGEX
|
268
|
+
url
|
269
|
+
else
|
270
|
+
absolute_url = [prefix]
|
271
|
+
absolute_url << (port == default_port ? host : "#{host}:#{port}")
|
272
|
+
absolute_url << url
|
273
|
+
::File.join(*absolute_url)
|
276
274
|
end
|
275
|
+
end
|
277
276
|
|
278
|
-
|
279
|
-
|
280
|
-
end
|
277
|
+
def prefix
|
278
|
+
https ? HTTPS_PREFIX : HTTP_PREFIX
|
281
279
|
end
|
282
280
|
|
281
|
+
def default_port
|
282
|
+
https ? DEFAULT_HTTPS_PORT : DEFAULT_HTTP_PORT
|
283
|
+
end
|
283
284
|
end
|
284
285
|
end
|
data/lib/rack/filters.rb
CHANGED
@@ -1,40 +1,39 @@
|
|
1
|
-
module Rack
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
module Rack::Filters
|
2
|
+
def before_filters
|
3
|
+
@before_filters ||=
|
4
|
+
if superclass.respond_to?(:before_filters)
|
5
5
|
superclass.before_filters.dup
|
6
6
|
else
|
7
7
|
[]
|
8
8
|
end
|
9
|
-
|
9
|
+
end
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
11
|
+
def before_filter(method)
|
12
|
+
unless before_filters.include?(method)
|
13
|
+
before_filters << method
|
15
14
|
end
|
15
|
+
end
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
def skip_before_filter(method)
|
18
|
+
before_filters.delete(method)
|
19
|
+
end
|
20
20
|
|
21
|
-
|
22
|
-
|
21
|
+
def after_filters
|
22
|
+
@after_filters ||=
|
23
|
+
if superclass.respond_to?(:after_filters)
|
23
24
|
superclass.after_filters.dup
|
24
25
|
else
|
25
26
|
[]
|
26
27
|
end
|
27
|
-
|
28
|
+
end
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
30
|
+
def after_filter(method)
|
31
|
+
unless after_filters.include?(method)
|
32
|
+
after_filters << method
|
33
33
|
end
|
34
|
+
end
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
end
|
36
|
+
def skip_after_filter(method)
|
37
|
+
after_filters.delete(method)
|
38
38
|
end
|
39
39
|
end
|
40
|
-
|
data/lib/rack_action.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require
|
1
|
+
require "rack/action"
|
data/rack-action.gemspec
CHANGED
@@ -1,18 +1,16 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
1
|
Gem::Specification.new do |gem|
|
4
2
|
gem.authors = ["Paul Barry"]
|
5
|
-
gem.email = ["
|
6
|
-
gem.description =
|
7
|
-
gem.summary =
|
3
|
+
gem.email = ["pauljbarry3@gmail.com"]
|
4
|
+
gem.description = "a small, simple framework for generating Rack responses"
|
5
|
+
gem.summary = "a small, simple framework for generating Rack responses"
|
8
6
|
gem.homepage = "http://github.com/pjb3/rack-action"
|
9
7
|
|
10
|
-
gem.files = `git ls-files`.split(
|
8
|
+
gem.files = `git ls-files`.split($ORS)
|
11
9
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
12
10
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
13
11
|
gem.name = "rack-action"
|
14
12
|
gem.require_paths = ["lib"]
|
15
|
-
gem.version = "0.
|
13
|
+
gem.version = "0.7.0"
|
16
14
|
|
17
15
|
gem.add_runtime_dependency "rack"
|
18
16
|
end
|
data/test/rack/action_test.rb
CHANGED
@@ -1,15 +1,13 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "rack_action"
|
2
|
+
require "rack_test"
|
3
3
|
|
4
4
|
class Rack::ActionTest < RackTest
|
5
|
-
|
6
5
|
def test_default_respond
|
7
6
|
app = Class.new(Rack::Action)
|
8
7
|
|
9
8
|
response = get app, "/"
|
10
9
|
assert_equal 200, response.status
|
11
|
-
assert_equal
|
12
|
-
assert_equal 'text/html', response["Content-Type"]
|
10
|
+
assert_equal "text/html", response["Content-Type"]
|
13
11
|
assert_equal [Rack::Action::DEFAULT_RESPONSE], response.body
|
14
12
|
end
|
15
13
|
|
@@ -23,24 +21,22 @@ class Rack::ActionTest < RackTest
|
|
23
21
|
response = get app, "/"
|
24
22
|
|
25
23
|
assert_equal 200, response.status
|
26
|
-
assert_equal
|
27
|
-
assert_equal
|
28
|
-
assert_equal ['bananas'], response.body
|
24
|
+
assert_equal "text/html", response["Content-Type"]
|
25
|
+
assert_equal ["bananas"], response.body
|
29
26
|
end
|
30
27
|
|
31
28
|
def test_json_respond
|
32
29
|
app = Class.new(Rack::Action) do
|
33
30
|
def respond
|
34
|
-
|
31
|
+
{ hello: "world" }
|
35
32
|
end
|
36
33
|
end
|
37
|
-
expected = %{
|
34
|
+
expected = %({"hello":"world"})
|
38
35
|
|
39
36
|
response = get app, "/"
|
40
37
|
|
41
38
|
assert_equal 200, response.status
|
42
|
-
assert_equal
|
43
|
-
assert_equal 'application/json', response["Content-Type"]
|
39
|
+
assert_equal "application/json", response["Content-Type"]
|
44
40
|
assert_equal [expected], response.body
|
45
41
|
end
|
46
42
|
|
@@ -50,31 +46,12 @@ class Rack::ActionTest < RackTest
|
|
50
46
|
json({:hello => "world"}, :status => 420)
|
51
47
|
end
|
52
48
|
end
|
53
|
-
expected = %{
|
49
|
+
expected = %({"hello":"world"})
|
54
50
|
|
55
51
|
response = get app, "/"
|
56
52
|
|
57
53
|
assert_equal 420, response.status
|
58
|
-
assert_equal
|
59
|
-
assert_equal 'application/json', response["Content-Type"]
|
60
|
-
assert_equal [expected], response.body
|
61
|
-
end
|
62
|
-
|
63
|
-
def test_pretty_json_respond
|
64
|
-
app = Class.new(Rack::Action) do
|
65
|
-
def respond
|
66
|
-
pretty_json :hello => "world"
|
67
|
-
end
|
68
|
-
end
|
69
|
-
expected = %{{
|
70
|
-
"hello": "world"
|
71
|
-
}}
|
72
|
-
|
73
|
-
response = get app, "/"
|
74
|
-
|
75
|
-
assert_equal 200, response.status
|
76
|
-
assert_equal expected.length.to_s, response["Content-Length"]
|
77
|
-
assert_equal 'application/json', response["Content-Type"]
|
54
|
+
assert_equal "application/json", response["Content-Type"]
|
78
55
|
assert_equal [expected], response.body
|
79
56
|
end
|
80
57
|
|
@@ -99,7 +76,7 @@ class Rack::ActionTest < RackTest
|
|
99
76
|
def test_before_filter_set_response
|
100
77
|
app = Class.new(Rack::Action) do
|
101
78
|
def respond
|
102
|
-
|
79
|
+
raise "respond should not be called if a before filter sets the response"
|
103
80
|
end
|
104
81
|
|
105
82
|
def set_response
|
@@ -117,7 +94,7 @@ class Rack::ActionTest < RackTest
|
|
117
94
|
def test_redirect
|
118
95
|
app = Class.new(Rack::Action) do
|
119
96
|
def respond
|
120
|
-
|
97
|
+
raise "respond should not be called if a before filter sets the response"
|
121
98
|
end
|
122
99
|
|
123
100
|
def login_required
|
@@ -135,7 +112,7 @@ class Rack::ActionTest < RackTest
|
|
135
112
|
def test_redirect_non_default_port
|
136
113
|
app = Class.new(Rack::Action) do
|
137
114
|
def respond
|
138
|
-
|
115
|
+
raise "respond should not be called if a before filter sets the response"
|
139
116
|
end
|
140
117
|
|
141
118
|
def login_required
|
@@ -153,7 +130,7 @@ class Rack::ActionTest < RackTest
|
|
153
130
|
def test_redirect_non_default_port_option
|
154
131
|
app = Class.new(Rack::Action) do
|
155
132
|
def respond
|
156
|
-
|
133
|
+
raise "respond should not be called if a before filter sets the response"
|
157
134
|
end
|
158
135
|
|
159
136
|
def login_required
|
@@ -171,7 +148,7 @@ class Rack::ActionTest < RackTest
|
|
171
148
|
def test_secure_redirect
|
172
149
|
app = Class.new(Rack::Action) do
|
173
150
|
def respond
|
174
|
-
|
151
|
+
raise "respond should not be called if a before filter sets the response"
|
175
152
|
end
|
176
153
|
|
177
154
|
def login_required
|
@@ -189,7 +166,7 @@ class Rack::ActionTest < RackTest
|
|
189
166
|
def test_redirect_absolute_url
|
190
167
|
app = Class.new(Rack::Action) do
|
191
168
|
def respond
|
192
|
-
|
169
|
+
raise "respond should not be called if a before filter sets the response"
|
193
170
|
end
|
194
171
|
|
195
172
|
def login_required
|
@@ -203,5 +180,4 @@ class Rack::ActionTest < RackTest
|
|
203
180
|
assert_equal 302, response.status
|
204
181
|
assert_equal "http://test.com/login", response["Location"]
|
205
182
|
end
|
206
|
-
|
207
183
|
end
|
data/test/rack_test.rb
CHANGED
@@ -1,18 +1,17 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require "test/unit"
|
2
|
+
require "stringio"
|
3
|
+
require "logger"
|
4
|
+
require "fileutils"
|
5
5
|
|
6
|
-
if ENV[
|
6
|
+
if ENV["RACK_ACTION_TEST_LOGGER"].to_s.downcase == "stdout"
|
7
7
|
Rack::Action.logger = Logger.new(STDOUT)
|
8
|
-
elsif ENV[
|
9
|
-
log_file = File.expand_path(ENV[
|
8
|
+
elsif ENV["RACK_ACTION_TEST_LOGGER"]
|
9
|
+
log_file = File.expand_path(ENV["RACK_ACTION_TEST_LOGGER"])
|
10
10
|
FileUtils.mkdir_p File.dirname(log_file)
|
11
11
|
Rack::Action.logger = Logger.new(log_file)
|
12
12
|
end
|
13
13
|
|
14
14
|
class RackTest < Test::Unit::TestCase
|
15
|
-
|
16
15
|
DEFAULT_HOST = "example.com".freeze
|
17
16
|
DEFAULT_PORT = 80
|
18
17
|
|
@@ -35,7 +34,9 @@ class RackTest < Test::Unit::TestCase
|
|
35
34
|
resp = app.call(DEFAULT_ENV.merge({
|
36
35
|
"REQUEST_METHOD" => method.to_s.upcase,
|
37
36
|
"PATH_INFO" => path
|
38
|
-
}.merge(env)
|
37
|
+
}.merge(env)
|
38
|
+
)
|
39
|
+
)
|
39
40
|
resp.is_a?(Rack::Response) ? resp : Rack::Response.new(resp[2], resp[0], resp[1])
|
40
41
|
end
|
41
42
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-action
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paul Barry
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-09-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -26,13 +26,13 @@ dependencies:
|
|
26
26
|
version: '0'
|
27
27
|
description: a small, simple framework for generating Rack responses
|
28
28
|
email:
|
29
|
-
-
|
29
|
+
- pauljbarry3@gmail.com
|
30
30
|
executables: []
|
31
31
|
extensions: []
|
32
32
|
extra_rdoc_files: []
|
33
33
|
files:
|
34
34
|
- ".gitignore"
|
35
|
-
- ".
|
35
|
+
- ".ruby-version"
|
36
36
|
- ".yardopts"
|
37
37
|
- Gemfile
|
38
38
|
- LICENSE
|
@@ -64,8 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
64
64
|
- !ruby/object:Gem::Version
|
65
65
|
version: '0'
|
66
66
|
requirements: []
|
67
|
-
|
68
|
-
rubygems_version: 2.4.5
|
67
|
+
rubygems_version: 3.0.3
|
69
68
|
signing_key:
|
70
69
|
specification_version: 4
|
71
70
|
summary: a small, simple framework for generating Rack responses
|
data/.rvmrc
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
rvm 1.9.3@rack-action --create
|