Reputation: 2738
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);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"?
Upvotes: 1
Views: 1352
Reputation: 9278
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.
Upvotes: 2
Reputation: 1095
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
Upvotes: 3
Reputation: 3012
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
}
Upvotes: 3