Rails:使用范围来显示模型的不同子集以及如何以较少 DRY 的方式构建它?

Posted

技术标签:

【中文标题】Rails:使用范围来显示模型的不同子集以及如何以较少 DRY 的方式构建它?【英文标题】:Rails: Using scopes to show different subsets of a model and how to build this the less DRY-ist way? 【发布时间】:2022-01-23 17:26:56 【问题描述】:

我的 Ruby on Rails 应用程序中有一个模型电影,我想要一些简单的链接来显示它的不同子集 - 例如,未看过的电影、没有输入制作年份的电影、评级为“很棒”等。

我在我的电影模型中为所有这些条件创建了范围,例如。 g.

scope :no_year, ->  where(release_year: [0, nil, ""]) 

但是我想要一个这些子集的列表 - 如前所述,用户可以单击并在默认视图(实际上是电影索引视图)中获得结果的链接列表。所以我有一个链接列表,如下所示,这要求我为所有这些看起来几乎相同的范围添加路由和方法。

<%= link_to 'Movies without a Year', noyear_movies_path %>
(<%= Movie.no_year.count %>)

routes.rb:

resources :movies do
  get :noyear, on: :collection
end

movies_controller.rb:

def noyear
  @q = Movie.no_year.ransack(params[:q]) # using Ransack for a sidebar that is displayed
  @pagy, @movies = pagy(@q.result(distinct: true)) # using pagy to split up results
  render 'index'
end

编辑:添加索引和侧边栏方法代码。

我的索引方法如下所示:

def index
  @pagy, @movies = pagy(@q.result(distinct: true))
end

...变量 q 本身是在应用程序范围内设置的,因为它是在包含始终显示的小搜索字段的边栏中定义的:

def sidebar_q_movie
  @q = Movie.ransack(params[:q])
end

我相信这可以更好地实现。但由于我对 Ruby 还很陌生,所以我不知道。任何提示表示赞赏!

【问题讨论】:

【参考方案1】:

您可以使用 Movies#index 的查询参数指定过滤器,而不是为每个电影过滤器设置单独的路由

<%= link_to 'Movies without a Year', movies_path(filter: 'no_year') %>

在控制器中:

def index
  @movies = Movies.send(params[:filter])
end

当然,您需要先验证过滤器参数,然后再发送到Movies

【讨论】:

谢谢你,这很有趣。但是我正在使用 ransack,并且我在原始问题中添加了我的索引方法的外观。 没关系 - 我想通了 :) 我需要链接它,...Movie.send(params[:filter].ransack(params[:q]),这似乎有效。

以上是关于Rails:使用范围来显示模型的不同子集以及如何以较少 DRY 的方式构建它?的主要内容,如果未能解决你的问题,请参考以下文章

Rails 视图表以显示来自另一个模型的值

如何构建 Rails 视图以编辑关联的数据集

Rails:如何在一个循环中访问两个模型

Rails、Simple Form 和 Javascript 显示/隐藏脚本

在 Rails 中审计记录

如何编写迁移以重命名 Rails 中的 ActiveRecord 模型及其表?