【问题标题】:How to use scopes in controller and views: Filter table by categories (enum) using scopes in Rails如何在控制器和视图中使用范围:使用 Rails 中的范围按类别(枚举)过滤表
【发布时间】:2019-10-11 11:16:12
【问题描述】:

我的 rails 应用程序中有一个 html 表格,用于支付所有费用。费用是一个枚举,可以采用“教育”、“啤酒”、“bliblablub”等值。

我希望能够根据这些枚举值过滤我的 html 表。我在表格的一侧有用户可以点击的链接。现在我希望表格根据链接过滤结果。

现在,我认为示波器是解决问题的方法,但我很难理解它们的真正工作原理。我创建了一个这样的范围只是为了理解它:

scope :find_category, -> {Expense.where(category:"education")}

在 Rails 控制台中这是可行的,当我调用 find_category 方法时,它会为我提供教育实例。

我认为动态范围应该是这样的:

scope :find_category, -> (category) {Expense.where(category:category)}

到目前为止一切顺利。现在,我并没有真正得到的是我现在如何在我的控制器和视图中使用过滤后的结果,也就是说点击链接时如何过滤它。

我试过这个:

控制器(试图得到我的查询结果)

  def find_category
    @expense = Expense.find_category
    render action: :index
  end

然后为 find_categories 放一条路线:

  resources :expenses, path: 'expenses' do
    collection do
      get :find_category
    end
  end

并在索引中放一个链接:

 <%= link_to 'education', {controller: 'expenses', action: 'index', :find_category => 'education'}  %>

我知道这不是真正的方式。点击链接虽然它给了我expenses?find_category=education。然而什么都没有改变。所以我很难找到正确的方法来做到这一点。当然,在不重新加载页面的情况下这样做也很棒,所以我想我必须使用 AJAX 调用和 JavaScript。但是页面重新加载也会对我有很大帮助。

【问题讨论】:

    标签: ruby-on-rails ajax filtering scopes


    【解决方案1】:

    使用枚举时,Rails 会为您创建方法,因此您可以直接调用类别,例如Expense.education

    这是一个如何管理它的示例,相当原始,假设您使用的是标准 Rails 约定。不需要特殊的路由。


    定义一个包含类别的常量,例如在关注中:
    # model/concerns/expenses_stuff.rb
    module ExpensesStuff
      extend ActiveSupport::Concern
    
      CATEGORIES = {category_a: 0, category_b: 100, category_c: 200 }
    
      module ClassMethods
       # class methods here
      end
    
      # instance methods here
    
    end
    


    models 中,将模块包含在 Expense 类中,并将类别字段定义为 enum,获取常量:
    # models/expense.rb
    class Expense < ApplicationRecord
      include ExpensesStuff
      enum category: MaterialStuff::CATEGORIES
      # usual stuff
    end
    


    现在在控制器中。请注意仅当包含在MaterialStuff::CATEGORIES.keys 中时才接受过滤器值。
    # expenses_controller.rb
    class ExpensesController < ApplicationController
    # usual stuff
      def index
        @expenses = filtered_expenses
      end
    
     private
      def sanitized_category_filter
        category = params[:category].to_sym if params[:category]
        return category.to_sym if MaterialStuff::CATEGORIES.keys.include? category
        :all
      end
    
      def filtered_espenses
        Expense.public_send(sanitized_category_filter) # call directly the method
      end
    
    end
    


    最后,在 view 中,您可以添加过滤链接。
    # views/expenses/index.html.erb
    
    <style>.bg-yellow {background-color:yellow;}</style> <!-- Move to *.css -->
    <% def active_filter(category); 'bg-yellow' if category.to_s == params[:category]; end # move to helpers %>
    
    <% (ExpensesStuff::CATEGORIES.keys << :all).each do |category| %>
      <%= link_to category, expenses_path(category: category), class: active_filter(category) %> |
    <% end %>
    

    您现在只需更新 CATEGORIES 哈希即可添加新类别。您也可以在表单中将其用作 select 的选项。

    【讨论】:

    • 多么好的答案,谢谢我的朋友。抱歉回复晚了,我请假了。我将在本周尝试实施这一点,并将评论/接受等......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-06
    • 2014-01-05
    • 1970-01-01
    相关资源
    最近更新 更多