Rails& Ajax:通过选择的过滤器显示产品

时间:2016-04-17 12:25:04

标签: ruby-on-rails ajax

我需要使用Ajax按选定的类别显示产品;如果用户没有选择类别,则显示所有产品。如果用户选择了一个或两个类别,则只应显示属于这些类别的产品。

例:

enter image description here

我的模型产品,类别和连接表cause_products

分类

class Category < ActiveRecord::Base has_and_belongs_to_many :products end

产品

class Product < ActiveRecord::Base has_and_belongs_to_many :categories end


我正在寻找一个教程,我找到了“Rails 4:”How to partials & AJAX, dead easy“。我遵循了这个教程,但是我得到了一个错误。我觉得我错过了什么。
您能否就此提出建议或参考有用的资料来源。谢谢!

产品控制器:

class ProductsController < ApplicationController
  def index
    @products = Product.all
    @categories = Category.all
  end
  def from_category
    @selected = Product.where(:category_id => params[:cat_id])
    respond_to do |format|
      format.js
    end
  end
end


产品/ index.html.erb:

<div class="grid">
  <%= render 'sidebar_menu' %>
  <%= render partial: 'product_grid', locals: { products: @products} %>
</div>


产品/ _sidebar_menu

<% @categories.each do | cat | %>
<%= link_to cat.name, fetch_products_path(:cat_id => cat.id), :remote => true %>
<% end %>


的routes.rb

get "/fetch_products" => 'products#from_category', as: 'fetch_products'


产品/ _products_grid.html.erb

<div>
  <%= render partial: 'products_list', locals: { products: products } %>
</div>


产品/ _products_list.html.erb

<% products.each do |product| %>
    <div class="product_box">
      product.name
    </div>
<% end %>


产品/ from_category.js.erb

$("#products_grid").html("<%= escape_javascript(render partial: 'products_list', locals: { products: @selected } ) %>");


我的终端输出:

Product Load (3.2ms)  SELECT `products`.* FROM `products` WHERE `products`.`category_id` = '11'
Mysql2::Error: Unknown column 'products.category_id' in 'where clause': SELECT `products`.* FROM `products` WHERE `products`.`category_id` = '11'
    Rendered products/_products_list.html.erb (8.8ms)
    Rendered products/from_category.js.erb (12.2ms)
    Completed 500 Internal Server Error in 23ms (ActiveRecord: 3.5ms)


ActionView::Template::Error (Mysql2::Error: Unknown column 'products.category_id' in 'where clause': SELECT `products`.* FROM `products` WHERE `products`.`category_id` = '11'):
    1: <% products.each do |product| %>
    2:     <div class="product_box">
    3:     <%= product.name %>
    4:     </div>
  app/views/products/_products_list.html.erb:1:in `_app_views_products__products_list_html_erb___255698018512654633_70336949043820'
  app/views/products/from_category.js.erb:1:in `_app_views_products_from_category_js_erb___4172137050793767106_70336965664480'
  app/controllers/products_controller.rb:24:in `from_category'`




* - 原来 sidebar_menu文件只包含一行:
<%= link_to cat.name, fetch_items_path(:cat_id => cat.id), :remote => true %>
但是我收到了这个错误:

Showing views/products/_sidebar_menu.html.erb where line #1 raised:

undefined local variable or method `cat' for #<#<Class:0x007ff1336747c0>:0x007ff1350376a8>
Extracted source (around line #1):

<%= link_to cat.name, fetch_products_path(:cat_id => cat.id), :remote
=> true %>




更新1

@max的解决方案:

 def from_category
    @products = Product.joins(:categories).where(categories: { id: params[:cat_id] })
    respond_to do |format|
      format.js
    end

感谢 @max 的帮助,他的解决方案是更新控制器操作,它解决了错误,但选择类别后产品列表没有刷新。

日志:

Started GET "/fetch_products?cat_id=11" for ::1 at 2016-04-18 13:53:01 +0300
Processing by ProductsController#from_category as JS
  Parameters: {"cat_id"=>"11"}
  Product Load (1.9ms)  SELECT `products`.* FROM `products` INNER JOIN `categories_products` ON `categories_products`.`product_id` = `products`.`id` INNER JOIN `categories` ON `categories`.`id` = `categories_products`.`category_id` WHERE `categories`.`id` = 11
  Rendered products/_products_list.html.erb (6.4ms)
  Rendered products/from_category.js.erb (11.5ms)
Completed 200 OK in 29ms (Views: 24.1ms | ActiveRecord: 1.9ms)




更新2:

@max这是我点击某个类别时在响应中得到的结果:

$("#products_grid").html("  
  <div class=\"product_box\">\n      Bed\n    <\/div>\n
  <div class=\"product_box\">\n      Notebook\n    <\/div>\n
  <div class=\"product_box\">\n      Desk\n    <\/div>\n    
  <div class=\"product_box\">\n      Mug\n    <\/div>\n"
);

@Jeffrey M Castro注意到我错过了products_grid中的div ID:

产品/ _products_grid.html.erb

<div id="products_grid">
  <%= render partial: 'products_list', locals: { products: products } %>
</div>

该代码仅适用于所选类别,但我希望它能够过滤两个或更多类别。我需要做出哪些改变?

方案: 用户点击“主页类别”,即可获得属于此类别的所有产品。然后他点击“鞋子类别”,现在他看到属于这两个类别的所有产品(“家庭类别”或“鞋子类别”)。用户点击“全部清除”按钮(为了重置所选类别),现在显示所有类别的所有产品。

感谢。

2 个答案:

答案 0 :(得分:2)

由于产品和类别之间存在has_and_belongs_to_many关系,因此您无法按products.category_id选择产品,因为两者之间的实际链接存储在categories_products联接表中。

您需要使用联接并在关联中指定条件:

@products = Product.joins(:categories)
                   .where(categories: { id: params[:cat_id] })

答案 1 :(得分:2)

根据@max的回复,最好使用浏览器检查器的网络选项卡检查服务器提供的JS响应。

在您的代码中:

$("#products_grid").html("<%= escape_javascript(render partial: 'products_list', locals: { products: @selected } ) %>");  

您想要更改#products_grid的html内容,但我在您的视图文件中没有看到任何具有该ID的内容。
因此,您必须在div中指定其ID为#products_grid

products / _products_grid.html.erb

<div id="products_grid">
  <%= render partial: 'products_list', locals: { products: products } %>
</div>