简体   繁体   中英

Rails treats Ajax requests with format “json” as “text/html”

Versions

Ruby: 2.4.1

Rails: 5.2.3

jQuery: 3.4.1

Problem

A request is sent from a page through Ajax which has json as a format but a Rails server thinks this request has a format text/html .

As a result, it generates ActionView::MissingTemplate .

ActionView::MissingTemplate (Missing template likes/json, application/json with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :arb, :slim, :coffee, :jbuilder]}

My code

routes.rb

Rails.application.routes.draw do
  resources :likes, only: %i(create destroy)

controller

class LikesController < ApplicationController
  def create
    item = Item.find(like_params[:item_id])
    like = Like.new(user: current_user, item: item)

    if like.save
      count = Like.where(item: item).count

      render :json, { count: count, like_id: like.id }
    else
      render :json, {}
    end
  end

view(slim)

.like-btn
  a href='#'
  .count = @like_count


javascript:
  $('.like-btn a').click( e => {
    e.preventDefault()

    $.ajax({
      url: '#{likes_path(item_id: @item.id)}',
      dataType: 'json',
      method: 'POST',
      success: (data) => {
        $('.like-btn .count').text(data.count)
      }
    })
  })

What I did

  • ruby
    • try respond_to
    • try render:plain, some_json, content_type: 'application/json
  • javascript
    • try $.post
    • set contentType , type , data

request object

# inside LikesController#create

(byebug) request.headers.to_h["CONTENT_TYPE"]
"application/x-www-form-urlencoded"
(byebug) request.format.to_s
"text/html"

Update

I tried #{likes_path(item_id: @item.id)}.json and 'likes?item_id=#{@item.id} but they didn't work and generated the same error.

Here is the request object. It doesn't have json in the url and the format is recognized as text/html even though the url in javascript has json .

# inside LikesController#create

byebug) request.url
"http://localhost:3001/likes?item_id=4"
(byebug) request.format
#<Mime::Type:0x007feea72326a0 @synonyms=["application/xhtml+xml"], @symbol=:html, @string="text/html", @hash=-2254575977737173308>

Update2

I tried #{likes_path(item_id: @item.id, format: :json) which generated likes.json/item_id=4 , but the same error was generated.

# inside LikesController#create

(byebug) request.url
"http://localhost:3001/likes?item_id=6210"
(byebug) request.format.to_s
"text/html"

Update3

I had an error in the success attribute in $.ajax and after removing that error, the Rails server started to recognizing the format as application/json but an error was still generated.

ActionView::MissingTemplate (Missing template likes/json, application/json with {:locale=>[:en], :formats=>[:json], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :arb, :slim, :coffee, :jbuilder]}.

Try appending .json to the URL

url: "#{likes_path(item_id: @item.id, format: :json)}"

Also, in your controller, try this

def create
  item = Item.find(like_params[:item_id])
  like = Like.new(user: current_user, item: item)
  count = nil

  if like.save
    count = Like.where(item: item).count
  end
  respond_to do |format|
    format.json do
      if count
        render json: { count: count, like_id: like.id }
      else
        render json: {}
      end
    end
  end
end

It should work!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM