Rails: Chaining filter methods on a model

99封情书 提交于 2019-12-11 09:37:57

问题


My web app is showing a list of articles. Articles can be published in different countries (i.e. Article belongs to a Country, and Country has many Articles), and in different languages (i.e. 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);
  • array of id's — that will mean, return articles only from countries with provided id's (or in languages with provided id's)
  • 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:

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? Also, how do I make sure the filter doesn't do anything if the parameter is "all"?


回答1:


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.




回答2:


Rails has built in support for what you're trying to achieve in the form of "scopes". You'll find everything you need to know in RailsGuides.

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




回答3:


What you are describing is called scopes in rails. 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
}


来源:https://stackoverflow.com/questions/28989814/rails-chaining-filter-methods-on-a-model

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!