rails-rfc6570 2.0.0 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +50 -0
- data/README.md +4 -4
- data/lib/rails/rfc6570.rb +45 -208
- data/lib/rails/rfc6570/formatter.rb +52 -0
- data/lib/rails/rfc6570/patches.rb +2 -0
- data/lib/rails/rfc6570/version.rb +3 -1
- data/lib/rails/rfc6570/visitor.rb +119 -0
- data/rails-rfc6570.gemspec +13 -12
- data/spec/dummy/log/test.log +2685 -658
- data/spec/rails/rfc6570/visitor_spec.rb +133 -0
- data/spec/{rfc6570_spec.rb → rails/rfc6570_spec.rb} +51 -21
- data/spec/spec_helper.rb +13 -7
- metadata +17 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8526615ae06cd6c8ca8cde71ea61249827646e1fabf6b655c05706062be3e4d2
|
4
|
+
data.tar.gz: 37cfb563a826b507523997b6aadd02580a844e573211bfc7f80b3caa42d90c66
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 74bf6d20d7e6aa3f8cf1b366a70b1397d1e42cdf28fc4e12b0f33fbb37078818b6a4dc7f36a581c5dab45f43242345d541d62611aba2190d942b1233d2f62730
|
7
|
+
data.tar.gz: 4f4a6eeb5297a1771c865e070fd3c7728fa6b41ac44251ed2d8e002985e60aee4734c49f4f32a6b93c43b5bc239a5dd3e09d30f36adcf74e160730ffe0add461
|
data/CHANGELOG.md
CHANGED
@@ -1,27 +1,77 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
This project adheres to [Semantic Versioning](http://semver.org/) and [Keep a Changelog](http://keepachangelog.com/).
|
5
|
+
|
6
|
+
|
7
|
+
## Unreleased
|
8
|
+
---
|
9
|
+
|
10
|
+
### New
|
11
|
+
|
12
|
+
### Changes
|
13
|
+
|
14
|
+
### Fixes
|
15
|
+
|
16
|
+
### Breaks
|
17
|
+
|
18
|
+
|
19
|
+
## 2.5.0 - (2020-12-13)
|
20
|
+
---
|
21
|
+
|
22
|
+
### New
|
23
|
+
* Add support for Rails 6.1
|
24
|
+
|
25
|
+
|
26
|
+
## 2.4.0
|
27
|
+
---
|
28
|
+
|
29
|
+
* Add support for Rails 6.0
|
30
|
+
|
31
|
+
## 2.3.0
|
32
|
+
---
|
33
|
+
|
34
|
+
* Newly written visitor and formatter to improve performance (#3)
|
35
|
+
* Nested groups are expanded into a list of groups
|
36
|
+
|
37
|
+
## 2.2.0
|
38
|
+
---
|
39
|
+
|
40
|
+
* Add support to Rails 5.2 to gemspec
|
41
|
+
|
42
|
+
## 2.1.0
|
43
|
+
---
|
44
|
+
|
45
|
+
* Add emulation for Rails' routing behavior with original script name
|
46
|
+
|
3
47
|
## 2.0.0
|
48
|
+
---
|
4
49
|
|
5
50
|
* Add support for Rails 5.1
|
6
51
|
* Drop support for Rails < 4.2
|
7
52
|
|
8
53
|
## 1.1.1
|
54
|
+
---
|
9
55
|
|
10
56
|
* Fix full URL generation to not use `root_url` helper to avoid depending on that and to improve compatibility with e.g. rails engines.
|
11
57
|
|
12
58
|
## 1.1.0
|
59
|
+
---
|
13
60
|
|
14
61
|
* Added support for Rails 5.0
|
15
62
|
|
16
63
|
## 1.0.0
|
64
|
+
---
|
17
65
|
|
18
66
|
* No changes just bumping version to a production release
|
19
67
|
|
20
68
|
## 0.3.0
|
69
|
+
---
|
21
70
|
|
22
71
|
* Added Rails 4.2 support
|
23
72
|
|
24
73
|
## 0.2.0
|
74
|
+
---
|
25
75
|
|
26
76
|
* Added `_path_rfc6570` and `_url_rfc6570` helpers (#2)
|
27
77
|
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# Rails::RFC6570
|
2
2
|
|
3
|
-
[![Build Status](https://
|
3
|
+
[![Build Status](https://github.com/jgraichen/rails-rfc6570/workflows/Build/badge.svg?event=push)](https://github.com/jgraichen/rails-rfc6570/actions?query=workflow%3ABuild)
|
4
4
|
|
5
|
-
Pragmatic access to your Rails
|
5
|
+
Pragmatic access to your Rails routes as RFC6570 URI templates. Tested with Rails 5.0, 5.1, 5.2, 6.0 and Ruby 2.5, 2.6, 2.7.
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
@@ -32,7 +32,7 @@ class ApplicationController < ActionController::API
|
|
32
32
|
end
|
33
33
|
```
|
34
34
|
|
35
|
-
**Pro Tip**: Append `_url` to the route names: `rfc6570_routes.
|
35
|
+
**Pro Tip**: Append `_url` to the route names: `rfc6570_routes.transform_keys {|k| "#{k}_url" }`.
|
36
36
|
|
37
37
|
By default the `format` placeholder is ignored and the HTTP host will be included in the URI template.
|
38
38
|
|
@@ -93,7 +93,7 @@ class UserDecorator < Draper::Decorator
|
|
93
93
|
end
|
94
94
|
```
|
95
95
|
|
96
|
-
This gem does not support every construct possible with route matchers especially nested groups cannot be expressed in URI templates. It also makes some assumptions when converting splat matchers like swallowing a multiple slashes.
|
96
|
+
This gem does not support every construct possible with route matchers especially nested groups cannot be expressed in URI templates. They are expanded into separate groups. It also makes some assumptions when converting splat matchers like swallowing a multiple slashes. An error is raised when routes with OR-clauses are tried to be converted.
|
97
97
|
|
98
98
|
You can also combine **Rails::RFC6570** with [rack-link_headers](https://github.com/jgraichen/rack-link_headers) and provide hypermedia linking everywhere!
|
99
99
|
|
data/lib/rails/rfc6570.rb
CHANGED
@@ -1,185 +1,30 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
module ActionDispatch
|
4
|
-
module Journey
|
5
|
-
module Visitors
|
6
|
-
class RFC6570 < Visitor
|
7
|
-
DISPATCH_CACHE = {}
|
8
|
-
|
9
|
-
def initialize(opts = {})
|
10
|
-
super()
|
11
|
-
|
12
|
-
@opts = opts
|
13
|
-
@stack = []
|
14
|
-
@group_depth = 0
|
15
|
-
end
|
16
|
-
|
17
|
-
def ignore
|
18
|
-
@opts.fetch(:ignore) { %w(format) }
|
19
|
-
end
|
20
|
-
|
21
|
-
def route
|
22
|
-
@route ||= @opts[:route]
|
23
|
-
end
|
24
|
-
|
25
|
-
def accept(node)
|
26
|
-
str = visit(node)
|
27
|
-
|
28
|
-
if @opts.fetch(:params, true) && route
|
29
|
-
controller = route.defaults[:controller].to_s
|
30
|
-
action = route.defaults[:action].to_s
|
31
|
-
|
32
|
-
if controller.present? && action.present?
|
33
|
-
params = Rails::RFC6570.params_for(controller, action)
|
34
|
-
str += '{?' + params.join(',') + '}' if params && params.any?
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
str
|
39
|
-
end
|
40
|
-
|
41
|
-
def visit(node)
|
42
|
-
@stack.unshift node.type
|
43
|
-
send DISPATCH_CACHE.fetch(node.type), node
|
44
|
-
ensure
|
45
|
-
@stack.shift
|
46
|
-
end
|
47
|
-
|
48
|
-
def symbol_name(node)
|
49
|
-
name = node.to_s.tr '*:', ''
|
50
|
-
|
51
|
-
if ignore.include?(name)
|
52
|
-
nil
|
53
|
-
else
|
54
|
-
name
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def placeholder(node, prefix = nil, suffix = nil, pretext = nil)
|
59
|
-
name = symbol_name node
|
60
|
-
if name
|
61
|
-
"#{pretext}{#{prefix}#{name}#{suffix}}"
|
62
|
-
else
|
63
|
-
''
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def binary(node)
|
68
|
-
case [node.left.type, node.right.type]
|
69
|
-
when [:DOT, :SYMBOL]
|
70
|
-
if @stack[0..1] == [:CAT, :GROUP]
|
71
|
-
placeholder node.right, '.'
|
72
|
-
else
|
73
|
-
placeholder(node.right, nil, nil, '.')
|
74
|
-
end
|
75
|
-
when [:SLASH, :SYMBOL]
|
76
|
-
if @stack[0..1] == [:CAT, :GROUP]
|
77
|
-
placeholder(node.right, '/')
|
78
|
-
else
|
79
|
-
placeholder(node.right, nil, nil, '/')
|
80
|
-
end
|
81
|
-
when [:SLASH, :STAR]
|
82
|
-
placeholder node.right, '/', '*'
|
83
|
-
when [:SLASH, :CAT]
|
84
|
-
if node.right.left.type == :STAR
|
85
|
-
placeholder(node.right.left, '/', '*') + visit(node.right.right)
|
86
|
-
else
|
87
|
-
[visit(node.left), visit(node.right)].join
|
88
|
-
end
|
89
|
-
when [:CAT, :STAR]
|
90
|
-
visit(node.left).to_s.gsub(/\/+$/, '') + placeholder(node.right, '/', '*')
|
91
|
-
else
|
92
|
-
[visit(node.left), visit(node.right)].join
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def terminal(node)
|
97
|
-
node.left
|
98
|
-
end
|
99
|
-
|
100
|
-
def nary(node)
|
101
|
-
node.children.each { |c| visit(c) }
|
102
|
-
end
|
103
|
-
|
104
|
-
def unary(node)
|
105
|
-
visit(node.left)
|
106
|
-
end
|
107
|
-
|
108
|
-
def visit_CAT(node)
|
109
|
-
binary(node)
|
110
|
-
end
|
111
|
-
|
112
|
-
def visit_SYMBOL(node)
|
113
|
-
terminal(node)
|
114
|
-
end
|
115
|
-
|
116
|
-
def visit_LITERAL(node)
|
117
|
-
terminal(node)
|
118
|
-
end
|
119
|
-
|
120
|
-
def visit_SLASH(node)
|
121
|
-
terminal(node)
|
122
|
-
end
|
1
|
+
# frozen_string_literal: true
|
123
2
|
|
124
|
-
|
125
|
-
terminal(node)
|
126
|
-
end
|
127
|
-
|
128
|
-
def visit_SYMBOL(node)
|
129
|
-
placeholder(node)
|
130
|
-
end
|
131
|
-
|
132
|
-
def visit_OR(node)
|
133
|
-
nary(node)
|
134
|
-
end
|
3
|
+
require 'action_dispatch/journey'
|
135
4
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
def visit_GROUP(node)
|
141
|
-
if @group_depth >= 1
|
142
|
-
raise RuntimeError.new 'Cannot transform nested groups.'
|
143
|
-
else
|
144
|
-
@group_depth += 1
|
145
|
-
visit node.left
|
146
|
-
end
|
147
|
-
ensure
|
148
|
-
@group_depth -= 1
|
149
|
-
end
|
150
|
-
|
151
|
-
instance_methods(true).each do |meth|
|
152
|
-
next unless meth =~ /^visit_(.*)$/
|
153
|
-
DISPATCH_CACHE[$1.to_sym] = meth
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|
5
|
+
require 'rails/rfc6570/formatter'
|
6
|
+
require 'rails/rfc6570/version'
|
7
|
+
require 'rails/rfc6570/visitor'
|
159
8
|
|
160
9
|
module Rails
|
161
10
|
module RFC6570
|
162
11
|
if defined?(::Rails::Railtie)
|
163
12
|
class Railtie < ::Rails::Railtie # :nodoc:
|
164
|
-
initializer 'rails-rfc6570', :
|
13
|
+
initializer 'rails-rfc6570', group: :all do |_app|
|
165
14
|
require 'rails/rfc6570/patches'
|
166
|
-
require 'action_dispatch/journey'
|
167
15
|
|
168
16
|
MAJOR = Rails::VERSION::MAJOR
|
169
17
|
MINOR = Rails::VERSION::MINOR
|
170
18
|
|
171
|
-
::ActionDispatch::Routing::RouteSet.
|
19
|
+
::ActionDispatch::Routing::RouteSet.include \
|
172
20
|
Rails::RFC6570::Extensions::RouteSet
|
173
21
|
|
174
|
-
::ActionDispatch::Routing::RouteSet::NamedRouteCollection.
|
175
|
-
|
22
|
+
::ActionDispatch::Routing::RouteSet::NamedRouteCollection.prepend \
|
23
|
+
Rails::RFC6570::Extensions::NamedRouteCollection
|
176
24
|
|
177
|
-
::ActionDispatch::Journey::Route.
|
25
|
+
::ActionDispatch::Journey::Route.include \
|
178
26
|
Rails::RFC6570::Extensions::JourneyRoute
|
179
27
|
|
180
|
-
::ActionDispatch::Journey::Nodes::Node.send :include,
|
181
|
-
Rails::RFC6570::Extensions::JourneyNode
|
182
|
-
|
183
28
|
::ActiveSupport.on_load(:action_controller) do
|
184
29
|
include Rails::RFC6570::Helper
|
185
30
|
extend Rails::RFC6570::ControllerExtension
|
@@ -191,13 +36,13 @@ module Rails
|
|
191
36
|
module Extensions
|
192
37
|
module RouteSet
|
193
38
|
def to_rfc6570(opts = {})
|
194
|
-
routes.map{|r| r.to_rfc6570(opts) }
|
39
|
+
routes.map {|r| r.to_rfc6570(opts) }
|
195
40
|
end
|
196
41
|
end
|
197
42
|
|
198
43
|
module NamedRouteCollection
|
199
44
|
def to_rfc6570(opts = {})
|
200
|
-
Hash[routes.map{|n, r| [n, r.to_rfc6570(opts)] }]
|
45
|
+
Hash[routes.map {|n, r| [n, r.to_rfc6570(opts)] }]
|
201
46
|
end
|
202
47
|
|
203
48
|
def define_rfc6570_helpers(name, route, mod, set)
|
@@ -210,16 +55,26 @@ module Rails
|
|
210
55
|
end
|
211
56
|
|
212
57
|
mod.module_eval do
|
213
|
-
define_method(rfc6570_name) do
|
214
|
-
::Rails::RFC6570
|
58
|
+
define_method(rfc6570_name) do |**opts|
|
59
|
+
::Rails::RFC6570.build_url_template(self, route, **opts)
|
215
60
|
end
|
216
61
|
|
217
|
-
define_method(rfc6570_url_name) do
|
218
|
-
|
62
|
+
define_method(rfc6570_url_name) do |**opts|
|
63
|
+
::Rails::RFC6570.build_url_template(
|
64
|
+
self,
|
65
|
+
route,
|
66
|
+
**opts,
|
67
|
+
path_only: false
|
68
|
+
)
|
219
69
|
end
|
220
70
|
|
221
|
-
define_method(rfc6570_path_name) do
|
222
|
-
|
71
|
+
define_method(rfc6570_path_name) do |**opts|
|
72
|
+
::Rails::RFC6570.build_url_template(
|
73
|
+
self,
|
74
|
+
route,
|
75
|
+
**opts,
|
76
|
+
path_only: true
|
77
|
+
)
|
223
78
|
end
|
224
79
|
end
|
225
80
|
|
@@ -233,46 +88,38 @@ module Rails
|
|
233
88
|
define_rfc6570_helpers name, route, @url_helpers_module, @url_helpers
|
234
89
|
end
|
235
90
|
|
236
|
-
|
91
|
+
alias []= add
|
237
92
|
end
|
238
93
|
|
239
94
|
module JourneyRoute
|
240
|
-
def to_rfc6570(opts
|
241
|
-
|
242
|
-
|
243
|
-
end
|
244
|
-
|
245
|
-
module JourneyNode
|
246
|
-
def to_rfc6570(opts = {})
|
247
|
-
::Addressable::Template.new \
|
248
|
-
::ActionDispatch::Journey::Visitors::RFC6570.new(opts).accept(self)
|
95
|
+
def to_rfc6570(**opts)
|
96
|
+
@rfc6570_formatter ||= RFC6570::Formatter.new(self)
|
97
|
+
@rfc6570_formatter.evaluate(**opts)
|
249
98
|
end
|
250
99
|
end
|
251
100
|
end
|
252
101
|
|
253
102
|
module Helper
|
254
|
-
def rfc6570_routes(opts
|
103
|
+
def rfc6570_routes(**opts)
|
255
104
|
routes = {}
|
256
105
|
Rails.application.routes.named_routes.names.each do |key|
|
257
|
-
routes[key] = rfc6570_route(key, opts)
|
106
|
+
routes[key] = rfc6570_route(key, **opts)
|
258
107
|
end
|
259
108
|
|
260
109
|
routes
|
261
110
|
end
|
262
111
|
|
263
|
-
def rfc6570_route(name, opts
|
264
|
-
route
|
265
|
-
unless route
|
266
|
-
raise KeyError.new "No named routed for `#{name}'."
|
267
|
-
end
|
112
|
+
def rfc6570_route(name, **opts)
|
113
|
+
route = Rails.application.routes.named_routes[name]
|
114
|
+
raise KeyError.new "No named routed for `#{name}'." unless route
|
268
115
|
|
269
|
-
|
116
|
+
route.to_rfc6570(**opts, ctx: self)
|
270
117
|
end
|
271
118
|
end
|
272
119
|
|
273
120
|
module ControllerExtension
|
274
121
|
def rfc6570_defs
|
275
|
-
@
|
122
|
+
@rfc6570_defs ||= {}
|
276
123
|
end
|
277
124
|
|
278
125
|
def rfc6570_params(defs)
|
@@ -284,27 +131,17 @@ module Rails
|
|
284
131
|
end
|
285
132
|
end
|
286
133
|
|
287
|
-
def build_url_template(t, route, options)
|
288
|
-
template = route.to_rfc6570(options)
|
289
|
-
|
290
|
-
if options.fetch(:path_only, false)
|
291
|
-
template
|
292
|
-
else
|
293
|
-
options = t.url_options.merge(options)
|
294
|
-
options[:path] = template.pattern
|
295
|
-
|
296
|
-
url = ActionDispatch::Http::URL.url_for options
|
297
|
-
|
298
|
-
::Addressable::Template.new url
|
299
|
-
end
|
300
|
-
end
|
301
|
-
|
302
134
|
def params_for(controller, action)
|
303
135
|
ctr = "#{controller.camelize}Controller".constantize
|
304
136
|
ctr.rfc6570_defs[action.to_sym] if ctr.respond_to?(:rfc6570_defs)
|
305
137
|
rescue NameError
|
306
138
|
nil
|
307
139
|
end
|
308
|
-
|
140
|
+
|
141
|
+
def build_url_template(ctx, route, **kwargs)
|
142
|
+
route.to_rfc6570(ctx: ctx, **kwargs)
|
143
|
+
end
|
144
|
+
|
145
|
+
extend self # rubocop:disable Style/ModuleFunction
|
309
146
|
end
|
310
147
|
end
|