Giter Site home page Giter Site logo

turbolinks-rails's Introduction

This repository houses the turbolinks RubyGem, which provides a Rails engine for Turbolinks 5 support.

It depends on the turbolinks-source RubyGem, which packages the Turbolinks JavaScript assets for the Rails asset pipeline.

turbolinks-rails's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

turbolinks-rails's Issues

assert_redirected_to behaving oddly with Rails 6

We have a bunch of tests that make xhr requests and used assert_redirected_to.

Attempting to update to Rails 6, the same tests that passed before, fail with:

Schools::Parents::UploadsControllerTest#test_requires_superadmin [/Users/bhilkert/code/bark/test/controllers/schools/parents/uploads_controller_test.rb:47]:
Expected response to be a <3XX: redirect>, but was a <200: OK>
Response body: Turbolinks.clearCache()
Turbolinks.visit("http://bark.test/schools/dashboard", {"action":"replace"})

rails test test/controllers/schools/parents/uploads_controller_test.rb:39

It should use Turbolink's version of assert_redirected_to, however it's not because the check is return false because response.content_type from Rails 6 is text/javascript; charset=utf-8 instead of the checked condition (text/javascript).

Is this the expected response type for Rails 6 and if so, should this be adjusted to check for the presence of text/javascript instead of the exact string? If so, I can make a PR, but just want to confirm we don't have something configured wrong.

"respond_with" via responders ignores JavaScript redirections

When rendering a form with remote: true, one can replace the form with an error-rendered state via AJAX. However, using the very popular "responders" conventions, like Devise does, you find that the success response looks like:

respond_with resource, location: after_sign_up_path_for(resource)

while the error response looks like

respond_with resource

The problem here being that the turbolinks-rails handling of the redirection in the success case never happens. In fact, no attempt at redirection is made. It simply tries to render a JS template for the action.

I'm not sure if a fix really belongs inside turbolinks-rails, but this issue is of course specific to turbolinks-rails. So if anyone else is pondering about the same problem, here's a simple fix:

# config/initializers/responders.rb
module ActionController
  class Responder

    # Default implementation of `to_js` is just `default_render` but if there's no errors and
    # we pass a location then I expect to be redirected via Turbolinks JS
    def to_js
      if !has_errors? && options[:location].present?
        redirect_to options[:location]
      else
        default_render
      end
    end

  end
end

Shouldn't the default visit option still be `advance`?

I noticed the default visit option changed from advance to replace, I don't understand in which use case that would be desirable.

To my understanding visit_location_with_turbolinks is only executed for xhr requests which aren't GETs , thus never triggered by Turbolinks.visit.
That means that calling Turbolinks.visit(location, "replace") will override the history location of the XHR request with the redirection target and navigating back will skip the page that issued the XHR request.
I would expect the default to still be advance, because the location of the XHR call is never put in the browser location history.

Cache is not cleared with `advance` redirect

Hi!

When redirecting with turbolinks: :advance, clearCache is called before visit, and current page remains in cache after visit is finished. So history.back() shows outdated page.

5.0.0.beta2 / redirect_to with turbolinks action 'change' renders {"action":"replace"} instead of { change: [...] }

Steps to reproduce

I have this view with turbolinks and would like to have a partial update of the div #result through serverside turbolinks.

<div id="result" data-turbolinks-temporary>
  <% if flash[:new] %>
      Created new mock. Send your requests to <%= link_to flash[:new] %>.
  <% end %>
</div>
<div>
  <%= form_for @new_mock, :remote => true do |f| %>
      <%= f.label :statuscode %>:
      <%= f.text_field :statuscode %><br />
...
      <%= f.submit %>
  <% end %>
</div>

And its backed by this controller

class MocksController < ApplicationController

  def index
    @new_mock = Mock.new
  end

  def create
    mock = Mock.new(mock_params)
    mock.save
    flash[:new] = mock

    redirect_to mocks_path, change: ['result']
  end

  private
...
end

Expected behavior

When submitting the form, i would expect the response of the POST to be

Turbolinks.clearCache()
Turbolinks.visit("http://localhost:3000/mocks", { change: ['result'] })

Actual behavior

But i get

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

System configuration

Rails version: 5.0.0.beta4
Turbolinks-rails version: 5.0.0.beta2

Ruby version: 2.3.0

Why not request.fullpath?

From what I can tell, xhr request still includes the Turbolinks-Referrer header even when redirecting, so instead of storing redirect url in session, isn't it simpler to just use request.fullpath when setting the header? Is there specific reason to not do it?

# lib/turbolinks/redirection.rb#L43
if request.headers["Turbolinks-Referrer"].present?
  response.headers["Turbolinks-Location"] = request.fullpath
end

(unfortunately I don't have testable app - I'm realizing this when using turbolinks from non-ruby app and reimplementing the integration)

Distribute un-minified version?

I've been messing with the source in the main Turbolinks repository, using blade and whatnot, to obtain an un-minified version of the Turbolinks source.

Since 90% of Rails users will be using the asset pipeline, distributing an unminified version will give most users more visibility in development mode.

Turbolinks JavaScript object not available in production

When I'm developing, Turbolinks works fine. The Turbolinks JavaScript object is available in my JavaScript console as expected.

development

When I deploy to production, the Turbolinks object isn't defined properly. The Turbolinks object isn't available in the JavaScript console, and my site does full page loads instead of Turbolinks page loads.

production

Upon further inspection of my production environment, the application.js asset is getting compiled and served. jQuery is accessible. Turbolinks appears in the minified JavaScript:

source

My application.js:

//= require jquery
//= require bootstrap
//= require jquery_ujs
//= require turbolinks
//= require_tree .

To me, it seems like Turbolinks is properly setup, but after going through asset compilation for the production environment it's not available in the window for usage.

Gemfile.lock

    turbolinks (5.0.1)
      turbolinks-source (~> 5)
    turbolinks-source (5.0.0)
    uglifier (3.0.2)
      execjs (>= 0.3.0, < 3)

config/environments/production.rb

  # Compress JavaScripts and CSS.
  config.assets.js_compressor = :uglifier
  # config.assets.css_compressor = :sass

  # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb

  # Enable serving of images, stylesheets, and JavaScripts from an asset server.
  # config.action_controller.asset_host = 'http://assets.example.com'

FWIW I'm deploying on Heroku and relying on them to do asset precompilation, and using the rails_12factor gem. To me it seems like Turbolinks is included correctly in the asset pipeline, but the Turbolinks JavaScript is somehow getting mangled by the precompliation/minification process.

Thanks for all the hard work you put into Turbolinks. My team is extremely excited about it.

–Ben

How to avoid redirecting to a single route when using `remote: true` link from two different pages

Sorry, I've tried to find the answer to this question but I haven't been able to find it anywhere. In my Rails app, I use <%= link_to ... remote: true %> to perform AJAX create/update requests. However, I'm trying to call the same controller action from two different pages, which means, in one scenario it's redirecting to the wrong place. I'd like for the page to simply refresh itself once the call has finished successfully, but instead, it currently redirects to the location that the controller specifies. The whole point of using the link_to ... remote: true syntax is that it's quick and easy, so I hope to find a simple/supported way to do this. Thanks!

Is this version going to support Rails 3.2?

Hey, thx for this awesome gem!
Is it meant to support Rails 3.2?

Bundling works but starting the rails server fails with this error:

/Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:89:in `rescue in block (2 levels) in require': There was an error while trying to load the gem 'turbolinks'. (Bundler::GemRequireError)
Gem Load Error is: undefined method `assets' for #<Rails::Engine::Configuration:0x007feb93786f50>
Backtrace for gem load error is:
/Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/railties-3.2.22.2/lib/rails/railtie/configuration.rb:85:in `method_missing'
/Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/turbolinks-5.0.0.beta2/lib/turbolinks.rb:17:in `<class:Engine>'
/Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/turbolinks-5.0.0.beta2/lib/turbolinks.rb:14:in `<module:Turbolinks>'
/Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/turbolinks-5.0.0.beta2/lib/turbolinks.rb:5:in `<top (required)>'
/Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:86:in `require'
/Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:86:in `block (2 levels) in require'
/Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:81:in `each'
/Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:81:in `block in require'
/Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:70:in `each'
/Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:70:in `require'
/Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/bundler-1.12.5/lib/bundler.rb:102:in `require'
/Users/gambo/Sites/Boxes/config/application.rb:13:in `<top (required)>'
/Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/railties-3.2.22.2/lib/rails/commands.rb:53:in `require'
/Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/railties-3.2.22.2/lib/rails/commands.rb:53:in `block in <top (required)>'
/Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/railties-3.2.22.2/lib/rails/commands.rb:50:in `tap'
/Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/railties-3.2.22.2/lib/rails/commands.rb:50:in `<top (required)>'
bin/rails:10:in `require'
bin/rails:10:in `<main>'
Bundler Error Backtrace:
    from /Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:85:in `block (2 levels) in require'
    from /Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:81:in `each'
    from /Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:81:in `block in require'
    from /Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:70:in `each'
    from /Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:70:in `require'
    from /Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/bundler-1.12.5/lib/bundler.rb:102:in `require'
    from /Users/gambo/Sites/Boxes/config/application.rb:13:in `<top (required)>'
    from /Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/railties-3.2.22.2/lib/rails/commands.rb:53:in `require'
    from /Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/railties-3.2.22.2/lib/rails/commands.rb:53:in `block in <top (required)>'
    from /Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/railties-3.2.22.2/lib/rails/commands.rb:50:in `tap'
    from /Users/gambo/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/railties-3.2.22.2/lib/rails/commands.rb:50:in `<top (required)>'
    from bin/rails:10:in `require'
    from bin/rails:10:in `<main>'

undefined method `get?' for 302:Integer

This issue has been reported on stackoverflow and I see that it has not yet been addressed:

https://stackoverflow.com/questions/49294119/undefined-method-get-for-302integer

From SO:

describe 'DELETE /salesman/:id' do
  let!(:salesman) { create :salesman }
  subject(:request) do
    delete salesman_path(salesman), headers: auth_headers
  end

  it 'redirects to index' do
    expect(request).to redirect_to company_salesmen_path(salesman.company)
  end
end
Failure/Error: expect(request).to redirect_to company_salesmen_path(salesman.company)

NoMethodError:
    undefined method `get?' for 302:Integer
  # /Users/dennish/.rvm/gems/ruby-2.5.0/gems/turbolinks-5.1.0/lib/turbolinks/assertions.rb:37:in `turbolinks_request?'
  # /Users/dennish/.rvm/gems/ruby-2.5.0/gems/turbolinks-5.1.0/lib/turbolinks/assertions.rb:6:in `assert_redirected_to'
  # ./spec/requests/salesmen_spec.rb:206:in `block (3 levels) in <top (required)>'

Do not split assets into separate gem

I'd love to package the turbolinks for Fedora, but the way how the assets are split into separate gem makes the whole matter quite unfortunate. Let me explain.

turbolinks is now independent js/coffee script library. So I should take it and package as js-turbolinks package. There is the turbolinks gem, i.e. this library. I should package it as rubygem-turbolinks in Fedora. Up until here, everything looks OK.

However, you split the JS assets into independent turbolinks-source gem and here it becomes interesting. Historically, for various reasons, we tried to unbundle everything in Fedora, that means that the turbolinks-source should depend on js-turbolinks and the .js library should by just filesystem system symlink. But, the thing is that in theory, the js-turbolinks might be of different version then the rubygem-turbolinks-source. That in turn means, that the version which is reported by turbolinks-source might not match the version of actual turbolinks.js. I might fix it by very strict version dependencies, but that has disadvantages as well, e.g:

  • we have to always update js-turbolinks together with rubygem-turbolink-source,
  • somebody might decide to update one library, but the other library can't be updated due to other version restrictions.

In this case, our live would be much easier, if the actual asset files were included directly into turbolinks. I see almost no disadvantages on your side, while it would make our life much easier.

Just FTR, I have been previously in the similar position with therubyracer gem, which used to bundled v8. This was unfortunate (because it is bundling) but we could unbundle the v8 and move on. Once the libv8 was introduced as dependency of therubyracer, we could not really move on with update.

I'd be very grateful if you can discontinue the turbolinks-source. Thanks for considering this 'weird' request.

Problems with server-side rendering after upgrading from classic

I have a Rails 4.2.7.1 app and upgraded Turbolinks only:

gem 'turbolinks', github: 'turbolinks/rails'

P.S. App doesn't use any partial replacement.

I have a jQuery ajax call e.g.

$.get({ url: url, dataType: 'script' })

In my Rails controller I have a:

render :new, turbolinks: true

I see that render has not be modified in this version of lib/turbolinks/redirection.rb as with the classic version.

But even if I replace render :new, turbolinks: true with redirect_to the overridden redirect_to did not kick in and do a Turbolinks.visit().

  1. Are there plans to port over classic's lib/turbolinks/redirection.rb with render support? I have bunch of places where render :***** , turbolinks: true is called.
  2. Is there something I need to add to the $.get({ url: url, dataType: 'script' }) call for the Turbolinks.visit to kick in?

Usage when the assets pipeline is disabled

Is it possible to use this gem without the assets? I'm using the Turbolinks npm package, but would like to use the redirection stuff from this gem.

I have a --skip-sprockets project which outputs this on rails s:

rescue in block (2 levels) in require': There was an error while trying to load the gem 'turbolinks'. (Bundler::GemRequireError)
Gem Load Error is: undefined method `assets' for #<Rails::Engine::Configuration:0x007fcf51d04350>

redirect_to in rspec failing

I'm having the same issue as listed here - turbolinks/turbolinks#398 - and my controller and tests are basically identical. I'm not sure what configuration I'd need to change to prevent this, but I'm happy to provide config info if it's needed. My turbolinks version is 5.2.1, rails is 5.2.3, rspec is 3.8.2, rspec-rails is 3.8.2

redirect_to with turbolinks option failing

I have an issue with cross domain redirects and Turbolinks not working as expected. Although I should admit at this point that this expectation is set using the README on turbolinks/turbolinks-classic since this repo doesn't have one. :]

If I add 'data-turbolinks' => false to the HTML link that triggers a redirect, then the redirection happens fine and no errors are printed to the JavaScript console. However, if I remove that data tag, and instead add the turbolinks: false option to the redirect_to call, then I get the initial XHR request, followed by the No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin ... is therefore not allowed access. error printed to the JavaScript console, followed by the HTML redirection request, which then succeeds.

I was under the impression that adding turbolinks: false to a redirect_to call would cause the browser to redirect normally, and therefore no Access-Control-Allow-Origin error would be printed to the log.

A little more context

We have an SSO service that all our apps communicate with. Each app has both a prominent sign on/off link, as well as automatic sign in if a user is already signed in to one of the other apps using the service. Adding the data-turbolinks tag to the links works fine, but it's the automatic sign in that is generating the Access-Control-Allow-Origin error. The way this works is that some business logic runs in a before_action in the application controller, and if it's determined that a user can be automatically signed in then a redirect happens using redirect_to to our SSO service that is hosted on a different domain.

Steps to reproduce

You can recreate the behaviour I'm seeing with this very simple example:

# controller.rb
class Controller < ApplicationController
  def google
    redirect_to('http://google.com', turbolinks: false)
  end
end

# routes.rb
get 'google', to: 'sessions#google'

# index.html.erb
<%= link_to("Google", google_path) %>

Expected behavior

The response served to the browser would cause it to redirect normally and not attempt to load the contents of the redirection via XHR.

Actual behavior

An attempt to redirect via XHR is triggered, followed by...

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin ... is therefore not allowed access.

...followed by a normal redirection.

System configuration

Rails version: Rails 5.0.0.beta3

Ruby version: ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-darwin15]

Add dependency on coffee-rails

I recently removed the coffee-rails gem from my Rails app Gemfile as a bit of housekeeping as I was not using CoffeeScript anywhere directly. What I didn't notice at the time was that the turbolinks 2.2 gem still depended on coffee-rails and so everything kept working fine.

When I updated turbolinks from 2.5 to 5.0 it broke the app because coffee-rails was no longer present. Some time between 2.5 and 5.0 the gem dependency on coffee-rails was removed.

It would seem sensible to add it back here to prevent other obsessive-compulsive dependency cleaners like myself from tripping up on this.

Add supports for `render` in controllers

I published a gem that adds support for render in Rails controllers when using Turbolinks.

I think this should be officially supported by Turbolinks and I am willing to work on that PR.
I would include a comprehensive suite of tests as part of the PR, and I am willing to follow any guideline or consideration you may have. I just don't want to do the work if there is no hope to have it used.

As mentioned in this comment:

I think the situation right now is inconsistent and can be really confusing:

  • Rails 5 adds Turbolinks by default
  • Forms are remote by default
  • render won't work with the defaults mentioned above.

The fact that forms in scaffolds are generated with local: true in Rails 5.2 looks like an smell to me. The vanilla code generated by Rails won't use its own defaults!

Redirection bug if your controller defines `location`

Took a day finding the issue with a bug we had :P Eventually leading to TurboBoost.

This is Turboboost's redirect method.

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) # Bug happens here
    else
      if request.headers["Turbolinks-Referrer"]
        store_turbolinks_location_in_session(location)
      end
    end
  end
end

Our controller for Locations with a quite common "find-object pattern"

class LocationsController < InheritedResources::Base

  def show
    @location = location.decorate
  end

  private

  def location
    @location ||= @current_company.locations.find(params[:id])
  end

end

This happened to override location inside your redirect_to method.

README and Upgrading to Turbolinks 5?

@sstephenson I'm testing out the beta and this has me fairly confused. Can we get a README that clarifies what exactly is happening here and, preferably, how to upgrade from Turbolinks Classic to Turbolinks 5? If there's a guide already out there, I can't find it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.