0

I want my Index to change according to Price descending and Price ascending just like Amazon.

Right now, I send an ajax request to the site, with the new value of the select requesting the data. The site gets the data from database and sorts it. After that, my javascript redraws the cards in my index page with the sorted book response.

But when I console.log the result I get the whole html page.
This line of code below gives me the error:

var books = JSON.parse(result);

Unexpected token < in JSON at position 0 BookController.rb

How can I only get the @books?
Below is my code:

BookController.rb

def index
  if params.dig("book", "title").nil? && params.dig("users", "university").nil?
    @books = Book.where({title: params.dig("book", "title")})
    .joins(:user).where(users: {university: params.dig("users", "university")})
  elsif !params.dig("book", "title").nil? && params.dig("users", "university").nil?
    @books = Book.where({title: params.dig("book", "title")})
  elsif params.dig("book", "title").nil? && !params.dig("users", "university").nil?
    @books = Book.joins(:user).where(users: {university: params.dig("users", "university")})
  else
    @books = Book.all
  end
  case params[:sort]
    when "Price Descending"
      @books.order(price_cents: "DESC")
    when "Price Ascending"
      @books.order(price_cents: "ASC")
    else
      @books.sort_by(&:created_at)
  end
  respond_to do |format|
    format.html
    format.json { render json: @books }
  end
end

Book Index.html.erb

<select id="priceSelect">
  <option value="Best Results" selected="selected">Best Results</option>
  <option value="Price Descending">Price Descending</option>
  <option value="Price Ascending">Price Ascending</option>
</select>
.
.
.
<div class="books-info">
  <% @books.each do |book| %>
    <div class="col-xs-12 selectable-card">
      <%= link_to book_path(book.id) do %>
        ...   
      <% end %>
    </div>
  <% end %>
</div>

<script>
  $('#priceSelect').change(function(){
    $.ajax({
      url: "books",
      type: "GET",
      data: {sort: $('#priceSelect :selected').val()},
      success:function(ret){
        console.log(ret);
        var books = JSON.parse(ret);
        var length = books.length;
        var html = "";
        for (var i = 0; i < length; i++) {
          html += "<div class='col-xs-12 selectable-card'>";
          html += "<a href='" + books[i].id + "'>" + books[i].name + "</a>";
          html += "</div>";
        }
        $('.books-info').innerHTML = html
      },
    })
  });
</script>

And lastly my routes.rb

resources :books do
  resources :users
end
WQ.Kevin
  • 319
  • 3
  • 13
  • The error means the response contains XML or HTML, not JSON as you've told it to expect – Rory McCrossan Sep 29 '17 at 15:25
  • Yes, it gives me the whole html ......But it's really weird because shouldn't it only get the objects from my @books because I said GET the index from the BooksController.rb? – WQ.Kevin Sep 29 '17 at 15:28

2 Answers2

0

Change this

 respond_to do |format|
   format.html
   format.json { render json: @books }
 end

to:

render json: {data: @books}
toddmetheny
  • 4,405
  • 1
  • 22
  • 39
  • It's getting warmer. When I do this the whole html is gone though, but it displays all the @books Objects that I actually wanted. And at the top right corner I can switch between raw and parsed – WQ.Kevin Sep 29 '17 at 15:35
0

I think you're missing the accept header in your Ajax request so you're actually getting the HTML page back again.

Try:

$.ajax({
  dataType: 'json',
  ...
});
  • Ok, I did that and the error changed to Uncaught SyntaxError: Unexpected end of JSON input. Does that mean I have a syntax error in my controller or in my javascript code? Additionally, if I console.log(ret) it gives me an array [ ] with length = 0 – WQ.Kevin Sep 29 '17 at 21:03
  • When I just do var books = ret; it gives me no error. But it says that the length of the array is 0. I took the advise from Aditya Mittal's answer: https://stackoverflow.com/a/33489715/1438029 – WQ.Kevin Sep 29 '17 at 21:11
  • Sounds like there is something wrong in the query you're making. Try debugging the code there to make sure that you're actually getting anything back from the database. – Anton Holmberg Sep 30 '17 at 06:38
  • I found out that if I print my @books in the case params[:sort], it tells me that books is just [ ] empty. the params[:sort] gives me my required "Price Descending/Ascending though". I think the problem lies in that it just tells me that its empty. That is what the sql says when I change the value of the select: SELECT "books".* FROM "books" INNER JOIN "users" ON "users"."id" = "books"."user_id" WHERE "books"."title" IS NULL AND "users"."university" IS NULL – WQ.Kevin Sep 30 '17 at 13:27
  • If the title is nil you should probably not include it in the where statement. The same goes for the University. – Anton Holmberg Sep 30 '17 at 20:40