actionpack 4.1.0.beta2 → 4.1.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +241 -10
- data/MIT-LICENSE +1 -1
- data/lib/abstract_controller/rendering.rb +4 -3
- data/lib/action_controller/log_subscriber.rb +9 -0
- data/lib/action_controller/metal/head.rb +1 -1
- data/lib/action_controller/metal/live.rb +3 -1
- data/lib/action_controller/metal/mime_responds.rb +66 -27
- data/lib/action_controller/metal/params_wrapper.rb +11 -4
- data/lib/action_controller/metal/rack_delegation.rb +2 -2
- data/lib/action_controller/metal/renderers.rb +1 -1
- data/lib/action_controller/metal/rendering.rb +38 -8
- data/lib/action_controller/metal/strong_parameters.rb +26 -14
- data/lib/action_controller/railtie.rb +1 -0
- data/lib/action_controller/test_case.rb +3 -0
- data/lib/action_dispatch.rb +5 -7
- data/lib/action_dispatch/http/filter_redirect.rb +5 -4
- data/lib/action_dispatch/http/mime_negotiation.rb +5 -3
- data/lib/action_dispatch/http/mime_type.rb +1 -1
- data/lib/action_dispatch/http/response.rb +14 -2
- data/lib/action_dispatch/journey/formatter.rb +2 -2
- data/lib/action_dispatch/journey/router.rb +1 -7
- data/lib/action_dispatch/journey/visitors.rb +24 -4
- data/lib/action_dispatch/middleware/cookies.rb +85 -20
- data/lib/action_dispatch/middleware/flash.rb +20 -7
- data/lib/action_dispatch/middleware/reloader.rb +11 -2
- data/lib/action_dispatch/middleware/remote_ip.rb +2 -2
- data/lib/action_dispatch/middleware/static.rb +3 -3
- data/lib/action_dispatch/railtie.rb +2 -0
- data/lib/action_dispatch/request/utils.rb +15 -4
- data/lib/action_dispatch/routing/inspector.rb +4 -4
- data/lib/action_dispatch/routing/mapper.rb +27 -9
- data/lib/action_dispatch/routing/redirection.rb +18 -8
- data/lib/action_dispatch/routing/route_set.rb +24 -30
- data/lib/action_dispatch/testing/assertions/routing.rb +1 -1
- data/lib/action_dispatch/testing/integration.rb +2 -2
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/version.rb +1 -1
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 48441494a6b94b3b37656c33c887284d571c4950
|
4
|
+
data.tar.gz: 159b15d6c50c7eda3830b4f28700c260d3e9f2aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fe168a619210d069350c142ccdf35cbf08e0cc1ef6762be5c7616182f26ec334eb3cf4ce948cfb2dc3e3245957886514e2e04243860a609ce5254c8de68976b5
|
7
|
+
data.tar.gz: c51d0e2a179ea132ec8ad8814917cdaefa646b3d0d93f6c68ad7f0d06a18fdf82e80ccdf118b0f13d486f47c850c41f1d605adb13e175038f4bda73de961a1a9
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,221 @@
|
|
1
|
+
* Introduce `render :html` as an option to render HTML content with a content
|
2
|
+
type of `text/html`. This rendering option calls `ERB::Util.html_escape`
|
3
|
+
internally to escape unsafe HTML string, so you will have to mark your
|
4
|
+
string as html safe if you have any HTML tag in it.
|
5
|
+
|
6
|
+
Please see #12374 for more detail.
|
7
|
+
|
8
|
+
*Prem Sichanugrist*
|
9
|
+
|
10
|
+
* Introduce `render :plain` as an option to render content with a content type
|
11
|
+
of `text/plain`. This is the preferred option if you are planning to render
|
12
|
+
a plain text content.
|
13
|
+
|
14
|
+
Please see #12374 for more detail.
|
15
|
+
|
16
|
+
*Prem Sichanugrist*
|
17
|
+
|
18
|
+
* Introduce `render :body` as an option for sending a raw content back to
|
19
|
+
browser. Note that this rendering option will unset the default content type
|
20
|
+
and does not include "Content-Type" header back in the response.
|
21
|
+
|
22
|
+
You should only use this option if you are expecting the "Content-Type"
|
23
|
+
header to not be set. More information on "Content-Type" header can be found
|
24
|
+
on RFC 2616, section 7.2.1.
|
25
|
+
|
26
|
+
Please see #12374 for more detail.
|
27
|
+
|
28
|
+
*Prem Sichanugrist*
|
29
|
+
|
30
|
+
* Set stream status to 500 (or 400 on BadRequest) when an error is thrown
|
31
|
+
before commiting.
|
32
|
+
|
33
|
+
Fixes #12552.
|
34
|
+
|
35
|
+
*Kevin Casey*
|
36
|
+
|
37
|
+
* Add new config option `config.action_dispatch.cookies_serializer` for
|
38
|
+
specifying a serializer for the signed and encrypted cookie jars.
|
39
|
+
|
40
|
+
The possible values are:
|
41
|
+
|
42
|
+
* `:json` - serialize cookie values with `JSON`
|
43
|
+
* `:marshal` - serialize cookie values with `Marshal`
|
44
|
+
* `:hybrid` - transparently migrate existing `Marshal` cookie values to `JSON`
|
45
|
+
|
46
|
+
For new apps `:json` option is added by default and `:marshal` is used
|
47
|
+
when no option is specified to maintain backwards compatibility.
|
48
|
+
|
49
|
+
*Łukasz Sarnacki*, *Matt Aimonetti*, *Guillermo Iguaran*, *Godfrey Chan*, *Rafael Mendonça França*
|
50
|
+
|
51
|
+
* `FlashHash` now behaves like a `HashWithIndifferentAccess`.
|
52
|
+
|
53
|
+
*Guillermo Iguaran*
|
54
|
+
|
55
|
+
* Set the `:shallow_path` scope option as each scope is generated rather than
|
56
|
+
waiting until the `shallow` option is set. Also make the behavior of the
|
57
|
+
`:shallow` resource option consistent with the behavior of the `shallow` method.
|
58
|
+
|
59
|
+
Fixes #12498.
|
60
|
+
|
61
|
+
*Andrew White*, *Aleksi Aalto*
|
62
|
+
|
63
|
+
* Properly require `action_view` in `AbstractController::Rendering` to prevent
|
64
|
+
uninitialized constant error for `ENCODING_FLAG`.
|
65
|
+
|
66
|
+
*Philipe Fatio*
|
67
|
+
|
68
|
+
* Do not discard query parameters that form a hash with the same root key as
|
69
|
+
the `wrapper_key` for a request using `wrap_parameters`.
|
70
|
+
|
71
|
+
*Josh Jordan*
|
72
|
+
|
73
|
+
* Ensure that `request.filtered_parameters` is reset between calls to `process`
|
74
|
+
in `ActionController::TestCase`.
|
75
|
+
|
76
|
+
Fixes #13803.
|
77
|
+
|
78
|
+
*Andrew White*
|
79
|
+
|
80
|
+
* Fix `rake routes` error when `Rails::Engine` with empty routes is mounted.
|
81
|
+
|
82
|
+
Fixes #13810.
|
83
|
+
|
84
|
+
*Maurizio De Santis*
|
85
|
+
|
86
|
+
* Log which keys were affected by deep munge.
|
87
|
+
|
88
|
+
Deep munge solves CVE-2013-0155 security vulnerability, but its
|
89
|
+
behaviour is definately confusing, so now at least information
|
90
|
+
about for which keys values were set to nil is visible in logs.
|
91
|
+
|
92
|
+
*Łukasz Sarnacki*
|
93
|
+
|
94
|
+
* Automatically convert dashes to underscores for shorthand routes, e.g:
|
95
|
+
|
96
|
+
get '/our-work/latest'
|
97
|
+
|
98
|
+
When running `rake routes` you will get the following output:
|
99
|
+
|
100
|
+
Prefix Verb URI Pattern Controller#Action
|
101
|
+
our_work_latest GET /our-work/latest(.:format) our_work#latest
|
102
|
+
|
103
|
+
*Mikko Johansson*
|
104
|
+
|
105
|
+
* Automatically convert dashes to underscores for url helpers, e.g:
|
106
|
+
|
107
|
+
get '/contact-us' => 'pages#contact'
|
108
|
+
get '/about-us' => 'pages#about_us'
|
109
|
+
|
110
|
+
When running `rake routes` you will get the following output:
|
111
|
+
|
112
|
+
Prefix Verb URI Pattern Controller#Action
|
113
|
+
contact_us GET /contact-us(.:format) pages#contact
|
114
|
+
about_us GET /about-us(.:format) pages#about_us
|
115
|
+
|
116
|
+
*Amr Tamimi*
|
117
|
+
|
118
|
+
* Fix stream closing when sending file with `ActionController::Live` included.
|
119
|
+
|
120
|
+
Fixes #12381
|
121
|
+
|
122
|
+
*Alessandro Diaferia*
|
123
|
+
|
124
|
+
* Allow an absolute controller path inside a module scope. Fixes #12777.
|
125
|
+
|
126
|
+
Example:
|
127
|
+
|
128
|
+
namespace :foo do
|
129
|
+
# will route to BarController without the namespace.
|
130
|
+
get '/special', to: '/bar#index'
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
* Unique the segment keys array for non-optimized url helpers
|
135
|
+
|
136
|
+
In Rails 3.2 you only needed pass an argument for dynamic segment once so
|
137
|
+
unique the segment keys array to match the number of args. Since the number
|
138
|
+
of args is less than required parts the non-optimized code path is selected.
|
139
|
+
This means to benefit from optimized url generation the arg needs to be
|
140
|
+
specified as many times as it appears in the path.
|
141
|
+
|
142
|
+
Fixes #12808.
|
143
|
+
|
144
|
+
*Andrew White*
|
145
|
+
|
146
|
+
* Show full route constraints in error message.
|
147
|
+
|
148
|
+
When an optimized helper fails to generate, show the full route constraints
|
149
|
+
in the error message. Previously it would only show the contraints that were
|
150
|
+
required as part of the path.
|
151
|
+
|
152
|
+
Fixes #13592.
|
153
|
+
|
154
|
+
*Andrew White*
|
155
|
+
|
156
|
+
* Use a custom route visitor for optimized url generation. Fixes #13349.
|
157
|
+
|
158
|
+
*Andrew White*
|
159
|
+
|
160
|
+
* Allow engine root relative redirects using an empty string.
|
161
|
+
|
162
|
+
Example:
|
163
|
+
|
164
|
+
# application routes.rb
|
165
|
+
mount BlogEngine => '/blog'
|
166
|
+
|
167
|
+
# engine routes.rb
|
168
|
+
get '/welcome' => redirect('')
|
169
|
+
|
170
|
+
This now redirects to the path `/blog`, whereas before it would redirect
|
171
|
+
to the application root path. In the case of a path redirect or a custom
|
172
|
+
redirect if the path returned contains a host then the path is treated as
|
173
|
+
absolute. Similarly for option redirects, if the options hash returned
|
174
|
+
contains a `:host` or `:domain` key then the path is treated as absolute.
|
175
|
+
|
176
|
+
Fixes #7977.
|
177
|
+
|
178
|
+
*Andrew White*
|
179
|
+
|
180
|
+
* Fix `Encoding::CompatibilityError` when public path is UTF-8
|
181
|
+
|
182
|
+
In #5337 we forced the path encoding to ASCII-8BIT to prevent static file handling
|
183
|
+
from blowing up before an application has had chance to deal with possibly invalid
|
184
|
+
urls. However this has a negative side effect of making it an incompatible encoding
|
185
|
+
if the application's public path has UTF-8 characters in it.
|
186
|
+
|
187
|
+
To work around the problem we check to see if the path has a valid encoding once
|
188
|
+
it has been unescaped. If it is not valid then we can return early since it will
|
189
|
+
not match any file anyway.
|
190
|
+
|
191
|
+
Fixes #13518.
|
192
|
+
|
193
|
+
*Andrew White*
|
194
|
+
|
195
|
+
* `ActionController::Parameters#permit!` permits hashes in array values.
|
196
|
+
|
197
|
+
*Xavier Noria*
|
198
|
+
|
199
|
+
* Converts hashes in arrays of unfiltered params to unpermitted params.
|
200
|
+
|
201
|
+
Fixes #13382.
|
202
|
+
|
203
|
+
*Xavier Noria*
|
204
|
+
|
205
|
+
* New config option to opt out of params "deep munging" that was used to
|
206
|
+
address security vulnerability CVE-2013-0155. In your app config:
|
207
|
+
|
208
|
+
config.action_dispatch.perform_deep_munge = false
|
209
|
+
|
210
|
+
Take care to understand the security risk involved before disabling this.
|
211
|
+
[Read more.](https://groups.google.com/forum/#!topic/rubyonrails-security/t1WFuuQyavI)
|
212
|
+
|
213
|
+
*Bernard Potocki*
|
214
|
+
|
215
|
+
* `rake routes` shows routes defined under assets prefix.
|
216
|
+
|
217
|
+
*Ryunosuke SATO*
|
218
|
+
|
1
219
|
* Extend cross-site request forgery (CSRF) protection to GET requests with
|
2
220
|
JavaScript responses, protecting apps from cross-origin `<script>` tags.
|
3
221
|
|
@@ -60,16 +278,35 @@
|
|
60
278
|
format.html.none { render "trash" }
|
61
279
|
end
|
62
280
|
|
281
|
+
Variants also support common `any`/`all` block that formats have.
|
282
|
+
|
283
|
+
It works for both inline:
|
284
|
+
|
285
|
+
respond_to do |format|
|
286
|
+
format.html.any { render text: "any" }
|
287
|
+
format.html.phone { render text: "phone" }
|
288
|
+
end
|
289
|
+
|
290
|
+
and block syntax:
|
291
|
+
|
292
|
+
respond_to do |format|
|
293
|
+
format.html do |variant|
|
294
|
+
variant.any(:tablet, :phablet){ render text: "any" }
|
295
|
+
variant.phone { render text: "phone" }
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
63
299
|
*Łukasz Strzałkowski*
|
64
300
|
|
65
|
-
* Fix
|
301
|
+
* Fix render of localized templates without an explicit format using wrong
|
302
|
+
content header and not passing correct formats to template due to the
|
303
|
+
introduction of the `NullType` for mimes.
|
66
304
|
|
67
|
-
|
68
|
-
the response now has the default and correct `content-type`.
|
305
|
+
Templates like `hello.it.erb` were subject to this issue.
|
69
306
|
|
70
307
|
Fixes #13064.
|
71
308
|
|
72
|
-
*Angelo Capilleri*
|
309
|
+
*Angelo Capilleri*, *Carlos Antonio da Silva*
|
73
310
|
|
74
311
|
* Try to escape each part of a url correctly when using a redirect route.
|
75
312
|
|
@@ -311,10 +548,4 @@
|
|
311
548
|
|
312
549
|
*Piotr Sarnacki*, *Łukasz Strzałkowski*
|
313
550
|
|
314
|
-
* Fix removing trailing slash for mounted apps.
|
315
|
-
|
316
|
-
Fixes #3215.
|
317
|
-
|
318
|
-
*Piotr Sarnacki*
|
319
|
-
|
320
551
|
Please check [4-0-stable](https://github.com/rails/rails/blob/4-0-stable/actionpack/CHANGELOG.md) for previous changes.
|
data/MIT-LICENSE
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'active_support/concern'
|
2
2
|
require 'active_support/core_ext/class/attribute'
|
3
|
+
require 'action_view'
|
3
4
|
require 'action_view/view_paths'
|
4
5
|
require 'set'
|
5
6
|
|
@@ -22,7 +23,7 @@ module AbstractController
|
|
22
23
|
def render(*args, &block)
|
23
24
|
options = _normalize_render(*args, &block)
|
24
25
|
self.response_body = render_to_body(options)
|
25
|
-
_process_format(rendered_format)
|
26
|
+
_process_format(rendered_format, options) if rendered_format
|
26
27
|
self.response_body
|
27
28
|
end
|
28
29
|
|
@@ -47,7 +48,7 @@ module AbstractController
|
|
47
48
|
def render_to_body(options = {})
|
48
49
|
end
|
49
50
|
|
50
|
-
#
|
51
|
+
# Returns Content-Type of rendered content
|
51
52
|
# :api: public
|
52
53
|
def rendered_format
|
53
54
|
Mime::TEXT
|
@@ -97,7 +98,7 @@ module AbstractController
|
|
97
98
|
|
98
99
|
# Process the rendered format.
|
99
100
|
# :api: private
|
100
|
-
def _process_format(format)
|
101
|
+
def _process_format(format, options = {})
|
101
102
|
end
|
102
103
|
|
103
104
|
# Normalize args and options.
|
@@ -53,6 +53,15 @@ module ActionController
|
|
53
53
|
debug("Unpermitted parameters: #{unpermitted_keys.join(", ")}")
|
54
54
|
end
|
55
55
|
|
56
|
+
def deep_munge(event)
|
57
|
+
message = "Value for params[:#{event.payload[:keys].join('][:')}] was set"\
|
58
|
+
"to nil, because it was one of [], [null] or [null, null, ...]."\
|
59
|
+
"Go to http://guides.rubyonrails.org/security.html#unsafe-query-generation"\
|
60
|
+
"for more information."\
|
61
|
+
|
62
|
+
debug(message)
|
63
|
+
end
|
64
|
+
|
56
65
|
%w(write_fragment read_fragment exist_fragment?
|
57
66
|
expire_fragment expire_page write_page).each do |method|
|
58
67
|
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module ActionController
|
2
2
|
module Head
|
3
|
-
#
|
3
|
+
# Returns a response that has no content (merely headers). The options
|
4
4
|
# argument is interpreted to be a hash of header names and values.
|
5
5
|
# This allows you to easily return a response that consists only of
|
6
6
|
# significant headers:
|
@@ -205,6 +205,8 @@ module ActionController
|
|
205
205
|
begin
|
206
206
|
super(name)
|
207
207
|
rescue => e
|
208
|
+
@_response.status = 500 unless @_response.committed?
|
209
|
+
@_response.status = 400 if e.class == ActionController::BadRequest
|
208
210
|
begin
|
209
211
|
@_response.stream.write(ActionView::Base.streaming_completion_on_exception) if request.format == :html
|
210
212
|
@_response.stream.call_on_error
|
@@ -234,7 +236,7 @@ module ActionController
|
|
234
236
|
|
235
237
|
def response_body=(body)
|
236
238
|
super
|
237
|
-
response.
|
239
|
+
response.close if response
|
238
240
|
end
|
239
241
|
|
240
242
|
def set_response!(request)
|
@@ -217,6 +217,36 @@ module ActionController #:nodoc:
|
|
217
217
|
# format.html.phone { redirect_to progress_path }
|
218
218
|
# format.html.none { render "trash" }
|
219
219
|
# end
|
220
|
+
#
|
221
|
+
# Variants also support common `any`/`all` block that formats have.
|
222
|
+
#
|
223
|
+
# It works for both inline:
|
224
|
+
#
|
225
|
+
# respond_to do |format|
|
226
|
+
# format.html.any { render text: "any" }
|
227
|
+
# format.html.phone { render text: "phone" }
|
228
|
+
# end
|
229
|
+
#
|
230
|
+
# and block syntax:
|
231
|
+
#
|
232
|
+
# respond_to do |format|
|
233
|
+
# format.html do |variant|
|
234
|
+
# variant.any(:tablet, :phablet){ render text: "any" }
|
235
|
+
# variant.phone { render text: "phone" }
|
236
|
+
# end
|
237
|
+
# end
|
238
|
+
#
|
239
|
+
# You can also set an array of variants:
|
240
|
+
#
|
241
|
+
# request.variant = [:tablet, :phone]
|
242
|
+
#
|
243
|
+
# which will work similarly to formats and MIME types negotiation. If there will be no
|
244
|
+
# :tablet variant declared, :phone variant will be picked:
|
245
|
+
#
|
246
|
+
# respond_to do |format|
|
247
|
+
# format.html.none
|
248
|
+
# format.html.phone # this gets rendered
|
249
|
+
# end
|
220
250
|
#
|
221
251
|
# Be sure to check the documentation of +respond_with+ and
|
222
252
|
# <tt>ActionController::MimeResponds.respond_to</tt> for more examples.
|
@@ -224,7 +254,7 @@ module ActionController #:nodoc:
|
|
224
254
|
raise ArgumentError, "respond_to takes either types or a block, never both" if mimes.any? && block_given?
|
225
255
|
|
226
256
|
if collector = retrieve_collector_from_mimes(mimes, &block)
|
227
|
-
response = collector.response
|
257
|
+
response = collector.response
|
228
258
|
response ? response.call : render({})
|
229
259
|
end
|
230
260
|
end
|
@@ -366,7 +396,7 @@ module ActionController #:nodoc:
|
|
366
396
|
if collector = retrieve_collector_from_mimes(&block)
|
367
397
|
options = resources.size == 1 ? {} : resources.extract_options!
|
368
398
|
options = options.clone
|
369
|
-
options[:default_response] = collector.response
|
399
|
+
options[:default_response] = collector.response
|
370
400
|
(options.delete(:responder) || self.class.responder).call(self, resources, options)
|
371
401
|
end
|
372
402
|
end
|
@@ -399,7 +429,7 @@ module ActionController #:nodoc:
|
|
399
429
|
# is available.
|
400
430
|
def retrieve_collector_from_mimes(mimes=nil, &block) #:nodoc:
|
401
431
|
mimes ||= collect_mimes_from_class_level
|
402
|
-
collector = Collector.new(mimes)
|
432
|
+
collector = Collector.new(mimes, request.variant)
|
403
433
|
block.call(collector) if block_given?
|
404
434
|
format = collector.negotiate_format(request)
|
405
435
|
|
@@ -437,8 +467,9 @@ module ActionController #:nodoc:
|
|
437
467
|
include AbstractController::Collector
|
438
468
|
attr_accessor :format
|
439
469
|
|
440
|
-
def initialize(mimes)
|
470
|
+
def initialize(mimes, variant = nil)
|
441
471
|
@responses = {}
|
472
|
+
@variant = variant
|
442
473
|
|
443
474
|
mimes.each { |mime| @responses["Mime::#{mime.upcase}".constantize] = nil }
|
444
475
|
end
|
@@ -457,18 +488,20 @@ module ActionController #:nodoc:
|
|
457
488
|
@responses[mime_type] ||= if block_given?
|
458
489
|
block
|
459
490
|
else
|
460
|
-
VariantCollector.new
|
491
|
+
VariantCollector.new(@variant)
|
461
492
|
end
|
462
493
|
end
|
463
494
|
|
464
|
-
def response
|
495
|
+
def response
|
465
496
|
response = @responses.fetch(format, @responses[Mime::ALL])
|
466
|
-
if response.is_a?(VariantCollector)
|
467
|
-
response.variant
|
468
|
-
elsif response.nil? || response.arity == 0
|
497
|
+
if response.is_a?(VariantCollector) # `format.html.phone` - variant inline syntax
|
498
|
+
response.variant
|
499
|
+
elsif response.nil? || response.arity == 0 # `format.html` - just a format, call its block
|
469
500
|
response
|
470
|
-
else
|
471
|
-
|
501
|
+
else # `format.html{ |variant| variant.phone }` - variant block syntax
|
502
|
+
variant_collector = VariantCollector.new(@variant)
|
503
|
+
response.call(variant_collector) # call format block with variants collector
|
504
|
+
variant_collector.variant
|
472
505
|
end
|
473
506
|
end
|
474
507
|
|
@@ -476,30 +509,36 @@ module ActionController #:nodoc:
|
|
476
509
|
@format = request.negotiate_mime(@responses.keys)
|
477
510
|
end
|
478
511
|
|
479
|
-
#Used for inline syntax
|
480
512
|
class VariantCollector #:nodoc:
|
481
|
-
def initialize
|
513
|
+
def initialize(variant = nil)
|
514
|
+
@variant = variant
|
482
515
|
@variants = {}
|
483
516
|
end
|
484
517
|
|
485
|
-
def
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
518
|
+
def any(*args, &block)
|
519
|
+
if block_given?
|
520
|
+
if args.any? && args.none?{ |a| a == @variant }
|
521
|
+
args.each{ |v| @variants[v] = block }
|
522
|
+
else
|
523
|
+
@variants[:any] = block
|
524
|
+
end
|
525
|
+
end
|
491
526
|
end
|
492
|
-
|
527
|
+
alias :all :any
|
493
528
|
|
494
|
-
|
495
|
-
|
496
|
-
def initialize(variant)
|
497
|
-
@variant = variant
|
529
|
+
def method_missing(name, *args, &block)
|
530
|
+
@variants[name] = block if block_given?
|
498
531
|
end
|
499
532
|
|
500
|
-
def
|
501
|
-
if
|
502
|
-
|
533
|
+
def variant
|
534
|
+
if @variant.nil?
|
535
|
+
@variants[:none] || @variants[:any]
|
536
|
+
elsif (@variants.keys & @variant).any?
|
537
|
+
@variant.each do |v|
|
538
|
+
return @variants[v] if @variants.key?(v)
|
539
|
+
end
|
540
|
+
else
|
541
|
+
@variants[:any]
|
503
542
|
end
|
504
543
|
end
|
505
544
|
end
|