0

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]}.
masa_ekohe
  • 49
  • 5

1 Answers1

0

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!

Rajdeep Singh
  • 16,466
  • 6
  • 45
  • 69
  • Thank you for a comment, Rajdeep. I tried `#{likes_path(item_id: @item.id)}.json` and `'likes?item_id=#{@item.id}` but it 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`. ``` # inside LikesController#create byebug) request.url "http://localhost:3001/likes?item_id=4" (byebug) request.format # ``` – masa_ekohe Nov 18 '19 at 18:05
  • @masa_ekohe I just edited my answer, please give it a try – Rajdeep Singh Nov 18 '19 at 18:07
  • Thank you for a quick follow up, I tried and updated the original comment. – masa_ekohe Nov 18 '19 at 18:17
  • @masa_ekohe Just edited my answer, I guess you had a syntax issue with `render :json`, it should be `render json: {}` and not `render :json, {}`, try my edited approach combined with the first approach – Rajdeep Singh Nov 18 '19 at 18:36
  • 1
    You are right. Now it is behaving correctly. Thank you Rajdeep! – masa_ekohe Nov 18 '19 at 18:51