js-routes 1.4.9 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc.js +15 -0
  3. data/.gitignore +5 -0
  4. data/.nvmrc +1 -0
  5. data/.travis.yml +2 -1
  6. data/CHANGELOG.md +85 -0
  7. data/Rakefile +5 -2
  8. data/Readme.md +274 -98
  9. data/VERSION_2_UPGRADE.md +66 -0
  10. data/js-routes.gemspec +8 -5
  11. data/lib/js_routes/engine.rb +0 -1
  12. data/lib/js_routes/generators/middleware.rb +33 -0
  13. data/lib/js_routes/generators/webpacker.rb +32 -0
  14. data/lib/js_routes/middleware.rb +36 -0
  15. data/lib/js_routes/version.rb +1 -1
  16. data/lib/js_routes.rb +341 -171
  17. data/lib/routes.d.ts +79 -0
  18. data/lib/routes.js +501 -519
  19. data/lib/routes.ts +737 -0
  20. data/lib/tasks/js_routes.rake +8 -2
  21. data/lib/templates/erb.js +11 -0
  22. data/lib/templates/initializer.rb +5 -0
  23. data/lib/templates/routes.js.erb +1 -0
  24. data/package.json +37 -0
  25. data/spec/dummy/app/assets/config/manifest.js +2 -0
  26. data/spec/js_routes/default_serializer_spec.rb +19 -3
  27. data/spec/js_routes/{amd_compatibility_spec.rb → module_types/amd_spec.rb} +7 -14
  28. data/spec/js_routes/module_types/cjs_spec.rb +15 -0
  29. data/spec/js_routes/module_types/dts/routes.spec.d.ts +114 -0
  30. data/spec/js_routes/module_types/dts/test.spec.ts +56 -0
  31. data/spec/js_routes/module_types/dts_spec.rb +111 -0
  32. data/spec/js_routes/module_types/esm_spec.rb +45 -0
  33. data/spec/js_routes/module_types/nil_spec.rb +86 -0
  34. data/spec/js_routes/{generated_javascript_spec.rb → module_types/umd_spec.rb} +33 -27
  35. data/spec/js_routes/options_spec.rb +67 -56
  36. data/spec/js_routes/rails_routes_compatibility_spec.rb +69 -25
  37. data/spec/js_routes/zzz_last_post_rails_init_spec.rb +4 -4
  38. data/spec/spec_helper.rb +34 -17
  39. data/spec/support/routes.rb +10 -4
  40. data/spec/tsconfig.json +4 -0
  41. data/tsconfig.json +28 -0
  42. data/yarn.lock +2145 -0
  43. metadata +42 -22
  44. data/lib/routes.js.coffee +0 -411
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bcc3b758ce05ed0444162cda94d5442b811a582330ea4418cf816763e4e482b0
4
- data.tar.gz: 3bfd8cc484ba00a6cd7ff0e5ffb90c3f3ec11c1d7aa9171572e93bc66b1cab42
3
+ metadata.gz: 315ddd617bc6630cf5858afc5ba38d2c204f6167a7984ccdaf7171a50404e418
4
+ data.tar.gz: 676d2d36107ee524c07517143499173c0658731cc06d1c52753e3ab2f4e6cb81
5
5
  SHA512:
6
- metadata.gz: a51ee9fc01642e16287b648085debd75749b983b2602a2407068cc7159cd302f8b04bd065b1ea28f7314cd19ae60e535cede86af4e7d7073648ffe2b3222d006
7
- data.tar.gz: a979758f820232a129f9befd597a248511c76b05eab8aae5b62b56bf31a2f94580b889371aa52e584aac0fdfd5802a03f1632eaee65713b2438d98e29265846b
6
+ metadata.gz: 6c7f715e9afd02d1daebb882381e328595beca59a6a6d8c10a3a1518801522090e986c6b362174aaa9c51faf91508ee8e1cc6fff8ba118a08c32eb26c7205ba1
7
+ data.tar.gz: 7f70bfa95a1fb42092f20118bb3f22f07e459ccc6f95b8d3b0651faf0457266152465873da6a4dfddc4d52df006d6f5b991e3608a083c1eb524fef5ed77ff0c8
data/.eslintrc.js ADDED
@@ -0,0 +1,15 @@
1
+ module.exports = {
2
+ root: true,
3
+ extends: [
4
+ 'eslint:recommended',
5
+ 'plugin:@typescript-eslint/eslint-recommended',
6
+ 'plugin:@typescript-eslint/recommended',
7
+ 'prettier/@typescript-eslint',
8
+ ],
9
+ parser: '@typescript-eslint/parser',
10
+ plugins: ['@typescript-eslint'],
11
+ rules: {
12
+ '@typescript-eslint/ban-types': 'off',
13
+ '@typescript-eslint/no-explicit-any': 'off'
14
+ },
15
+ };
data/.gitignore CHANGED
@@ -14,6 +14,9 @@ log
14
14
 
15
15
  # jeweler generated
16
16
  pkg
17
+ tmp
18
+
19
+ node_modules
17
20
 
18
21
  # Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
19
22
  #
@@ -58,3 +61,5 @@ gemfiles/*.lock
58
61
  /spec/dummy/app/assets/javascripts/routes.js
59
62
  /spec/dummy/logs
60
63
  /spec/dummy/tmp
64
+ node_modules
65
+
data/.nvmrc ADDED
@@ -0,0 +1 @@
1
+ 14
data/.travis.yml CHANGED
@@ -5,7 +5,6 @@ before_install:
5
5
  - gem install bundler # need for jruby and ruby-head
6
6
 
7
7
  rvm:
8
- - 2.3.1
9
8
  - 2.4.1
10
9
  - 2.5.3
11
10
  - 2.6.0
@@ -22,6 +21,8 @@ gemfile:
22
21
  - gemfiles/rails50_sprockets_3.gemfile
23
22
  - gemfiles/rails51_sprockets_3.gemfile
24
23
  - gemfiles/rails52_sprockets_3.gemfile
24
+ env:
25
+ TRAVIS_CI: true
25
26
 
26
27
  sudo: false
27
28
  dist: xenial
data/CHANGELOG.md CHANGED
@@ -1,5 +1,90 @@
1
1
  ## master
2
2
 
3
+ ## v2.2.0
4
+
5
+ * Use Rack Middleware to automatically update routes file in development [#288](https://github.com/railsware/js-routes/issues/288)
6
+ * 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)
7
+
8
+ ## v2.1.3
9
+
10
+ * Fix `default_url_options` bug. [#290](https://github.com/railsware/js-routes/issues/290)
11
+
12
+ ## v2.1.2
13
+
14
+ * Improve browser window object detection. [#287](https://github.com/railsware/js-routes/issues/287)
15
+
16
+ ## v2.1.1
17
+
18
+ * Added webpacker generator `./bin/rails generate js_routes:webpacker`
19
+ * Reorganized Readme to describe different setups with their pros and cons more clearly
20
+
21
+ ## v2.1.0
22
+
23
+ * Support typescript defintions file aka `routes.d.ts`. See [Readme.md](./Readme.md#definitions) for more information.
24
+
25
+ ## v2.0.8
26
+
27
+ * Forbid usage of `namespace` option if `module_type` is not `nil`. [#281](https://github.com/railsware/js-routes/issues/281).
28
+
29
+ ## v2.0.7
30
+
31
+ * Remove source map annotation from JS file. Fixes [#277](https://github.com/railsware/js-routes/issues/277)
32
+ * Generated file is not minified, so it is better to use app side bundler/compressor for source maps
33
+
34
+
35
+ ## v2.0.6
36
+
37
+ * Disable `namespace` option default for all envs [#278](https://github.com/railsware/js-routes/issues/278)
38
+
39
+ ## v2.0.5
40
+
41
+ * Fixed backward compatibility issue [#276](https://github.com/railsware/js-routes/issues/276)
42
+
43
+ ## v2.0.4
44
+
45
+ * Fixed backward compatibility issue [#275](https://github.com/railsware/js-routes/issues/275)
46
+
47
+ ## v2.0.3
48
+
49
+ * Fixed backward compatibility issue [#275](https://github.com/railsware/js-routes/issues/275)
50
+
51
+ ## v2.0.2
52
+
53
+ * Fixed backward compatibility issue [#274](https://github.com/railsware/js-routes/issues/274)
54
+
55
+ ## v2.0.1
56
+
57
+ * Fixed backward compatibility issue [#272](https://github.com/railsware/js-routes/issues/272)
58
+
59
+ ## v2.0.0
60
+
61
+ Version 2.0 has some breaking changes.
62
+ See [UPGRADE TO 2.0](./VERSION_2_UPGRADE.md) for guidance.
63
+
64
+ * `module_type` option support
65
+ * `documentation` option spport
66
+ * Migrated implementation to typescript
67
+ * ESM tree shaking support
68
+ * Support camel case `toParam` version of `to_param` property
69
+
70
+ ## v1.4.14
71
+
72
+ * Fix compatibility with UMD modules #237 [Comment](https://github.com/railsware/js-routes/issues/237#issuecomment-752754679)
73
+
74
+ ## v1.4.13
75
+
76
+ * Improve compatibility with node environment #269.
77
+ * Change default file location configuration to Webpacker if both Webpacker and Sprockets are loaded
78
+
79
+ ## v1.4.11
80
+
81
+ * Use app/javascript/routes.js as a default file location if app/javascript directory exists
82
+ * Add `default` export for better experience when used as es6 module
83
+
84
+ ## v1.4.10
85
+
86
+ * Require engine only when sprockets is loaded #257.
87
+
3
88
  ## v1.4.9
4
89
 
5
90
  * Allow to specify null namespace and receive routes as an object without assigning it anywhere #247
data/Rakefile CHANGED
@@ -12,7 +12,10 @@ require 'bundler/gem_tasks'
12
12
  require 'rspec/core'
13
13
  require 'rspec/core/rake_task'
14
14
  require 'appraisal'
15
- load "rails/tasks/routes.rake"
15
+ require 'rails/version'
16
+ if Rails.version < "6.1"
17
+ load "rails/tasks/routes.rake"
18
+ end
16
19
 
17
20
  RSpec::Core::RakeTask.new(:spec)
18
21
 
@@ -29,6 +32,6 @@ namespace :spec do
29
32
  draw_routes
30
33
  all_routes = Rails.application.routes.routes
31
34
  inspector = ActionDispatch::Routing::RoutesInspector.new(all_routes)
32
- puts inspector.format(ActionDispatch::Routing::ConsoleFormatter.new, ENV['CONTROLLER'])
35
+ puts inspector.format(ActionDispatch::Routing::ConsoleFormatter::Sheet.new)
33
36
  end
34
37
  end
data/Readme.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  Generates javascript file that defines all Rails named routes as javascript helpers
6
6
 
7
+ [UPGRADE TO 2.0](./VERSION_2_UPGRADE.md)
8
+
7
9
  ## Intallation
8
10
 
9
11
  Your Rails Gemfile:
@@ -12,9 +14,179 @@ Your Rails Gemfile:
12
14
  gem "js-routes"
13
15
  ```
14
16
 
15
- ### Basic Setup
17
+ ## Setup
18
+
19
+ There are 3 possible ways to setup JsRoutes:
20
+
21
+ * [Quick and easy](#quick-start)
22
+ * Uses Rack Middleware to automatically update routes locally
23
+ * Works great for a simple Rails application
24
+ * [Webpacker](#webpacker) automatic updates
25
+ * Requires ESM module system (the default)
26
+ * Doesn't support typescript definitions
27
+ * [Advanced Setup](#advanced-setup)
28
+ * Allows very custom setups
29
+ * [Sprockets](#sprockets) legacy
30
+ * Deprecated and not recommended for modern apps
31
+
32
+ <div id='quick-start'></div>
33
+
34
+ ### Quick Start
35
+
36
+ Setup [Rack Middleware](https://guides.rubyonrails.org/rails_on_rack.html#action-dispatcher-middleware-stack) to automatically generate and maintain `routes.js` file and corresponding [Typescript definitions](https://www.typescriptlang.org/docs/handbook/declaration-files/templates/module-d-ts.html) `routes.d.ts`:
37
+
38
+ Run:
39
+
40
+ ``` sh
41
+ rails generate js_routes:middleware
42
+ ```
43
+
44
+
45
+ <div id='webpacker'></div>
46
+
47
+ ### Webpacker + automatic updates - Typescript
48
+
49
+ **IMPORTANT**: this setup doesn't support IDE autocompletion with [Typescript](https://www.typescriptlang.org/docs/handbook/declaration-files/templates/module-d-ts.html)
50
+
51
+
52
+ #### Use a Generator
53
+
54
+ Run a command:
55
+
56
+ ``` sh
57
+ ./bin/rails generate js_routes:webpacker
58
+ ```
59
+
60
+ #### Setup manually
61
+
62
+ The routes files can be automatically updated without `rake` task being called manually.
63
+ It requires [rails-erb-loader](https://github.com/usabilityhub/rails-erb-loader) npm package to work.
64
+
65
+ Add `erb` loader to webpacker:
66
+
67
+ ``` sh
68
+ yarn add rails-erb-loader
69
+ rm -f app/javascript/routes.js # delete static file if any
70
+ ```
71
+
72
+ Create webpack ERB config `config/webpack/loaders/erb.js`:
73
+
74
+ ``` javascript
75
+ module.exports = {
76
+ module: {
77
+ rules: [
78
+ {
79
+ test: /\.erb$/,
80
+ enforce: 'pre',
81
+ loader: 'rails-erb-loader'
82
+ },
83
+ ]
84
+ }
85
+ };
86
+ ```
87
+
88
+ Enable `erb` extension in `config/webpack/environment.js`:
89
+
90
+ ``` javascript
91
+ const erb = require('./loaders/erb')
92
+ environment.loaders.append('erb', erb)
93
+ ```
94
+
95
+ Create routes file `app/javascript/routes.js.erb`:
96
+
97
+ ``` erb
98
+ <%= JsRoutes.generate() %>
99
+ ```
100
+
101
+ Use routes wherever you need them `app/javascript/packs/application.js`:
102
+
103
+ ``` javascript
104
+ import * as Routes from 'routes.js.erb';
105
+ window.Routes = Routes;
106
+ ```
107
+
108
+ <div id='advanced-setup'></div>
109
+
110
+ ### Advanced Setup
111
+
112
+ **IMPORTANT**: that this setup requires the JS routes file to be updates manually
113
+
114
+ You can run every time you want to generate a routes file:
115
+
116
+ ``` sh
117
+ rake js:routes
118
+ # OR for typescript support
119
+ rake js:routes:typescript
120
+ ```
121
+
122
+ In case you need multiple route files for different parts of your application, you have to create the files manually.
123
+ If your application has an `admin` and an `application` namespace for example:
124
+
125
+ ``` erb
126
+ // app/javascript/admin/routes.js.erb
127
+ <%= JsRoutes.generate(include: /admin/) %>
128
+ ```
129
+
130
+ ``` erb
131
+ // app/javascript/customer/routes.js.erb
132
+ <%= JsRoutes.generate(exclude: /admin/) %>
133
+ ```
134
+
135
+ You can manipulate the generated helper manually by injecting ruby into javascript:
136
+
137
+ ``` erb
138
+ export const routes = <%= JsRoutes.generate(module_type: nil, namespace: nil) %>
139
+ ```
140
+
141
+ If you want to generate the routes files outside of the asset pipeline, you can use `JsRoutes.generate!`:
142
+
143
+ ``` ruby
144
+ path = Rails.root.join("app/javascript")
145
+
146
+ JsRoutes.generate!("#{path}/app_routes.js", exclude: [/^admin_/, /^api_/])
147
+ JsRoutes.generate!("#{path}/adm_routes.js", include: /^admin_/)
148
+ JsRoutes.generate!("#{path}/api_routes.js", include: /^api_/, default_url_options: {format: "json"})
149
+ ```
16
150
 
17
- Require JsRoutes in `application.js` or other bundle
151
+ <div id='definitions'></div>
152
+
153
+ #### Typescript Definitions
154
+
155
+ JsRoutes has typescript support out of the box.
156
+
157
+ Restrictions:
158
+
159
+ * Only available if `module_type` is set to `ESM` (strongly recommended and default).
160
+ * Webpacker Automatic Updates are not available because typescript compiler can not be configured to understand `.erb` extensions.
161
+
162
+ For the basic setup of typscript definitions see [Quick Start](#quick-start) setup.
163
+ More advanced setup would involve calling manually:
164
+
165
+ ``` ruby
166
+ JsRoutes.definitions! # to output to file
167
+ # or
168
+ JsRoutes.definitions # to output to string
169
+ ```
170
+
171
+ Even more advanced setups can be achieved by setting `module_type` to `DTS` inside [configuration](#module_type)
172
+ which will cause any `JsRoutes` instance to generate defintions instead of routes themselves.
173
+
174
+ <div id="sprockets"></div>
175
+
176
+ ### Sprockets (Deprecated)
177
+
178
+ If you are using [Sprockets](https://github.com/rails/sprockets-rails) you may configure js-routes in the following way.
179
+
180
+ Setup the initializer (e.g. `config/initializers/js_routes.rb`):
181
+
182
+ ``` ruby
183
+ JsRoutes.setup do |config|
184
+ config.module_type = nil
185
+ config.namespace = 'Routes'
186
+ end
187
+ ```
188
+
189
+ Require JsRoutes in `app/assets/javascripts/application.js` or other bundle
18
190
 
19
191
  ``` js
20
192
  //= require js-routes
@@ -30,9 +202,9 @@ This cache is not flushed on server restart in development environment.
30
202
 
31
203
  **Important:** If routes.js file is not updated after some configuration change you need to run this rake task again.
32
204
 
33
- ### Configuration
205
+ ## Configuration
34
206
 
35
- You can configure JsRoutes in two main ways. Either with an initializer (e.g. `config/initializers/jsroutes.rb`):
207
+ You can configure JsRoutes in two main ways. Either with an initializer (e.g. `config/initializers/js_routes.rb`):
36
208
 
37
209
  ``` ruby
38
210
  JsRoutes.setup do |config|
@@ -40,123 +212,110 @@ JsRoutes.setup do |config|
40
212
  end
41
213
  ```
42
214
 
43
- Or dynamically in JavaScript, although not all configuration options are supported:
215
+ Or dynamically in JavaScript, although only [Formatter Options](#formatter-options) are supported:
44
216
 
45
217
  ``` js
218
+ import * as Routes from 'routes'
46
219
  Routes.configure({
47
220
  option: value
48
221
  });
49
222
  Routes.config(); // current config
50
223
  ```
51
224
 
52
- Available options:
225
+ ### Available Options
53
226
 
54
- * `default_url_options` - default parameters used when generating URLs
55
- * Option is configurable at JS level with `Routes.configure()`
56
- * Example: {:format => "json", :trailing\_slash => true, :protocol => "https", :subdomain => "api", :host => "example.com", :port => 3000}
57
- * Default: {}
227
+ #### Generator Options
228
+
229
+ Options to configure JavaScript file generator. These options are only available in Ruby context but not JavaScript.
230
+
231
+ <div id='module-type'></div>
232
+
233
+ * `module_type` - JavaScript module type for generated code. [Article](https://dev.to/iggredible/what-the-heck-are-cjs-amd-umd-and-esm-ikm)
234
+ * Options: `ESM`, `UMD`, `CJS`, `AMD`, `DTS`, `nil`.
235
+ * Default: `ESM`
236
+ * `nil` option can be used in case you don't want generated code to export anything.
237
+ * `documentation` - specifies if each route should be annotated with [JSDoc](https://jsdoc.app/) comment
238
+ * Default: `true`
58
239
  * `exclude` - Array of regexps to exclude from routes.
59
- * Default: []
240
+ * Default: `[]`
60
241
  * The regexp applies only to the name before the `_path` suffix, eg: you want to match exactly `settings_path`, the regexp should be `/^settings$/`
61
242
  * `include` - Array of regexps to include in routes.
62
- * Default: []
243
+ * Default: `[]`
63
244
  * The regexp applies only to the name before the `_path` suffix, eg: you want to match exactly `settings_path`, the regexp should be `/^settings$/`
64
245
  * `namespace` - global object used to access routes.
246
+ * Only available if `module_type` option is set to `nil`.
65
247
  * Supports nested namespace like `MyProject.routes`
66
- * Default: `Routes`
67
- * `prefix` - String representing a url path to prepend to all paths.
68
- * Option is configurable at JS level with `Routes.configure()`
69
- * Example: `http://yourdomain.com`. This will cause route helpers to generate full path only.
70
- * Default: `Rails.application.config.relative_url_root`
71
- * `camel_case` (version >= 0.8.8) - Generate camel case route names.
72
- * Default: false
73
- * `url_links` (version >= 0.8.9) - Generate `*_url` helpers (in addition to the default `*_path` helpers).
74
- * Example: true
75
- * Default: false
248
+ * Default: `nil`
249
+ * `camel_case` - specifies if route helpers should be generated in camel case instead of underscore case.
250
+ * Default: `false`
251
+ * `url_links` - specifies if `*_url` helpers should be generated (in addition to the default `*_path` helpers).
252
+ * Default: `false`
76
253
  * Note: generated URLs will first use the protocol, host, and port options specified in the route definition. Otherwise, the URL will be based on the option specified in the `default_url_options` config. If no default option has been set, then the URL will fallback to the current URL based on `window.location`.
77
- * `compact` (version > 0.9.9) - Remove `_path` suffix in path routes(`*_url` routes stay untouched if they were enabled)
78
- * Default: false
254
+ * `compact` - Remove `_path` suffix in path routes(`*_url` routes stay untouched if they were enabled)
255
+ * Default: `false`
79
256
  * Sample route call when option is set to true: Routes.users() => `/users`
80
- * `serializer` (version >= 1.1.0) - Puts a JS function here that serializes a Javascript Hash object into URL paramters: `{a: 1, b: 2} => "a=1&b=2"`.
81
- * Default: `nil`. Uses built-in serializer
82
- * Option is configurable at JS level with `Routes.configure()`
83
- * Example: `jQuery.param` - use jQuery's serializer algorithm. You can attach serialize function from your favorite AJAX framework.
84
- * Example: `MyApp.custom_serialize` - use completely custom serializer of your application.
85
-
86
- * `special_options_key` - a special key that helps JsRoutes to destinguish serialized model from options hash
87
- * This option is required because JS doesn't provide a difference between an object and a hash
88
- * Option is configurable at JS level with `Routes.configure()`
89
- * Default: `_options`
90
257
  * `application` - a key to specify which rails engine you want to generate routes too.
91
258
  * This option allows to only generate routes for a specific rails engine, that is mounted into routes instead of all Rails app routes
92
259
  * Default: `Rails.application`
260
+ * `file` - a file location where generated routes are stored
261
+ * Default: `app/javascript/routes.js` if setup with Webpacker, otherwise `app/assets/javascripts/routes.js` if setup with Sprockets.
93
262
 
94
- ### Very Advanced Setup
263
+ <div id="formatter-options"></div>
95
264
 
96
- In case you need multiple route files for different parts of your application, you have to create the files manually.
97
- If your application has an `admin` and an `application` namespace for example:
265
+ #### Formatter Options
98
266
 
99
- ```
100
- # app/assets/javascripts/admin/routes.js.erb
101
- <%= JsRoutes.generate(namespace: "AdminRoutes", include: /admin/) %>
267
+ Options to configure routes formatting. These options are available both in Ruby and JavaScript context.
102
268
 
103
- # app/assets/javascripts/admin.js.coffee
104
- #= require admin/routes
105
- ```
106
-
107
- ```
108
- # app/assets/javascripts/application/routes.js.erb
109
- <%= JsRoutes.generate(namespace: "AppRoutes", exclude: /admin/) %>
110
-
111
- # app/assets/javascripts/application.js.coffee
112
- #= require application/routes
113
- ```
114
-
115
- In order to generate the routes JS code to a string:
269
+ * `default_url_options` - default parameters used when generating URLs
270
+ * Example: `{format: "json", trailing_slash: true, protocol: "https", subdomain: "api", host: "example.com", port: 3000}`
271
+ * Default: `{}`
272
+ * `prefix` - string that will prepend any generated URL. Usually used when app URL root includes a path component.
273
+ * Example: `/rails-app`
274
+ * Default: `Rails.application.config.relative_url_root`
275
+ * `serializer` - a JS function that serializes a Javascript Hash object into URL paramters like `{a: 1, b: 2} => "a=1&b=2"`.
276
+ * Default: `nil`. Uses built-in serializer compatible with Rails
277
+ * Example: `jQuery.param` - use jQuery's serializer algorithm. You can attach serialize function from your favorite AJAX framework.
278
+ * Example: `function (object) { ... }` - use completely custom serializer of your application.
279
+ * `special_options_key` - a special key that helps JsRoutes to destinguish serialized model from options hash
280
+ * This option exists because JS doesn't provide a difference between an object and a hash
281
+ * Default: `_options`
116
282
 
117
- ```ruby
118
- routes_js = JsRoutes.generate(options)
119
- ```
120
283
 
121
- If you want to generate the routes files outside of the asset pipeline, you can use `JsRoutes.generate!`:
284
+ ## Usage
122
285
 
123
- ``` ruby
124
- path = "app/assets/javascripts"
125
- JsRoutes.generate!("#{path}/app_routes.js", :namespace => "AppRoutes", :exclude => [/^admin_/, /^api_/])
126
- JsRoutes.generate!("#{path}/adm_routes.js", :namespace => "AdmRoutes", :include => /^admin_/)
127
- JsRoutes.generate!("#{path}/api_routes.js", :namespace => "ApiRoutes", :include => /^api_/, :default_url_options => {:format => "json"})
128
- ```
286
+ Configuration above will create a nice javascript file with `Routes` object that has all the rails routes available:
129
287
 
130
- ### Rails relative URL root
288
+ ``` js
289
+ import * as Routes from 'routes';
131
290
 
132
- If you've installed your application in a sub-path or sub-URI of your server instead of at the root, you need to set the `RAILS_RELATIVE_URL_ROOT` environment variable to the correct path prefix for your application when you precompile assets. Eg., if your application's base URL is "https://appl.example.com/Application1", the command to precompile assets would be:
133
- ```
134
- RAILS_RELATIVE_URL_ROOT=/Application1 RAILS_ENV=production bundle exec rake assets:precompile
135
- ```
136
- The environment variable is only needed for precompilation of assets, at any other time (eg. when assets are compiled on-the-fly as in the development environment) Rails will set the relative URL root correctly on it's own.
291
+ Routes.users_path()
292
+ // => "/users"
137
293
 
294
+ Routes.user_path(1)
295
+ // => "/users/1"
296
+
297
+ Routes.user_path(1, {format: 'json'})
298
+ // => "/users/1.json"
138
299
 
139
- ## Usage
300
+ Routes.user_path(1, {anchor: 'profile'})
301
+ // => "/users/1#profile"
140
302
 
141
- Configuration above will create a nice javascript file with `Routes` object that has all the rails routes available:
303
+ Routes.new_user_project_path(1, {format: 'json'})
304
+ // => "/users/1/projects/new.json"
142
305
 
143
- ``` js
144
- Routes.users_path() // => "/users"
145
- Routes.user_path(1) // => "/users/1"
146
- Routes.user_path(1, {format: 'json'}) // => "/users/1.json"
147
- Routes.user_path(1, {anchor: 'profile'}) // => "/users/1#profile"
148
- Routes.new_user_project_path(1, {format: 'json'}) // => "/users/1/projects/new.json"
149
- Routes.user_project_path(1,2, {q: 'hello', custom: true}) // => "/users/1/projects/2?q=hello&custom=true"
150
- Routes.user_project_path(1,2, {hello: ['world', 'mars']}) // => "/users/1/projects/2?hello%5B%5D=world&hello%5B%5D=mars"
151
- ```
306
+ Routes.user_project_path(1,2, {q: 'hello', custom: true})
307
+ // => "/users/1/projects/2?q=hello&custom=true"
152
308
 
153
- Using serialized object as route function arguments:
309
+ Routes.user_project_path(1,2, {hello: ['world', 'mars']})
310
+ // => "/users/1/projects/2?hello%5B%5D=world&hello%5B%5D=mars"
154
311
 
155
- ``` js
156
312
  var google = {id: 1, name: "Google"};
157
- Routes.company_path(google) // => "/companies/1"
313
+ Routes.company_path(google)
314
+ // => "/companies/1"
315
+
158
316
  var google = {id: 1, name: "Google", to_param: "google"};
159
- Routes.company_path(google) // => "/companies/google"
317
+ Routes.company_path(google)
318
+ // => "/companies/google"
160
319
  ```
161
320
 
162
321
  In order to make routes helpers available globally:
@@ -165,7 +324,7 @@ In order to make routes helpers available globally:
165
324
  jQuery.extend(window, Routes)
166
325
  ```
167
326
 
168
- ## Get spec of routes and required params
327
+ ### Get spec of routes and required params
169
328
 
170
329
  Possible to get `spec` of route by function `toString`:
171
330
 
@@ -181,11 +340,11 @@ This function allow to get the same `spec` for route, if you will get string rep
181
340
  '' + Routes.user_path // => "/users/:id(.:format)"
182
341
  ```
183
342
 
184
- Route function also contain inside attribute `required_params` required param names as array:
343
+ Route function also contain method `requiredParams` inside which returns required param names array:
185
344
 
186
345
  ```js
187
- Routes.users_path.required_params // => []
188
- Routes.user_path.required_params // => ['id']
346
+ Routes.users_path.requiredParams() // => []
347
+ Routes.user_path.requiredParams() // => ['id']
189
348
  ```
190
349
 
191
350
 
@@ -206,21 +365,37 @@ Routes.company_project_path({company_id: 1, id: 2, _options: true}) // => "/comp
206
365
 
207
366
  ## What about security?
208
367
 
209
- JsRoutes itself do not have security holes. It makes URLs
210
- without access protection more reachable by potential attacker.
211
- In order to prevent this use `:exclude` option for sensitive urls like `/admin_/`
212
-
213
- ## JsRoutes and Heroku
368
+ JsRoutes itself does not have security holes.
369
+ It makes URLs without access protection more reachable by potential attacker.
370
+ If that is an issue for you, you may use one of the following solutions:
214
371
 
215
- When using this setup on Heroku, it is impossible to use the asset pipeline. You should use the "Very Advanced Setup" schema in this case.
372
+ ### Explicit Import + ESM Tree shaking
216
373
 
217
- For example create routes.js.erb in assets folder with needed content:
374
+ Make sure `module_type` is set to `ESM` (the default) and JS files import only required routes into the file like:
218
375
 
219
- ``` erb
220
- <%= JsRoutes.generate(options) %>
376
+ ``` javascript
377
+ import {
378
+ inbox_path,
379
+ inboxes_path,
380
+ inbox_message_path,
381
+ inbox_attachment_path,
382
+ user_path,
383
+ } from 'routes.js.erb'
221
384
  ```
222
385
 
223
- This should just work.
386
+ Such import structure allows for moddern JS bundlers like [Webpack](https://webpack.js.org/) to only include explicitly imported routes into JS bundle file.
387
+ See [Tree Shaking](https://webpack.js.org/guides/tree-shaking/) for more information.
388
+
389
+ ### Exclude option
390
+
391
+ Split your routes into multiple files related to each section of your website like:
392
+
393
+ ``` javascript
394
+ // admin-routes.js.erb
395
+ <%= JsRoutes.generate(include: /^admin_/) %>
396
+ // app-routes.js.erb
397
+ <%= JsRoutes.generate(exclude: /^admin_/) %>
398
+ ```
224
399
 
225
400
  ## Advantages over alternatives
226
401
 
@@ -228,6 +403,7 @@ There are some alternatives available. Most of them has only basic feature and d
228
403
  Advantages of this one are:
229
404
 
230
405
  * Rails 4,5,6 support
406
+ * [ESM Tree shaking](https://webpack.js.org/guides/tree-shaking/) support
231
407
  * Rich options set
232
408
  * Full rails compatibility
233
409
  * Support Rails `#to_param` convention for seo optimized paths