質問

What is the "Rails Way" to send data to a controller action on a simple click event when using turbolinks?

I have a page with two links: one points to /food and the other to /drinks. My goal is to send some location data (via the geolocation api) to the controller and then render the appropriate view after processing that location data.

What is the path of least resistance to navigate the user to the appropriate path and send data along with the request?

Should each button be wrapped in a form and send a post request?

Should I hijack/turn off Turbolinks and manage the rendering on my own? If I just send data via an XHR on a click event, the controller gets 2 requests: one from Turbolinks and another from my handler, which is undesirable.

Here is some code:

app/controllers/drinks_controller.rb

class DrinksController < ApplicationController
  def index
    # Ideally, I would like to check for POST or GET data here 
    # and send as a parameter to get_a_venue

    @venue = get_a_venue(:drinks)
  end
end

app/views/drinks/index.html.erb

<% provide(:title, @venue[:name]) %>

<!-- body content -->

<div class="row buttons">
    <div class="small-12 medium-6 columns">
        <h3>
            <%= link_to 'Try Another One', drinks_path, class: "button expand radius choice" %>
        </h3>
    </div>
    <div class="small-12 medium-6 columns">
        <h3>
            <%= link_to "I Want Some Food Instead", food_index_path, class: "button expand radius choice" %>
        </h3>
    </div>
</div>

app/assets/javascripts/handlers.js

$(function() {
    // success callback sets an in scope variable to the location coordinates
    navigator.geolocation.getCurrentPosition(success, error, options)

    document.addEventListener('click', function(e) {
        if (e.currentTarget.nodeName === 'A' &&
            e.currentTarget.classList.contains('choice') {

            // send data via ajax here?
        }
    }, false)
 })()
役に立ちましたか?

解決

You could for instance opt-out your buttons, which will prevent your buttons from using turbolinks.

Or you could listen to the page:before-change event, perform your AJAX request and return false. This will cancel the turbolink request. Source

So something like:

document.addEventListener('page:before-change', function(e) {
  if (e.currentTarget.nodeName === 'A' &&
      e.currentTarget.classList.contains('choice') {
     // do stuff
  }
  return false;
}, false)

If you wanna use turbolinks but provide the geolocation as a query string to your controller you could do link_to "something", something_path(lat: <geolat>, lng: <geolng>) and then access lat, lng with params[:lat], params[:lng]

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top