ruby-on-rails - 如何在控制器和视图中使用范围:使用 Rails 中的范围按类别(枚举)过滤表
问题描述
我的 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。但是页面重新加载也会对我有很大帮助。
解决方案
使用枚举时,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 类中,并将 category 字段定义为 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
最后在视图中,您可以添加过滤链接。
# 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
哈希即可。您也可以在表单中将其用作选择的选项。
推荐阅读
- java - Flyway - 特定环境的不同迁移 - Spring Boot
- node.js - 使用 CURRENT_DATE、Now() 和 CURRENT_TIMESTAMP 返回错误的日期和时间 - 关闭 1 天/停留在 23:00
- sklearn-pandas - StratifiedShuffleSplit 跨多个功能?
- powershell - PS:如果现有参数值设置为特定值,则使用动态参数
- r - 为不同组生成日期之间的时间序列
- arrays - 使用 C 生成文件中的变量
- regex - PCRE 的 ng 模式
- python - cv2.putText() 不使用可变参数
- laravel - 允许通过 Axios 请求从 Vue 到 Laravel 控制器的 HTML 标签
- postgresql - 搜索两圆交叉区域的共同对象