diff options
Diffstat (limited to 'lib/tasks')
-rw-r--r-- | lib/tasks/frontend/routes.rake | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/lib/tasks/frontend/routes.rake b/lib/tasks/frontend/routes.rake new file mode 100644 index 00000000000..50669f00cc4 --- /dev/null +++ b/lib/tasks/frontend/routes.rake @@ -0,0 +1,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 |