简体   繁体   English

Rails:模型上的链接过滤器方法

[英]Rails: Chaining filter methods on a model

My web app is showing a list of articles. 我的网络应用程序显示文章列表。 Articles can be published in different countries (ie Article belongs to a Country, and Country has many Articles), and in different languages (ie Article belongs to a Language, and Language has many Articles). 文章可以在不同的国家(即文章属于某个国家,而一个国家有很多文章)发表,也可以在不同的语言中发表(即,文章属于一种语言,而语言有很多文章)。

What I would like to do is to make requests that will return me articles from selected countries and in selected languages. 我想做的是发出请求,将以选定的语言和语言返回我的文章。 That is, I would eventually like to make a request such as this: 也就是说,我最终希望发出这样的请求:

Article.selected_countries.selected_languages

and get a list of articles. 并获取文章列表。

Both for the countries, and for the languages, the front-end can send the following parameters: 对于国家和语言,前端都可以发送以下参数:

  • "all" — that means, effectively, do not apply this filter, and return articles from all countries (or articles in all languages); "all" -表示实际上不应用此过滤器,而是返回所有国家/地区的文章(或所有语言的文章);
  • array of id's — that will mean, return articles only from countries with provided id's (or in languages with provided id's) ID数组-表示仅从具有ID的国家(或以具有ID的语言)返回文章
  • empty array — I guess, that is a special case of the previous option; 空数组—我想这是前一个选项的特例; it will mean that articles from no country (or in no language) have to be returned, so no articles will be returned 这意味着没有国家(或任何语言)的文章必须退回,因此不会退回任何文章

Now, what confuses me is to how to write these class methods and how to make them chainable. 现在,令我困惑的是如何编写这些类方法以及如何使它们可链接。 Rails Guides provide the following example: Rails指南提供以下示例:

class Article < ActiveRecord::Base
  def self.created_before(time)
    where("created_at < ?", time)
  end
end

if I build a class method based on this example, such as the following: 如果我基于此示例构建了一个类方法,例如:

def self.selected_countries(parameter)
  ???
end

How do I define this method provided the parameter can be the string "all", an array of id's, or an empty array? 如果parameter可以是字符串“ all”,id的数组或空数组,如何定义此方法? Also, how do I make sure the filter doesn't do anything if the parameter is "all"? 另外,如果参数为“ all”,如何确定过滤器什么也不做?

def self.selected_countries(parameters)
  case parameters
  when "all"
    all
  else
    where(country_id: parameters)
  end
end

Subsequent chains of scope methods append to the query, instead of replacing it. 随后的范围方法链将附加到查询中,而不是替换它。

So you could call this scope like 所以你可以称这个范围像

Article.selected_countries([1]).selected_countries("all")

and you'll get all the Articles for country 1. 您将获得有关国家1的所有文章。

What you are describing is called scopes in rails. 您所描述的被称为Rails中的范围。 http://guides.rubyonrails.org/active_record_querying.html#scopes http://guides.rubyonrails.org/active_record_querying.html#scopes

The nice thing about scopes is that (if written right) they support exactly the kind of chaining you want. 关于范围的好处是(如果书写正确)它们完全支持您想要的链接类型。 Here is an example of a scope, it returns all if given an empty array otherwise it returns records associated with any of the countries in the array: 这是一个范围的示例,如果给定一个空数组,它将返回所有,否则它将返回与数组中任何国家/地区相关的记录:

scope : selected_countries, lambda { |countries|
  if countries.length == 0
    all
  else
    where(country_id: countries)
  end
}

Rails has built in support for what you're trying to achieve in the form of "scopes". Rails以“作用域”的形式内置了对您要实现的目标的支持。 You'll find everything you need to know in RailsGuides. 您会在RailsGuides中找到所有需要了解的信息。

http://guides.rubyonrails.org/active_record_querying.html#scopes http://guides.rubyonrails.org/active_record_querying.html#scopes

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM