0

My Rails 5 app makes four API calls and displays the results on the show page. I have button_to in place that calls an Ajax POST request on the show page so users can vote on their favorite. This triggers some JS, which works fine in dev and production on my laptop. Browsers on my iphone, though, use the full controller URI and try to download it. The button_to returns a 204: no content status.

I've tried redirecting to another /show page after the Ajax call as well as redirecting with the gem browser if the user is on mobile, but those pages crash if the user refreshes them. I've tried explicitly returning a 200 status in the controller, but that wants a redirect. I want the user to stay on the /show page, so nothing else with redirecting works for me.

In the model:

def self.first_api(term)
  call_url = FIRST_CALL_URL
  response = HTTParty.get(call_url,
    { headers: {
      "Accept": "application/json",
      "app_id": "#{ENV['FIRST_API_APP_ID']}",
      "app_key": "#{ENV['FIRST_API_APP_KEY']}" }
    })

  if response.include?("!DOCTYPE")
    "NO DEFINITION"
  else
    response
  end
end

Controller (truncated):

def show
  @full_call = FullCall.find(params[:id])
end

def create
  @full_call = FullCall.where(word:full_call_params[:word]).first_or_create do |call|
    call.first_api_response = FirstCall.first_api(call.word)
  end
end

if @full_call.save
  redirect_to @full_call
else
  render 'new'
end

def vote_for_first
  @full_call.first_vote += 1
  @full_call.save
end

private

    def full_call_params
      params.require(:full_call).permit(:word, :definition)
    end

Relevant routes:

resources :full_calls
post 'vote_for_first', to: 'full_calls#vote_for_first'

/show page:

<p>
  <div>
    <h2 id='full-call-heading'><%= @full_call.word.upcase %></h2>
    <div id='full-call-alert'></div>
  </div>
</p>

<div class="container">
  <div class="card-title">
    <div class="card card-default">
      <div class="card-header"><strong>First Call Definition:</strong>
        <div>
          <%= button_to('VOTE FOR FIRST', { controller: 'full_calls',
                                         action: 'vote_for_first',
                                         id: @full_call,
                                         remote: true },
                                       { class: "btn btn-outline-secondary btn-sm vote-btn" }) %>
        </div>
      </div>
    <div class="card-block"><%= @full_call.first_api_response %></div>

application.js

$(document).on('turbolinks:load', function() {
  $('.vote-btn').on('click', function() {
    setTimeout(function() {
      $('.vote-btn').attr('disabled', true);
      $('#full-call-alert').append("<h5>Thanks for voting!</h5>").hide().slideDown('slow');
    }, 100);
  });
});

And, finally, the URL that returns the "Download failed" message only on mobile browsers:

myapp.herokuapp.com/vote_for_first?id=12&remote=true

Any ideas?

  • What's the `Content-Type` on the URL? I can imagine if an unknown `Content-Type` is returned that a mobile browser would attempt to just download it as a binary file. I'd run the Chrome and/or Safari remote debugger/inspector to see what's going on. – mroach May 24 '18 at 07:06
  • Thanks, I'll give this a shot later today. – nobetterjim May 24 '18 at 14:52

0 Answers0