railbus 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.editorconfig +33 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +227 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/railbus.rb +28 -0
- data/lib/railbus/route_set.rb +114 -0
- data/lib/railbus/route_set_presenter.rb +11 -0
- data/lib/railbus/templates/js.erb +92 -0
- data/lib/railbus/version.rb +3 -0
- data/railbus.gemspec +34 -0
- metadata +102 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3a4d4f90743b019f021dce043615b79204496078835955c549aee7e31238aaad
|
4
|
+
data.tar.gz: d0d414564db34c8c3a12ee40a060333f208da3443754fba9af7c4943d3ce3843
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ffaadfde8d0fc1367f75a6b4ddd49d6bf399269ccb6e92fde68d5b712fb21f3fc657a952e4129739ef40dabf34f471e03f0a0e69ce40d8596806d6b220c7bfc4
|
7
|
+
data.tar.gz: 2e6b62c58abfa3fe253d387eb3d4d863998784b1f11734e8fa133db09c5493b85705c02b4106bc4a022c17fbbae5d99ef7d2281a7cdc9323d93e78cb959db4c3
|
data/.editorconfig
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
root = true
|
2
|
+
|
3
|
+
[*.{rb,md,editorconfig,js,rake,erb}]
|
4
|
+
charset = utf-8
|
5
|
+
end_of_line = lf
|
6
|
+
insert_final_newline = true
|
7
|
+
indent_style = space
|
8
|
+
indent_size = 2
|
9
|
+
max_line_length = 80
|
10
|
+
trim_trailing_whitespace = true
|
11
|
+
|
12
|
+
[{Gemfile*,Rakefile,.git*,.rspec}]
|
13
|
+
charset = utf-8
|
14
|
+
end_of_line = lf
|
15
|
+
insert_final_newline = true
|
16
|
+
indent_style = space
|
17
|
+
indent_size = 2
|
18
|
+
max_line_length = 80
|
19
|
+
trim_trailing_whitespace = true
|
20
|
+
|
21
|
+
[*.md]
|
22
|
+
indent_size = unset
|
23
|
+
max_line_length = unset
|
24
|
+
trim_trailing_whitespace = false
|
25
|
+
|
26
|
+
[{{.git,bin,tmp,vendor}/**,*.lock}]
|
27
|
+
charset = unset
|
28
|
+
end_of_line = unset
|
29
|
+
insert_final_newline = unset
|
30
|
+
indent_style = unset
|
31
|
+
indent_size = unset
|
32
|
+
max_line_length = unset
|
33
|
+
trim_trailing_whitespace = unset
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2020 Evgeniy Nochevnov
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,227 @@
|
|
1
|
+
# Railbus
|
2
|
+
|
3
|
+
Do you want to use autogenerated set of Rails application routes in your JavaScript files?
|
4
|
+
|
5
|
+
Do you want to make requests to your routes from JS with human-readable names like `create_news`, `update_message`?
|
6
|
+
|
7
|
+
Here comes Railbus to you.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'railbus'
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle install
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install railbus
|
24
|
+
|
25
|
+
To use it with Webpack, create `*.js.erb` file in `app/javascript`
|
26
|
+
(e.g. `lib/routes.js.erb`):
|
27
|
+
|
28
|
+
```erb
|
29
|
+
/* rails-erb-loader-dependencies ../config/routes */
|
30
|
+
<%= Railbus.generate %>
|
31
|
+
```
|
32
|
+
|
33
|
+
And the last step, require this file in your `.js` files where you want to use application routes.
|
34
|
+
|
35
|
+
```js
|
36
|
+
import Routes from 'lib/routes'
|
37
|
+
```
|
38
|
+
|
39
|
+
## Usage
|
40
|
+
|
41
|
+
In short:
|
42
|
+
|
43
|
+
1. See output of `rails routes`, it includes route names. You may use these names in JS as functions for XHR requests.
|
44
|
+
2. Append `_path` to a route name to get its URL.
|
45
|
+
|
46
|
+
Route names in JS depend on route names in Rails:
|
47
|
+
|
48
|
+
Action name | HTTP method | Request function | Path function
|
49
|
+
------------|-------------|------------------------|----------------------------
|
50
|
+
index | GET | {plural_name} | {plural_name}_path
|
51
|
+
show | GET | {singular_name} | {singular_name}_path
|
52
|
+
new | GET | new_{singular_name} | new_{singular_name}_path
|
53
|
+
edit | GET | edit_{singular_name} | edit_{singular_name}_path
|
54
|
+
create | POST | create_{singular_name} | create_{singular_name}_path
|
55
|
+
update | PUT/PATCH | update_{singular_name} | update_{singular_name}_path
|
56
|
+
destroy | DELETE | delete_{singular_name} | delete_{singular_name}_path
|
57
|
+
|
58
|
+
### Functions' arguments
|
59
|
+
|
60
|
+
Here `String or Number, ...` represents values used in paths, e.g.
|
61
|
+
`:id`, `:category_id` (zero, one or more params).
|
62
|
+
|
63
|
+
And `...path_params` means hash-like object with values for paths, e.g.
|
64
|
+
`{id: 123, category_id: 56}` (zero, one or more params).
|
65
|
+
|
66
|
+
`data` means request body (payload), it can be hash-like object, `FormData` and so on, its allowed types depend on XHR library.
|
67
|
+
|
68
|
+
All arguments are optional.
|
69
|
+
|
70
|
+
```js
|
71
|
+
// Request `index`, `show`, `new`, `edit`, `destroy` actions.
|
72
|
+
({format: String, ...path_params, ...url_options})
|
73
|
+
// Or:
|
74
|
+
(String or Number, ..., {format: String, ...url_options})
|
75
|
+
|
76
|
+
// Request `create` and `update` actions.
|
77
|
+
({format: String, ...path_params, ...url_options}, data)
|
78
|
+
// Or:
|
79
|
+
(String or Number, ..., {format: String, ...url_options}, data)
|
80
|
+
|
81
|
+
// Get path for any action (does not include query string starting with '?').
|
82
|
+
({format: String, ...path_params})
|
83
|
+
// Or:
|
84
|
+
(String or Number, ..., {format: String})
|
85
|
+
```
|
86
|
+
|
87
|
+
### Configuration
|
88
|
+
|
89
|
+
By default Railbus generates functions for all routes defined
|
90
|
+
in `Rails.application` and these functions use `axios`. You may change it:
|
91
|
+
|
92
|
+
```js
|
93
|
+
<%=
|
94
|
+
Railbus.generate(
|
95
|
+
# Here `YourApp::Engine` inherits `Rails::Engine`.
|
96
|
+
# Default: `Rails.application`.
|
97
|
+
app: YourApp::Engine,
|
98
|
+
|
99
|
+
# 'axios' or the name of function defined or imported in this file.
|
100
|
+
# Default: 'axios'.
|
101
|
+
client: 'request_api',
|
102
|
+
|
103
|
+
# Include only these route paths that start with '/api'.
|
104
|
+
# Empty array: include all routes (default).
|
105
|
+
include: [%r{^/api}],
|
106
|
+
|
107
|
+
# Exclude all route paths matching regexpes.
|
108
|
+
# Empty array: do not exclude any routes (default).
|
109
|
+
exclude: [/edit|new/]
|
110
|
+
)
|
111
|
+
%>
|
112
|
+
|
113
|
+
import axios from 'axios';
|
114
|
+
const axios_api = axios.create({
|
115
|
+
baseURL: `${document.location.origin}/api/`
|
116
|
+
})
|
117
|
+
|
118
|
+
function request_api(route, params) {
|
119
|
+
return axios_api.request({
|
120
|
+
url: params.path,
|
121
|
+
method: route.verb,
|
122
|
+
params: params.url_options,
|
123
|
+
data: params.data
|
124
|
+
})
|
125
|
+
}
|
126
|
+
```
|
127
|
+
|
128
|
+
### Examples
|
129
|
+
|
130
|
+
Let's take these routes as an example:
|
131
|
+
|
132
|
+
```ruby
|
133
|
+
resources :news do
|
134
|
+
resources :images, only: %w[index show create update destroy]
|
135
|
+
end
|
136
|
+
resources :messages, only: %w[new create]
|
137
|
+
namespace :my do
|
138
|
+
resources :favourites, only: %w[index show create update destroy]
|
139
|
+
end
|
140
|
+
```
|
141
|
+
|
142
|
+
To make XHR requests with promises you may do this in JS
|
143
|
+
([axios](https://github.com/axios/axios) required):
|
144
|
+
|
145
|
+
```js
|
146
|
+
import Routes from 'lib/routes'
|
147
|
+
|
148
|
+
// Request all favourites and print to console. Note: using namespace `my`.
|
149
|
+
// It will call `My::FavouritesController#index`.
|
150
|
+
// Path: '/my/favourites'.
|
151
|
+
Routes.my_favourites().then(response => console.log(response.data))
|
152
|
+
|
153
|
+
// Request all news and print to console.
|
154
|
+
// String `index` appended to distinguish `index` and `show` actions.
|
155
|
+
// It will call `NewsController#index`.
|
156
|
+
// Path: '/news'.
|
157
|
+
Routes.news_index().then(response => console.log(response.data))
|
158
|
+
|
159
|
+
// Request all news filtered by date, and print to console.
|
160
|
+
// `NewsController#index` with param `date` in query string (GET).
|
161
|
+
// Path: '/news' with query string '?date=2020-12-31'.
|
162
|
+
Routes.news_index({date: '2020-12-31'}).then(response => console.log(response.data))
|
163
|
+
|
164
|
+
// Request one news and print to console.
|
165
|
+
// `NewsController#show` with param `id` = 327 (GET).
|
166
|
+
// Path: '/news/327'.
|
167
|
+
Routes.news(327).then(response => console.log(response.data))
|
168
|
+
// Or
|
169
|
+
Routes.news({id: 327}).then(response => console.log(response.data))
|
170
|
+
|
171
|
+
// Specify format (for example, '.json').
|
172
|
+
// `NewsController#show` with param `id` = 327 (GET) and `format` = 'json'.
|
173
|
+
// Path: '/news/327.json'.
|
174
|
+
Routes.news(327, {format: 'json'}).then(response => console.log(response.data))
|
175
|
+
// Or
|
176
|
+
Routes.news({id: 327, format: 'json'}).then(response => console.log(response.data))
|
177
|
+
|
178
|
+
// Create news with given title.
|
179
|
+
// `NewsController#create` with param `title` (POST).
|
180
|
+
Routes.create_news({title: 'Bears showed up in Tomsk'}).then(response => console.log(response.data))
|
181
|
+
|
182
|
+
// Create message with given title. Note: `message`, singular form.
|
183
|
+
// `MessagesController#create` with params `body`, `to` (POST).
|
184
|
+
Routes.create_message({body: 'Fantastic!', to: 23}).then(response => console.log(response.data))
|
185
|
+
|
186
|
+
// Create message with given title. Note: using namespace `my`.
|
187
|
+
// `My::FavouritesController#create` with param `url` (POST).
|
188
|
+
Routes.create_my_favourite({url: 'https://best.site'}).then(response => console.log(response.data))
|
189
|
+
|
190
|
+
// Attach an image to the news.
|
191
|
+
// `ImageController#create` with param `news_id` = 41 (GET), `blob` (POST).
|
192
|
+
Routes.create_news_image(41, {blob: file})
|
193
|
+
|
194
|
+
// Get URL for `create` action.
|
195
|
+
Routes.create_my_favourite_path() // => 'my/favourites'
|
196
|
+
```
|
197
|
+
|
198
|
+
## Development
|
199
|
+
|
200
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
201
|
+
|
202
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
203
|
+
|
204
|
+
TODO:
|
205
|
+
|
206
|
+
- Support [fetch](https://developer.mozilla.org/ru/docs/Web/API/Fetch_API/Using_Fetch)
|
207
|
+
- Tests
|
208
|
+
|
209
|
+
## Contributing
|
210
|
+
|
211
|
+
Bug reports and pull requests are welcome on GitHub at [github.com/crosspath/railbus](https://github.com/crosspath/railbus).
|
212
|
+
|
213
|
+
Please do not change version number in pull requests.
|
214
|
+
|
215
|
+
## Alternative solutions
|
216
|
+
|
217
|
+
1. [rswag](https://github.com/rswag/rswag) +
|
218
|
+
[swagger-js](https://github.com/swagger-api/swagger-js) +
|
219
|
+
your integration specs (tests)
|
220
|
+
2. [railsware/js-routes](https://github.com/railsware/js-routes)
|
221
|
+
3. [mtrpcic/js-routes](https://github.com/mtrpcic/js-routes)
|
222
|
+
4. [less-js-routes](https://github.com/stevenbristol/less-js-routes)
|
223
|
+
5. [js_named_routes](https://github.com/jsierles/js_named_routes)
|
224
|
+
|
225
|
+
## License
|
226
|
+
|
227
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "railbus"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/lib/railbus.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'erubi'
|
3
|
+
require 'active_support'
|
4
|
+
|
5
|
+
require_relative 'railbus/version'
|
6
|
+
require_relative 'railbus/route_set'
|
7
|
+
require_relative 'railbus/route_set_presenter'
|
8
|
+
|
9
|
+
module Railbus
|
10
|
+
module_function
|
11
|
+
|
12
|
+
def generate(
|
13
|
+
app: Rails.application,
|
14
|
+
client: 'axios',
|
15
|
+
include: [],
|
16
|
+
exclude: []
|
17
|
+
)
|
18
|
+
route_set = RouteSet.new(app, include, exclude)
|
19
|
+
routes_json = Railbus::RouteSetPresenter.to_h(route_set).to_json
|
20
|
+
|
21
|
+
js_template = File.join(__dir__, 'railbus', 'templates', 'js.erb')
|
22
|
+
erb_engine = Erubi::Engine.new(File.read(js_template))
|
23
|
+
|
24
|
+
# Template uses `routes_json`, `client`
|
25
|
+
client = client.to_s
|
26
|
+
eval(erb_engine.src)
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
class Railbus::RouteSet
|
2
|
+
# Example:
|
3
|
+
# get, /users/:id, ['/users/', {a: 'id'}], ['id'], user
|
4
|
+
Route = Struct.new(:verb, :path, :parts, :required, :name)
|
5
|
+
|
6
|
+
%w[post patch put].each do |word|
|
7
|
+
Route.define_method("#{word}?") { verb == word }
|
8
|
+
end
|
9
|
+
|
10
|
+
MAP_NAMES = {
|
11
|
+
'post' => 'create_',
|
12
|
+
'put' => 'update_',
|
13
|
+
'patch' => 'update_',
|
14
|
+
'delete' => 'destroy_'
|
15
|
+
}
|
16
|
+
|
17
|
+
attr_reader :paths
|
18
|
+
|
19
|
+
def initialize(app, include, exclude)
|
20
|
+
@paths = add_route_names(paths_for_app(app, include, exclude))
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def paths_for_app(app, include, exclude)
|
26
|
+
app.routes.set.routes.map do |route|
|
27
|
+
formatter = route.instance_variable_get(:@path_formatter)
|
28
|
+
route_parts = parts_combined(formatter.instance_variable_get(:@parts))
|
29
|
+
|
30
|
+
path = join_parts(route_parts)
|
31
|
+
next nil unless include_path?(path, include, exclude)
|
32
|
+
|
33
|
+
Route.new(
|
34
|
+
route.verb.downcase,
|
35
|
+
path,
|
36
|
+
route_parts,
|
37
|
+
required_params(route_parts),
|
38
|
+
route.name
|
39
|
+
)
|
40
|
+
end.compact
|
41
|
+
end
|
42
|
+
|
43
|
+
def parts_combined(parts)
|
44
|
+
parts.reduce([]) do |a, pt|
|
45
|
+
e = parts_element(pt)
|
46
|
+
next a if e.empty?
|
47
|
+
if a.empty?
|
48
|
+
a = [e]
|
49
|
+
elsif a[-1].respond_to?(:<<) && e.respond_to?(:<<)
|
50
|
+
# Both vars are strings -> concat them.
|
51
|
+
a[-1] << e
|
52
|
+
else
|
53
|
+
a << e
|
54
|
+
end
|
55
|
+
a
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def parts_element(part)
|
60
|
+
if part.respond_to?(:name)
|
61
|
+
# Is a path parameter (e.g. `:id`).
|
62
|
+
{a: part.name}
|
63
|
+
else
|
64
|
+
# Is a `format` parameter -> skip it.
|
65
|
+
# Otherwise it is a string.
|
66
|
+
(part.respond_to?(:evaluate) ? '' : part).dup
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def join_parts(route_parts)
|
71
|
+
route_parts.map { |x| x.respond_to?(:<<) ? x : ":#{x[:a]}" }.join
|
72
|
+
end
|
73
|
+
|
74
|
+
def required_params(route_parts)
|
75
|
+
route_parts.reject { |x| x.respond_to?(:<<) }.map { |x| x[:a] }
|
76
|
+
end
|
77
|
+
|
78
|
+
def include_path?(path, include, exclude)
|
79
|
+
return false if !include.empty? && include.none? { |re| path =~ re }
|
80
|
+
return false if exclude.any? { |re| path =~ re }
|
81
|
+
true
|
82
|
+
end
|
83
|
+
|
84
|
+
def add_route_names(paths)
|
85
|
+
paths.group_by(&:path).flat_map do |_, routes|
|
86
|
+
name = routes.find(&:name)&.name
|
87
|
+
if name
|
88
|
+
routes.reject!(&:patch?) if routes.find(&:put?)
|
89
|
+
routes.map do |route|
|
90
|
+
route.name ||= "#{MAP_NAMES[route.verb]}#{route_name(route, name)}"
|
91
|
+
route
|
92
|
+
end
|
93
|
+
else
|
94
|
+
[]
|
95
|
+
end
|
96
|
+
end.uniq
|
97
|
+
end
|
98
|
+
|
99
|
+
def route_name(route, base_name)
|
100
|
+
if route.post?
|
101
|
+
route_name_for_create(base_name)
|
102
|
+
else
|
103
|
+
base_name
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def route_name_for_create(base_name)
|
108
|
+
if base_name.end_with?('_index')
|
109
|
+
base_name.sub(/_index$/, '')
|
110
|
+
else
|
111
|
+
base_name.singularize
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
const routes = <%= routes_json.html_safe %>;
|
2
|
+
|
3
|
+
<% if client == 'axios' %>
|
4
|
+
import axios from 'axios'
|
5
|
+
|
6
|
+
function request(route, args) {
|
7
|
+
const params = build_request_options(route, args)
|
8
|
+
return axios.request({
|
9
|
+
url: params.path,
|
10
|
+
method: route.verb,
|
11
|
+
params: params.url_options,
|
12
|
+
data: params.data
|
13
|
+
})
|
14
|
+
}
|
15
|
+
<% else %>
|
16
|
+
function request(route, args) {
|
17
|
+
const params = build_request_options(route, args)
|
18
|
+
return <%= client %>(route, params)
|
19
|
+
}
|
20
|
+
<% end %>
|
21
|
+
|
22
|
+
const request_functions = Object.fromEntries(
|
23
|
+
Object.entries(routes).map(pair => {
|
24
|
+
const route = pair[1]
|
25
|
+
const func = (...args) => request(route, args)
|
26
|
+
return [pair[0], func]
|
27
|
+
})
|
28
|
+
)
|
29
|
+
|
30
|
+
const path_functions = Object.fromEntries(
|
31
|
+
Object.entries(routes).map(pair => {
|
32
|
+
const route = pair[1]
|
33
|
+
const func = (...args) => build_request_options(route, args).path
|
34
|
+
return [`${pair[0]}_path`, func]
|
35
|
+
})
|
36
|
+
)
|
37
|
+
|
38
|
+
export default Object.assign({}, request_functions, path_functions)
|
39
|
+
|
40
|
+
function split_args(route, args) {
|
41
|
+
const required_params = route.required
|
42
|
+
let path_params = {}, url_options = {}, data = {}
|
43
|
+
for (let index in args) {
|
44
|
+
const arg = args[index]
|
45
|
+
if (['string', 'number'].includes(typeof arg)) {
|
46
|
+
path_params[required_params[index]] = arg
|
47
|
+
} else {
|
48
|
+
break
|
49
|
+
}
|
50
|
+
}
|
51
|
+
let options = args[Object.keys(path_params).length]
|
52
|
+
data = args[Object.keys(path_params).length + 1]
|
53
|
+
if (typeof options !== 'object')
|
54
|
+
options = {}
|
55
|
+
if (typeof data !== 'object')
|
56
|
+
data = {}
|
57
|
+
for (let param of required_params) {
|
58
|
+
if (!(param in path_params)) {
|
59
|
+
if (param in options) {
|
60
|
+
path_params[param] = options[param]
|
61
|
+
} else {
|
62
|
+
throw new Error(required_param(route, param))
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}
|
66
|
+
const format = presence(options.format)
|
67
|
+
const extracted = required_params.concat(['format'])
|
68
|
+
url_options = Object.fromEntries(
|
69
|
+
Object.entries(options).filter(pair => !extracted.includes(pair[0]))
|
70
|
+
)
|
71
|
+
return {path_params, format, url_options, data}
|
72
|
+
}
|
73
|
+
|
74
|
+
function presence(v) {
|
75
|
+
return (v != null && v !== '') ? v : null
|
76
|
+
}
|
77
|
+
|
78
|
+
function required_param(route, param) {
|
79
|
+
return `Cannot find "${param}" in passed URL options. `+
|
80
|
+
`This value is required for route "${route.name}" (${route.path}).`;
|
81
|
+
}
|
82
|
+
|
83
|
+
function build_request_options(route, args) {
|
84
|
+
const params = split_args(route, args)
|
85
|
+
let path = route.parts.
|
86
|
+
map(v => typeof v === 'string' ? v : params.path_params[v.a]).join('')
|
87
|
+
if (params.format)
|
88
|
+
path += `.${params.format}`
|
89
|
+
if (['get', 'delete'].includes(route.verb))
|
90
|
+
params.data = null
|
91
|
+
return {path: path, url_options: params.url_options, data: params.data}
|
92
|
+
}
|
data/railbus.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative 'lib/railbus/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "railbus"
|
5
|
+
spec.version = Railbus::VERSION
|
6
|
+
spec.authors = ["Evgeniy Nochevnov"]
|
7
|
+
|
8
|
+
spec.summary = %q{Generate JS functions for XHR requests to Rails routes}
|
9
|
+
# spec.description = %q{TODO: Write a longer description or delete this line.}
|
10
|
+
spec.homepage = "https://github.com/crosspath/railbus"
|
11
|
+
spec.license = "MIT"
|
12
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
|
13
|
+
|
14
|
+
spec.add_dependency 'activesupport'
|
15
|
+
spec.add_dependency 'erubi'
|
16
|
+
|
17
|
+
spec.add_development_dependency 'rake'
|
18
|
+
# spec.add_development_dependency 'rspec', '>= 3'
|
19
|
+
|
20
|
+
# spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
|
21
|
+
|
22
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
23
|
+
spec.metadata["source_code_uri"] = "https://github.com/crosspath/railbus"
|
24
|
+
# spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
25
|
+
|
26
|
+
# Specify which files should be added to the gem when it is released.
|
27
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
28
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
29
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
30
|
+
end
|
31
|
+
spec.bindir = "exe"
|
32
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
33
|
+
spec.require_paths = ["lib"]
|
34
|
+
end
|
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: railbus
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Evgeniy Nochevnov
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-07-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: erubi
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description:
|
56
|
+
email:
|
57
|
+
executables: []
|
58
|
+
extensions: []
|
59
|
+
extra_rdoc_files: []
|
60
|
+
files:
|
61
|
+
- ".editorconfig"
|
62
|
+
- ".gitignore"
|
63
|
+
- ".rspec"
|
64
|
+
- ".travis.yml"
|
65
|
+
- Gemfile
|
66
|
+
- LICENSE
|
67
|
+
- README.md
|
68
|
+
- Rakefile
|
69
|
+
- bin/console
|
70
|
+
- bin/setup
|
71
|
+
- lib/railbus.rb
|
72
|
+
- lib/railbus/route_set.rb
|
73
|
+
- lib/railbus/route_set_presenter.rb
|
74
|
+
- lib/railbus/templates/js.erb
|
75
|
+
- lib/railbus/version.rb
|
76
|
+
- railbus.gemspec
|
77
|
+
homepage: https://github.com/crosspath/railbus
|
78
|
+
licenses:
|
79
|
+
- MIT
|
80
|
+
metadata:
|
81
|
+
homepage_uri: https://github.com/crosspath/railbus
|
82
|
+
source_code_uri: https://github.com/crosspath/railbus
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options: []
|
85
|
+
require_paths:
|
86
|
+
- lib
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: 2.3.0
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
requirements: []
|
98
|
+
rubygems_version: 3.0.3
|
99
|
+
signing_key:
|
100
|
+
specification_version: 4
|
101
|
+
summary: Generate JS functions for XHR requests to Rails routes
|
102
|
+
test_files: []
|