Rails responds to Javascript request even if format.js is not on controller

In a standard Rails 5.1 (or 5.0) controller, you get this in the create action:

def create
    @test = Test.new(test_params)

    respond_to do |format|
      if @test.save
        format.html { redirect_to @test, notice: 'Test was successfully created.' }
        format.json { render :show, status: :created, location: @test }
      else
        format.html { render :new }
        format.json { render json: @test.errors, status: :unprocessable_entity }
      end
    end
  end

      

As you can see, it is not there format.js

.

But if you add remote: true

to the form (or in Rails 5.1 you remove local: true

that will use the new default, which should be submitted via ajax), the form works: the browser will send the message via xhr and redirect to the newly created record.

Looking at the dev tools I see that the response for submitting the form was 200 OK with the following content:

Turbolinks.clearCache()
Turbolinks.visit("http://localhost:3000/tests/10", {"action":"replace"})

      

The console also indicates that it has been processed by Javascript: Started POST "/tests" for 127.0.0.1 at 2017-06-18 09:38:25 -0300 Processing by TestsController#create as JS

The question is: How does Rails handle this response / redirect for a JS request if not in the controller format.js

?

I'm all in the Rails fashion, but I want to know how it works and I haven't seen this "fallback JS request to the format.html block" documented anywhere.

+3


source to share


2 answers


It looks like the code that generates this response is coming from the turbolinks-rails

gem.

https://github.com/turbolinks/turbolinks-rails/blob/v5.0.1/lib/turbolinks/redirection.rb#L14

From the linked code, it looks like turbolinks prepares a js response when called redirect_to

, a request XHR

, not a request GET

, and was turbolinks: false

not provided to the call redirect_to

.



Turbolinks overrides ActionController redirect_to

when gem is present and app.config.turbolinks.auto_include

right.

def redirect_to(url = {}, options = {})
  turbolinks = options.delete(:turbolinks)

  super.tap do
    if turbolinks != false && request.xhr? && !request.get?
      visit_location_with_turbolinks(location, turbolinks)
    else
      if request.headers["Turbolinks-Referrer"]
        store_turbolinks_location_in_session(location)
      end
    end
  end
end

      

+1


source


This behavior is intended and implemented ActionView::LookupContext

:

https://github.com/rails/rails/blob/master/actionview/lib/action_view/lookup_context.rb#L251

# Override formats= to expand ["*/*"] values and automatically
# add :html as fallback to :js.
def formats=(values)
  if values
    values.concat(default_formats) if values.delete "*/*".freeze
    if values == [:js]
      values << :html
      @html_fallback_for_js = true
    end
  end
  super(values)
end

      

There is an open PR to change this behavior, but now it stalled:



https://github.com/rails/rails/pull/15224

There has been some discussion of this other PR:

https://github.com/rails/rails/pull/5892

0


source







All Articles