Why is this controller returning an html, causing respond_to to fail?

241 Views Asked by At

I'm following a course where we are trying to render a partial through a respond_to. I have been following it strictly, and I'm very confused about why my project is now showing an error while the instructor's project up to this point is running fine.

ActionController::UnknownFormat in StocksController#search

ActionController::UnknownFormat in StocksController#search

For some reason, the controller can only respond to an html result, and not a js one, which is what this section of the course is covering. I'm having difficulty understanding why this is happening.

Here is the relevant model, controller, and views:

app/controllers/stocks_controller.rb

class StocksController <ApplicationController
    
    def search
        if params[:stock].present?            
             @stock = Stock.new_lookup(params[:stock])
             if @stock            
                respond_to do |format|
                    format.js { render partial: 'users/result' }
                end         
             else
                flash[:alert] = "Please enter a valid symbol to search"
                redirect_to my_portfolio_path
             end             
        else 
            flash[:alert] = "Please enter a symbol to search"
            redirect_to my_portfolio_path
        end
    end
    
end

app/models/stock.rb

class Stock < ApplicationRecord
    def self.new_lookup(ticker)
        client = IEX::Api::Client.new(
            publishable_token: Rails.application.credentials.iex_client[:sandbox_publishable_token],
            secret_token: Rails.application.credentials.iex_client[:sandbox_secret_token],
            endpoint: 'https://sandbox.iexapis.com/v1'
        )
        begin
            new(ticker: ticker, name: client.company(ticker).company_name, last_price: client.price(ticker))
        rescue Exception => e
            nil
        end
    end
end

app/views/users/my_portfolio.html.erb

<h1>My Portfolio</h1>
 
<div class='search-area'>
  <h3>Search Stocks</h3>
  <%= form_tag search_stock_path, remote: true, method: :get do %>
    <div class="form-group row">
      <div class="col-sm-9 no-right-padding">
        <%= text_field_tag :stock, params[:stock], placeholder: "Stock ticker symbol", autofocus: true, class: "form-control form-control-lg" %>
      </div>
      <div class="col-sm-3 no-left-padding">
        <%= button_tag type: :submit, class: "btn btn-success" do %>
          <%= fa_icon 'search 2x' %>
        <% end %>
      </div>
    </div>
  <% end %>
</div>
 
<div id="results">
 
</div>

app/views/users/_result.html.erb

<% if @stock %>
  <div class="card card-header results-block">
    <strong>Symbol: </strong> <%= @stock.ticker %>
    <strong>Name: </strong> <%= @stock.name %>
    <strong>Price: </strong> <%= @stock.last_price %>
  </div>
<% end %>

app/views/users/_result.js.erb

alert("Hello!");

It is my understanding that by typing in a valid ticker into the form, I should see the alert since that is what is happening for the instructor. I already have remote: true in the form, which is what I saw from other answers.

Any help would be greatly appreciated. Thank you!

EDIT: This is my application.js file. It already has the suggested require, and the only part I added was import "bootstrap".

// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")


// Uncomment to copy all static images under ../images to the output folder and reference
// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
// or the `imagePath` JavaScript helper below.
//
// const images = require.context('../images', true)
// const imagePath = (name) => images(name, true)

import "bootstrap"

Edit 2: It seems like the remote: true part of this is not working at all. When I follow the instructor's commands before the section this question pertains to, no ajax is called, and the page reloads again.

What I mean is that the page is loading the /search_stock endpoint from the /my_portfolio endpoint (where I start the search from) instead of staying on /my_portfolio and waiting for a js response. The form tag does correctly have the data-remote="true" show up in the inspector though. Ajax failing to be called

1

There are 1 best solutions below

0
On
const { environment } = require('@rails/webpacker')

const webpack = require("webpack")

environment.plugins.append("Provide", new webpack.ProvidePlugin({
    $: "jQuery",
    jQuery: "jQuery",
    Popper: ["popper.js", "default"]
}))

module.exports = environment

My environment.js file was referencing jQuery inside the strings when it should instead say jquery, with no capital Q.