1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
Route = Struct.new(:name, :path, :has_params?) do
def <=> (other)
self.name <=> other.name
end
end
def placeholder_params_hash(params)
Hash[params.zip(params.map { |param| "${params.#{param.to_s.camelize(:lower)}}" })]
end
class InternalRouteGenerator
def self.path_for_route(route, params)
path = route.format(placeholder_params_hash(params))
path = path.gsub(/%7B(.+?)%7D/, '{\1}') # undo escaping of JavaScript placeholdes
path.gsub(/\.\$\{params.format\}$/, '') # we favor ?format=
end
def self.all
routes = Rails.application.routes.routes.named_routes
routes.map do |name, route|
params = route.parts
Route.new("#{name}_path", self.path_for_route(route, params), !params.empty?)
end
end
end
class ApiRouteGenerator
def self.path_for_route(route, params, api_version)
values = placeholder_params_hash(params).merge(version: api_version)
segments = route.path_segments_with_values(values).reject { |s| route.optional_segment?(s) }
'/' + segments.join('/')
end
def self.all
routes = Array(Grape::API.decorated_routes)
routes.flat_map do |route|
Array(route.route_options[:version]).map do |api_version|
params = route.route_options[:params].keys
name = route.path_helper_name({ version: api_version, format: route.extension })
Route.new(name, self.path_for_route(route, params, api_version), !params.empty?)
end
end
end
end
namespace :frontend do
task :routes do
def write_routes(file, routes)
routes.each do |route|
name = route.name.camelize(:lower)
path = "${baseUrl}#{route.path}"
if route.has_params?
file.puts "export const #{name} = params => `#{path}`;"
else
file.puts "export const #{name} = () => `#{path}`;"
end
end
end
all_routes = (InternalRouteGenerator.all + ApiRouteGenerator.all).uniq { |route| route.name }.sort
output_path = File.join(Rails.root, 'app', 'assets', 'javascripts', 'routes.js')
File.open(output_path, 'w') do |file|
file.puts '// This file was generated by bin/rake frontend:routes'
file.puts "const baseUrl = gon.relative_url_root || '';"
write_routes(file, all_routes)
end
end
end
|