rails: Rails route URL helpers do not handle strong parameters `format` correctly

Steps to reproduce

git clone https://github.com/codeodor/rails-issue-with-format
cd rails-issue-with-format
rails s
open http://localhost:3000/tests

Expected behavior

The two URLs output should be identical.

Actual behavior

The first example sticks a parameter in the URL for format instead of changing the extension.

Rails’ controllers behave fine when responding to these links – the controller still responds with the requested format. But Turbolinks does not see this as an extension it should avoid, which causes it to send a request with a different format than the server responds with.

System configuration

Rails version: 5.1.3

Ruby version: 2.3.0

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 18 (13 by maintainers)

Most upvoted comments

I can reproduce:

begin
  require "bundler/inline"
rescue LoadError => e
  $stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler"
  raise e
end

gemfile(true) do
  source "https://rubygems.org"
  gem "rails", github: "rails/rails"
  gem "arel", github: "rails/arel"
end

require "action_controller/railtie"

class TestApp < Rails::Application
  config.root = __dir__
  secrets.secret_token    = "secret_token"
  secrets.secret_key_base = "secret_key_base"

  config.logger = Logger.new($stdout)
  Rails.logger  = config.logger

  routes.draw do
    resources :tests, only: [:index]
  end
end

class TestController < ActionController::Base
  include Rails.application.routes.url_helpers

  def index
    render plain: "Home"
  end
end

require "minitest/autorun"
require "rack/test"

class BugTest < Minitest::Test
  include Rack::Test::Methods
  include Rails.application.routes.url_helpers

  def test_returns_success
    param_hash = { location_id: 10, format: 'pdf' }
    params = ActionController::Parameters.new(param_hash).permit!

    hash_path = tests_path(param_hash)
    params_path = tests_path(params)

    assert_equal hash_path, params_path
  end

  private
    def app
      Rails.application
    end
end

@codeodor You are right, this was only for tests.

I would like someone else to also take a look at this before I start fixing it and to confirm what should be the expected outcome.

They’re not both incorrect: tests_path("params" => {"format" => "pdf"}) should give /tests?format=pdf