js-routes 2.1.1 → 2.2.2
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 +4 -4
- data/CHANGELOG.md +21 -0
- data/Readme.md +87 -49
- data/lib/js_routes/configuration.rb +111 -0
- data/lib/js_routes/engine.rb +1 -1
- data/lib/js_routes/generators/middleware.rb +58 -0
- data/lib/js_routes/generators/webpacker.rb +1 -1
- data/lib/js_routes/instance.rb +154 -0
- data/lib/js_routes/middleware.rb +36 -0
- data/lib/js_routes/route.rb +172 -0
- data/lib/js_routes/version.rb +2 -2
- data/lib/js_routes.rb +11 -421
- data/lib/routes.js +10 -7
- data/lib/routes.ts +13 -8
- data/spec/js_routes/module_types/amd_spec.rb +6 -5
- data/spec/js_routes/module_types/nil_spec.rb +86 -0
- data/spec/js_routes/module_types/umd_spec.rb +1 -1
- data/spec/js_routes/options_spec.rb +33 -51
- data/spec/spec_helper.rb +1 -2
- data/spec/support/routes.rb +1 -1
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 52db2ffdef9bea714377b9c00e152177b17e40de0fd8ef57ba09a84fee2f206e
|
4
|
+
data.tar.gz: 8f899234c70859fee6a7c0486825c12ce501a01052e2b5d9a038f08544ac6df9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e697c45b1908906c40cdc4591f5914dd415226de79a42a8e948f6095e0f09eb5edb5bfb0c5fd61953fde7121d9a025b3472b644ddb17ca2c13cb075c97311000
|
7
|
+
data.tar.gz: 7f48edacee6659d4e4b5be0d71b5127f26e473119a8bf13a73c55a7b3c295dbee7fc34b9d3f515725c5871baad319ceb0bb32ed176900845b48a84c786ba3f9c
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
## master
|
2
2
|
|
3
|
+
## v2.2.2.
|
4
|
+
|
5
|
+
* Fix custom file path [#295](https://github.com/railsware/js-routes/issues/295)
|
6
|
+
|
7
|
+
## v2.2.1
|
8
|
+
|
9
|
+
* Improve generator to update route files on `assets:precompile` and add them to `.gitignore by default` [#288](https://github.com/railsware/js-routes/issues/288#issuecomment-1012182815)
|
10
|
+
|
11
|
+
## v2.2.0
|
12
|
+
|
13
|
+
* Use Rack Middleware to automatically update routes file in development [#288](https://github.com/railsware/js-routes/issues/288)
|
14
|
+
* This setup is now a default recommended due to lack of any downside comparing to [ERB Loader](./Readme.md#webpacker) and [Manual Setup](./Readme.md#advanced-setup)
|
15
|
+
|
16
|
+
## v2.1.3
|
17
|
+
|
18
|
+
* Fix `default_url_options` bug. [#290](https://github.com/railsware/js-routes/issues/290)
|
19
|
+
|
20
|
+
## v2.1.2
|
21
|
+
|
22
|
+
* Improve browser window object detection. [#287](https://github.com/railsware/js-routes/issues/287)
|
23
|
+
|
3
24
|
## v2.1.1
|
4
25
|
|
5
26
|
* Added webpacker generator `./bin/rails generate js_routes:webpacker`
|
data/Readme.md
CHANGED
@@ -16,13 +16,16 @@ gem "js-routes"
|
|
16
16
|
|
17
17
|
## Setup
|
18
18
|
|
19
|
-
There are
|
19
|
+
There are several possible ways to setup JsRoutes:
|
20
20
|
|
21
21
|
* [Quick and easy](#quick-start)
|
22
|
-
*
|
23
|
-
*
|
22
|
+
* Uses Rack Middleware to automatically update routes locally
|
23
|
+
* Works great for a simple Rails application
|
24
|
+
* [Webpacker ERB Loader](#webpacker)
|
24
25
|
* Requires ESM module system (the default)
|
25
26
|
* Doesn't support typescript definitions
|
27
|
+
* [Advanced Setup](#advanced-setup)
|
28
|
+
* Allows very custom setups
|
26
29
|
* [Sprockets](#sprockets) legacy
|
27
30
|
* Deprecated and not recommended for modern apps
|
28
31
|
|
@@ -30,36 +33,54 @@ There are 3 possible ways to setup JsRoutes:
|
|
30
33
|
|
31
34
|
### Quick Start
|
32
35
|
|
33
|
-
|
36
|
+
Setup [Rack Middleware](https://guides.rubyonrails.org/rails_on_rack.html#action-dispatcher-middleware-stack)
|
37
|
+
to automatically generate and maintain `routes.js` file and corresponding
|
38
|
+
[Typescript definitions](https://www.typescriptlang.org/docs/handbook/declaration-files/templates/module-d-ts.html) `routes.d.ts`:
|
39
|
+
|
40
|
+
#### Use a Generator
|
41
|
+
|
42
|
+
Run a command:
|
34
43
|
|
35
44
|
``` sh
|
36
|
-
|
37
|
-
# OR for typescript support
|
38
|
-
rake js:routes:typescript
|
45
|
+
rails generate js_routes:middleware
|
39
46
|
```
|
40
47
|
|
41
|
-
|
48
|
+
#### Setup Manually
|
42
49
|
|
43
|
-
|
50
|
+
Add the following to `config/environments/development.rb`:
|
44
51
|
|
45
|
-
```
|
46
|
-
|
47
|
-
console.log(posts_path({format: 'json'})) // => "/posts.json"
|
48
|
-
console.log(edit_post_path(1)) // => "/posts/1/edit"
|
52
|
+
``` ruby
|
53
|
+
config.middleware.use(JsRoutes::Middleware)
|
49
54
|
```
|
50
55
|
|
51
|
-
|
56
|
+
Use it in `app/javascript/packs/application.js`:
|
52
57
|
|
53
58
|
``` javascript
|
54
|
-
import * as Routes from 'routes';
|
55
|
-
window.Routes = Routes;
|
59
|
+
import * as Routes from '../routes';
|
60
|
+
// window.Routes = Routes;
|
61
|
+
alert(Routes.post_path(1))
|
62
|
+
```
|
63
|
+
|
64
|
+
Upgrade `rake assets:precompile` to update js-routes files:
|
65
|
+
|
66
|
+
``` ruby
|
67
|
+
namespace :assets do
|
68
|
+
task :precompile => "js:routes:typescript"
|
69
|
+
end
|
70
|
+
```
|
71
|
+
|
72
|
+
Add js-routes files to `.gitignore`:
|
73
|
+
|
74
|
+
```
|
75
|
+
/app/javascript/routes.js
|
76
|
+
/app/javascript/routes.d.ts
|
56
77
|
```
|
57
78
|
|
58
79
|
<div id='webpacker'></div>
|
59
80
|
|
60
|
-
### Webpacker
|
81
|
+
### Webpacker ERB loader
|
61
82
|
|
62
|
-
**IMPORTANT**: this setup doesn't support IDE autocompletion with [Typescript](
|
83
|
+
**IMPORTANT**: this setup doesn't support IDE autocompletion with [Typescript](https://www.typescriptlang.org/docs/handbook/declaration-files/templates/module-d-ts.html)
|
63
84
|
|
64
85
|
|
65
86
|
#### Use a Generator
|
@@ -118,9 +139,54 @@ import * as Routes from 'routes.js.erb';
|
|
118
139
|
window.Routes = Routes;
|
119
140
|
```
|
120
141
|
|
142
|
+
<div id='advanced-setup'></div>
|
143
|
+
|
144
|
+
### Advanced Setup
|
145
|
+
|
146
|
+
**IMPORTANT**: that this setup requires the JS routes file to be updates manually
|
147
|
+
|
148
|
+
Routes file can be generated with a `rake` task:
|
149
|
+
|
150
|
+
``` sh
|
151
|
+
rake js:routes
|
152
|
+
# OR for typescript support
|
153
|
+
rake js:routes:typescript
|
154
|
+
```
|
155
|
+
|
156
|
+
In case you need multiple route files for different parts of your application, you have to create the files manually.
|
157
|
+
If your application has an `admin` and an `application` namespace for example:
|
158
|
+
|
159
|
+
**IMPORTANT**: Requires [Webpacker ERB Loader](#webpacker) setup.
|
160
|
+
|
161
|
+
``` erb
|
162
|
+
// app/javascript/admin/routes.js.erb
|
163
|
+
<%= JsRoutes.generate(include: /admin/) %>
|
164
|
+
```
|
165
|
+
|
166
|
+
``` erb
|
167
|
+
// app/javascript/customer/routes.js.erb
|
168
|
+
<%= JsRoutes.generate(exclude: /admin/) %>
|
169
|
+
```
|
170
|
+
|
171
|
+
You can manipulate the generated helper manually by injecting ruby into javascript:
|
172
|
+
|
173
|
+
``` erb
|
174
|
+
export const routes = <%= JsRoutes.generate(module_type: nil, namespace: nil) %>
|
175
|
+
```
|
176
|
+
|
177
|
+
If you want to generate the routes files outside of the asset pipeline, you can use `JsRoutes.generate!`:
|
178
|
+
|
179
|
+
``` ruby
|
180
|
+
path = Rails.root.join("app/javascript")
|
181
|
+
|
182
|
+
JsRoutes.generate!("#{path}/app_routes.js", exclude: [/^admin_/, /^api_/])
|
183
|
+
JsRoutes.generate!("#{path}/adm_routes.js", include: /^admin_/)
|
184
|
+
JsRoutes.generate!("#{path}/api_routes.js", include: /^api_/, default_url_options: {format: "json"})
|
185
|
+
```
|
186
|
+
|
121
187
|
<div id='definitions'></div>
|
122
188
|
|
123
|
-
|
189
|
+
#### Typescript Definitions
|
124
190
|
|
125
191
|
JsRoutes has typescript support out of the box.
|
126
192
|
|
@@ -230,6 +296,8 @@ Options to configure JavaScript file generator. These options are only available
|
|
230
296
|
* `file` - a file location where generated routes are stored
|
231
297
|
* Default: `app/javascript/routes.js` if setup with Webpacker, otherwise `app/assets/javascripts/routes.js` if setup with Sprockets.
|
232
298
|
|
299
|
+
<div id="formatter-options"></div>
|
300
|
+
|
233
301
|
#### Formatter Options
|
234
302
|
|
235
303
|
Options to configure routes formatting. These options are available both in Ruby and JavaScript context.
|
@@ -248,36 +316,6 @@ Options to configure routes formatting. These options are available both in Ruby
|
|
248
316
|
* This option exists because JS doesn't provide a difference between an object and a hash
|
249
317
|
* Default: `_options`
|
250
318
|
|
251
|
-
## Advanced Setup
|
252
|
-
|
253
|
-
In case you need multiple route files for different parts of your application, you have to create the files manually.
|
254
|
-
If your application has an `admin` and an `application` namespace for example:
|
255
|
-
|
256
|
-
``` erb
|
257
|
-
// app/javascript/admin/routes.js.erb
|
258
|
-
<%= JsRoutes.generate(include: /admin/) %>
|
259
|
-
```
|
260
|
-
|
261
|
-
``` erb
|
262
|
-
// app/javascript/customer/routes.js.erb
|
263
|
-
<%= JsRoutes.generate(exclude: /admin/) %>
|
264
|
-
```
|
265
|
-
|
266
|
-
You can manipulate the generated helper manually by injecting ruby into javascript:
|
267
|
-
|
268
|
-
``` erb
|
269
|
-
export const routes = <%= JsRoutes.generate(module_type: nil, namespace: nil) %>
|
270
|
-
```
|
271
|
-
|
272
|
-
If you want to generate the routes files outside of the asset pipeline, you can use `JsRoutes.generate!`:
|
273
|
-
|
274
|
-
``` ruby
|
275
|
-
path = Rails.root.join("app/javascript")
|
276
|
-
|
277
|
-
JsRoutes.generate!("#{path}/app_routes.js", exclude: [/^admin_/, /^api_/])
|
278
|
-
JsRoutes.generate!("#{path}/adm_routes.js", include: /^admin_/)
|
279
|
-
JsRoutes.generate!("#{path}/api_routes.js", include: /^api_/, default_url_options: {format: "json"})
|
280
|
-
```
|
281
319
|
|
282
320
|
## Usage
|
283
321
|
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require "pathname"
|
2
|
+
|
3
|
+
module JsRoutes
|
4
|
+
class Configuration
|
5
|
+
DEFAULTS = {
|
6
|
+
namespace: nil,
|
7
|
+
exclude: [],
|
8
|
+
include: //,
|
9
|
+
file: nil,
|
10
|
+
prefix: -> { Rails.application.config.relative_url_root || "" },
|
11
|
+
url_links: false,
|
12
|
+
camel_case: false,
|
13
|
+
default_url_options: {},
|
14
|
+
compact: false,
|
15
|
+
serializer: nil,
|
16
|
+
special_options_key: "_options",
|
17
|
+
application: -> { Rails.application },
|
18
|
+
module_type: 'ESM',
|
19
|
+
documentation: true,
|
20
|
+
} #:nodoc:
|
21
|
+
|
22
|
+
attr_accessor(*DEFAULTS.keys)
|
23
|
+
|
24
|
+
def initialize(attributes = nil)
|
25
|
+
assign(DEFAULTS)
|
26
|
+
return unless attributes
|
27
|
+
assign(attributes)
|
28
|
+
end
|
29
|
+
|
30
|
+
def assign(attributes = nil, &block)
|
31
|
+
if !attributes && !block
|
32
|
+
raise "Provide attributes or block"
|
33
|
+
end
|
34
|
+
tap(&block) if block
|
35
|
+
if attributes
|
36
|
+
attributes.each do |attribute, value|
|
37
|
+
value = value.call if value.is_a?(Proc)
|
38
|
+
send(:"#{attribute}=", value)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
normalize_and_verify
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
45
|
+
def [](attribute)
|
46
|
+
send(attribute)
|
47
|
+
end
|
48
|
+
|
49
|
+
def merge(attributes)
|
50
|
+
clone.assign(attributes)
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_hash
|
54
|
+
Hash[*members.zip(values).flatten(1)].symbolize_keys
|
55
|
+
end
|
56
|
+
|
57
|
+
def esm?
|
58
|
+
module_type === 'ESM'
|
59
|
+
end
|
60
|
+
|
61
|
+
def dts?
|
62
|
+
self.module_type === 'DTS'
|
63
|
+
end
|
64
|
+
|
65
|
+
def modern?
|
66
|
+
esm? || dts?
|
67
|
+
end
|
68
|
+
|
69
|
+
def require_esm
|
70
|
+
raise "ESM module type is required" unless modern?
|
71
|
+
end
|
72
|
+
|
73
|
+
def source_file
|
74
|
+
File.dirname(__FILE__) + "/../" + default_file_name
|
75
|
+
end
|
76
|
+
|
77
|
+
def output_file
|
78
|
+
webpacker_dir = pathname('app', 'javascript')
|
79
|
+
sprockets_dir = pathname('app','assets','javascripts')
|
80
|
+
file_name = file || default_file_name
|
81
|
+
sprockets_file = sprockets_dir.join(file_name)
|
82
|
+
webpacker_file = webpacker_dir.join(file_name)
|
83
|
+
!Dir.exist?(webpacker_dir) && defined?(::Sprockets) ? sprockets_file : webpacker_file
|
84
|
+
end
|
85
|
+
|
86
|
+
protected
|
87
|
+
|
88
|
+
def normalize_and_verify
|
89
|
+
normalize
|
90
|
+
verify
|
91
|
+
end
|
92
|
+
|
93
|
+
def pathname(*parts)
|
94
|
+
Pathname.new(File.join(*parts))
|
95
|
+
end
|
96
|
+
|
97
|
+
def default_file_name
|
98
|
+
dts? ? "routes.d.ts" : "routes.js"
|
99
|
+
end
|
100
|
+
|
101
|
+
def normalize
|
102
|
+
self.module_type = module_type&.upcase || 'NIL'
|
103
|
+
end
|
104
|
+
|
105
|
+
def verify
|
106
|
+
if module_type != 'NIL' && namespace
|
107
|
+
raise "JsRoutes namespace option can only be used if module_type is nil"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
data/lib/js_routes/engine.rb
CHANGED
@@ -0,0 +1,58 @@
|
|
1
|
+
require "rails/generators"
|
2
|
+
|
3
|
+
class JsRoutes::Generators::Middleware < Rails::Generators::Base
|
4
|
+
|
5
|
+
source_root File.expand_path(__FILE__ + "/../../../templates")
|
6
|
+
|
7
|
+
def create_middleware
|
8
|
+
copy_file "initializer.rb", "config/initializers/js_routes.rb"
|
9
|
+
inject_into_file "app/javascript/packs/application.js", pack_content
|
10
|
+
inject_into_file "config/environments/development.rb", middleware_content, before: /^end\n\z/
|
11
|
+
inject_into_file "Rakefile", rakefile_content
|
12
|
+
inject_into_file ".gitignore", gitignore_content
|
13
|
+
JsRoutes.generate!
|
14
|
+
JsRoutes.definitions!
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def pack_content
|
20
|
+
<<-JS
|
21
|
+
import * as Routes from '../routes';
|
22
|
+
window.Routes = Routes;
|
23
|
+
JS
|
24
|
+
end
|
25
|
+
|
26
|
+
def middleware_content
|
27
|
+
<<-RB
|
28
|
+
|
29
|
+
# Automatically update js-routes file
|
30
|
+
# when routes.rb is changed
|
31
|
+
config.middleware.use(JsRoutes::Middleware)
|
32
|
+
RB
|
33
|
+
end
|
34
|
+
|
35
|
+
def rakefile_content
|
36
|
+
<<-RB
|
37
|
+
|
38
|
+
# Update js-routes file before assets precompile
|
39
|
+
namespace :assets do
|
40
|
+
task :precompile => "js:routes:typescript"
|
41
|
+
end
|
42
|
+
RB
|
43
|
+
end
|
44
|
+
|
45
|
+
def gitignore_content
|
46
|
+
banner = <<-TXT
|
47
|
+
|
48
|
+
# Ignore automatically generated js-routes files.
|
49
|
+
TXT
|
50
|
+
|
51
|
+
banner + [
|
52
|
+
{},
|
53
|
+
{module_type: 'DTS'}
|
54
|
+
].map do |config|
|
55
|
+
File.join('/', JsRoutes.new(config).configuration.output_file) + "\n"
|
56
|
+
end.join
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require "js_routes/configuration"
|
2
|
+
require "js_routes/route"
|
3
|
+
|
4
|
+
module JsRoutes
|
5
|
+
class Instance
|
6
|
+
|
7
|
+
attr_reader :configuration
|
8
|
+
#
|
9
|
+
# Implementation
|
10
|
+
#
|
11
|
+
|
12
|
+
def initialize(options = {})
|
13
|
+
@configuration = JsRoutes.configuration.merge(options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def generate
|
17
|
+
# Ensure routes are loaded. If they're not, load them.
|
18
|
+
if named_routes.empty? && application.respond_to?(:reload_routes!)
|
19
|
+
application.reload_routes!
|
20
|
+
end
|
21
|
+
content = File.read(@configuration.source_file)
|
22
|
+
|
23
|
+
if !@configuration.dts?
|
24
|
+
content = js_variables.inject(content) do |js, (key, value)|
|
25
|
+
js.gsub!("RubyVariables.#{key}", value.to_s) ||
|
26
|
+
raise("Missing key #{key} in JS template")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
content + routes_export + prevent_types_export
|
30
|
+
end
|
31
|
+
|
32
|
+
def generate!
|
33
|
+
# Some libraries like Devise did not load their routes yet
|
34
|
+
# so we will wait until initialization process finishes
|
35
|
+
# https://github.com/railsware/js-routes/issues/7
|
36
|
+
Rails.configuration.after_initialize do
|
37
|
+
file_path = Rails.root.join(@configuration.output_file)
|
38
|
+
source_code = generate
|
39
|
+
|
40
|
+
# We don't need to rewrite file if it already exist and have same content.
|
41
|
+
# It helps asset pipeline or webpack understand that file wasn't changed.
|
42
|
+
next if File.exist?(file_path) && File.read(file_path) == source_code
|
43
|
+
|
44
|
+
File.open(file_path, 'w') do |f|
|
45
|
+
f.write source_code
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
protected
|
51
|
+
|
52
|
+
def js_variables
|
53
|
+
{
|
54
|
+
'GEM_VERSION' => JsRoutes::VERSION,
|
55
|
+
'ROUTES_OBJECT' => routes_object,
|
56
|
+
'RAILS_VERSION' => ActionPack.version,
|
57
|
+
'DEPRECATED_GLOBBING_BEHAVIOR' => ActionPack::VERSION::MAJOR == 4 && ActionPack::VERSION::MINOR == 0,
|
58
|
+
|
59
|
+
'APP_CLASS' => application.class.to_s,
|
60
|
+
'NAMESPACE' => json(@configuration.namespace),
|
61
|
+
'DEFAULT_URL_OPTIONS' => json(@configuration.default_url_options),
|
62
|
+
'PREFIX' => json(@configuration.prefix),
|
63
|
+
'SPECIAL_OPTIONS_KEY' => json(@configuration.special_options_key),
|
64
|
+
'SERIALIZER' => @configuration.serializer || json(nil),
|
65
|
+
'MODULE_TYPE' => json(@configuration.module_type),
|
66
|
+
'WRAPPER' => @configuration.esm? ? 'const __jsr = ' : '',
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
def application
|
71
|
+
@configuration.application
|
72
|
+
end
|
73
|
+
|
74
|
+
def json(string)
|
75
|
+
JsRoutes.json(string)
|
76
|
+
end
|
77
|
+
|
78
|
+
def named_routes
|
79
|
+
application.routes.named_routes.to_a
|
80
|
+
end
|
81
|
+
|
82
|
+
def routes_object
|
83
|
+
return json({}) if @configuration.modern?
|
84
|
+
properties = routes_list.map do |comment, name, body|
|
85
|
+
"#{comment}#{name}: #{body}".indent(2)
|
86
|
+
end
|
87
|
+
"{\n" + properties.join(",\n\n") + "}\n"
|
88
|
+
end
|
89
|
+
|
90
|
+
def static_exports
|
91
|
+
[:configure, :config, :serialize].map do |name|
|
92
|
+
[
|
93
|
+
"", name,
|
94
|
+
@configuration.dts? ?
|
95
|
+
"RouterExposedMethods['#{name}']" :
|
96
|
+
"__jsr.#{name}"
|
97
|
+
]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def routes_export
|
102
|
+
return "" unless @configuration.modern?
|
103
|
+
[*static_exports, *routes_list].map do |comment, name, body|
|
104
|
+
"#{comment}export const #{name}#{export_separator}#{body};\n\n"
|
105
|
+
end.join
|
106
|
+
end
|
107
|
+
|
108
|
+
def prevent_types_export
|
109
|
+
return "" unless @configuration.dts?
|
110
|
+
<<-JS
|
111
|
+
// By some reason this line prevents all types in a file
|
112
|
+
// from being automatically exported
|
113
|
+
export {};
|
114
|
+
JS
|
115
|
+
end
|
116
|
+
|
117
|
+
def export_separator
|
118
|
+
@configuration.dts? ? ': ' : ' = '
|
119
|
+
end
|
120
|
+
|
121
|
+
def routes_list
|
122
|
+
named_routes.sort_by(&:first).flat_map do |_, route|
|
123
|
+
route_helpers_if_match(route) + mounted_app_routes(route)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def mounted_app_routes(route)
|
128
|
+
rails_engine_app = app_from_route(route)
|
129
|
+
if rails_engine_app.respond_to?(:superclass) &&
|
130
|
+
rails_engine_app.superclass == Rails::Engine && !route.path.anchored
|
131
|
+
rails_engine_app.routes.named_routes.flat_map do |_, engine_route|
|
132
|
+
route_helpers_if_match(engine_route, route)
|
133
|
+
end
|
134
|
+
else
|
135
|
+
[]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def app_from_route(route)
|
140
|
+
app = route.app
|
141
|
+
# rails engine in Rails 4.2 use additional
|
142
|
+
# ActionDispatch::Routing::Mapper::Constraints, which contain app
|
143
|
+
if app.respond_to?(:app) && app.respond_to?(:constraints)
|
144
|
+
app.app
|
145
|
+
else
|
146
|
+
app
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def route_helpers_if_match(route, parent_route = nil)
|
151
|
+
Route.new(@configuration, route, parent_route).helpers
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module JsRoutes
|
2
|
+
# A Rack middleware that automatically updates routes file
|
3
|
+
# whenever routes.rb is modified
|
4
|
+
#
|
5
|
+
# Inspired by
|
6
|
+
# https://github.com/fnando/i18n-js/blob/main/lib/i18n/js/middleware.rb
|
7
|
+
class Middleware
|
8
|
+
def initialize(app)
|
9
|
+
@app = app
|
10
|
+
@routes_file = Rails.root.join("config/routes.rb")
|
11
|
+
@mtime = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
update_js_routes
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def update_js_routes
|
22
|
+
new_mtime = routes_mtime
|
23
|
+
unless new_mtime == @mtime
|
24
|
+
JsRoutes.generate!
|
25
|
+
JsRoutes.definitions!
|
26
|
+
@mtime = new_mtime
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def routes_mtime
|
31
|
+
File.mtime(@routes_file)
|
32
|
+
rescue Errno::ENOENT
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|