Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ This project adheres to [Semantic Versioning](http://semver.org/) and [Keep a Ch
---

### New
- Support for options hash for `*_rfc6570` to support Rails Engines.

### Changes

Expand All @@ -17,6 +18,7 @@ This project adheres to [Semantic Versioning](http://semver.org/) and [Keep a Ch
### Fixes

- Fix up `RouteSet#to_rfc6570` and `NamedRouteCollection#to_rfc6570`
- Fix up `*_path_rfc6570` to include Rails Engines mount point.

### Breaks

Expand Down
6 changes: 3 additions & 3 deletions lib/rails/rfc6570.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,15 @@ def define_rfc6570_helpers(name, route, mod, set)
end

mod.module_eval do
define_method(rfc6570_name) do |**opts|
define_method(rfc6570_name) do |opts = {}|
route.to_rfc6570(**opts, ctx: self)
end

define_method(rfc6570_url_name) do |**opts|
define_method(rfc6570_url_name) do |opts = {}|
route.to_rfc6570(**opts, ctx: self, path_only: false)
end

define_method(rfc6570_path_name) do |**opts|
define_method(rfc6570_path_name) do |opts = {}|
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why's this needed? 👀

Copy link
Author

@arkirchner arkirchner Sep 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Support for options hash for *_rfc6570 to support Rails Engines.

When used in a Rails engine, the options are a hash. I was able to reproduce this issue loading the engine; however, this seems to no longer be the case.

I am investigating.

route.to_rfc6570(**opts, ctx: self, path_only: true)
end
end
Expand Down
19 changes: 8 additions & 11 deletions lib/rails/rfc6570/formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,16 @@ def evaluate(ctx:, ignore: %w[format], **kwargs)
end
end

if kwargs.fetch(:path_only, false)
::Addressable::Template.new parts.join
else
options = ctx.url_options.merge(kwargs)
options[:path] = parts.join

if (osn = options.delete(:original_script_name))
options[:script_name] = osn + options[:script_name]
end
options = ctx.url_options.merge(kwargs)
options[:path] = parts.join
options[:only_path] = kwargs.fetch(:path_only, false)

::Addressable::Template.new \
ActionDispatch::Http::URL.url_for(options)
if (osn = options.delete(:original_script_name))
options[:script_name] = osn + options[:script_name]
end

::Addressable::Template.new \
ActionDispatch::Http::URL.url_for(options)
Comment on lines +28 to +37
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be the primary change here, but it is very similar to before.

What's the important change here? It handles path_only: true much more like a full URL? Is that the important change for supporting engines?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the original version removed the engines mount path.

/some_engine/users was resolved to just /users.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix up *_path_rfc6570 to include Rails Engines mount point.

Basically the previous version would ignore script_name for paths.

end

def symbol(node, prefix: nil, suffix: nil)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module DummyEngine
class ApplicationController < ActionController::API
end
end
5 changes: 5 additions & 0 deletions spec/dummy/dummy_engine/lib/dummy_engine.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module DummyEngine
class Engine < ::Rails::Engine
isolate_namespace DummyEngine
end
end
42 changes: 41 additions & 1 deletion spec/rails/rfc6570_spec.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
# frozen_string_literal: true

require 'spec_helper'
require_relative '../dummy/dummy_engine/lib/dummy_engine'
require_relative '../dummy/dummy_engine/app/controllers/dummy_engine/application_controller'

ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.acronym 'API'
end

DummyEngine::Engine.routes.draw do
get '/action' => 'api#action', as: :action
end

Dummy::Application.routes.draw do
get '/' => 'api#index', as: :root

Expand All @@ -20,6 +26,8 @@
get '/path/*capture/:title' => 'api#index', as: :test4
get '/path(/*capture)/:title' => 'api#index', as: :test5
get '/path(/*capture)(/:title)' => 'api#index', as: :test6

mount DummyEngine::Engine => '/dummy_engine'
end

class APIController < ApplicationController
Expand Down Expand Up @@ -49,6 +57,18 @@ def default_url_options
end
end

class DummyEngine::APIController < DummyEngine::ApplicationController
rfc6570_params action: %i[param3]
def action
render json: {
ref: action_path,
template: action_rfc6570,
template_url: action_url_rfc6570,
template_path: action_path_rfc6570,
}
end
end

describe Rails::RFC6570, type: :request do
let(:host) { 'http://www.example.com' }
let(:json) { JSON.parse response.body }
Expand All @@ -58,7 +78,7 @@ def default_url_options

it 'returns list of all parsed and named routes' do
expect(json.keys).to match_array \
%w[root action test1 test2 test3 test4 test5 test6]
%w[root action test1 test2 test3 test4 test5 test6 dummy_engine]
end

it 'includes known parameters' do
Expand Down Expand Up @@ -134,4 +154,24 @@ def default_url_options
end
end
end

context 'action in Rails Engine' do
before { get '/dummy_engine/action', headers: headers }

it 'includes URL helpers' do
expect(response).to have_http_status :ok
end

it 'allows to return and render templates' do
expect(json['template']).to eq "#{host}/dummy_engine/action{?param3}"
end

it 'allows to return and render url templates' do
expect(json['template_url']).to eq "#{host}/dummy_engine/action{?param3}"
end

it 'allows to return and render path templates' do
expect(json['template_path']).to eq '/dummy_engine/action{?param3}'
end
end
end