From 0108bd6fc785306c0d3bd5d29a801e97fd0bcdf3 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Mon, 9 Feb 2009 15:00:42 +0100 Subject: Removed named scopes from the finders guide. Named scopes deserve it's own guide --- .../guides/source/active_record_querying.textile | 122 +-------------------- 1 file changed, 2 insertions(+), 120 deletions(-) (limited to 'railties') diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile index 139d9f31c6..817d24de1f 100644 --- a/railties/guides/source/active_record_querying.textile +++ b/railties/guides/source/active_record_querying.textile @@ -782,125 +782,6 @@ h3. select_all Client.connection.select_all("SELECT * FROM clients WHERE id = '1'") -h3. Working with Associations - -When you define a has_many association on a model you get the +find+ method and dynamic finders also on that association. This is helpful for finding associated records within the scope of an existing record, for example finding all the orders for a client that have been sent and not received by doing something like +Client.find(params[:id]).orders.find_by_sent_and_received(true, false)+. Having this find method available on associations is extremely helpful when using nested resources. - -h3. Named Scopes - -Named scopes are another way to add custom finding behavior to the models in the application. Named scopes provide an object-oriented way to narrow the results of a query. - -h4. Simple Named Scopes - -Suppose we want to find all clients who are male. You could use this code: - - -class Client < ActiveRecord::Base - named_scope :males, :conditions => { :gender => "male" } -end - - -Then you could call +Client.males.all+ to get all the clients who are male. Please note that if you do not specify the +all+ on the end you will get a +Scope+ object back, not a set of records which you do get back if you put the +all+ on the end. - -If you wanted to find all the clients who are active, you could use this: - - -class Client < ActiveRecord::Base - named_scope :active, :conditions => { :active => true } -end - - -You can call this new named_scope with +Client.active.all+ and this will do the same query as if we just used +Client.all(:conditions => ["active = ?", true])+. If you want to find the first client within this named scope you could do +Client.active.first+. - -h4. Combining Named Scopes - -If you wanted to find all the clients who are active and male you can stack the named scopes like this: - - -Client.males.active.all - - -If you would then like to do a +all+ on that scope, you can. Just like an association, named scopes allow you to call +all+ on them: - - -Client.males.active.all(:conditions => ["age > ?", params[:age]]) - - -h4. Runtime Evaluation of Named Scope Conditions - -Consider the following code: - - -class Client < ActiveRecord::Base - named_scope :recent, :conditions => { :created_at > 2.weeks.ago } -end - - -This looks like a standard named scope that defines a method called +recent+ which gathers all records created any time between now and 2 weeks ago. That's correct for the first time the model is loaded but for any time after that, +2.weeks.ago+ is set to that same value, so you will consistently get records from a certain date until your model is reloaded by something like your application restarting. The way to fix this is to put the code in a lambda block: - - -class Client < ActiveRecord::Base - named_scope :recent, lambda { { :conditions => ["created_at > ?", 2.weeks.ago] } } -end - - -And now every time the +recent+ named scope is called, the code in the lambda block will be executed, so you'll get actually 2 weeks ago from the code execution, not 2 weeks ago from the time the model was loaded. - -h4. Named Scopes with Multiple Models - -In a named scope you can use +:include+ and +:joins+ options just like in +find+. - - -class Client < ActiveRecord::Base - named_scope :active_within_2_weeks - lambda { { :joins => :order, :conditions => ["orders.created_at > ?", 2.weeks.ago] } } -end - - -This method, called as +Client.active_within_2_weeks.all+, will return all clients who have placed orders in the past 2 weeks. - -h4. Arguments to Named Scopes - -If you want to pass to a named scope a required argument, just specify it as a block argument like this: - - -class Client < ActiveRecord::Base - named_scope :recent, lambda { |time| { :conditions => ["created_at > ?", time] } } -end - - -This will work if you call +Client.recent(2.weeks.ago).all+ but not if you call +Client.recent+. If you want to add an optional argument for this, you have to use prefix the arugment with an *. - - -class Client < ActiveRecord::Base - named_scope :recent, lambda { |*args| { :conditions => ["created_at > ?", args.first || 2.weeks.ago] } } -end - - -This will work with +Client.recent(2.weeks.ago).all+ and +Client.recent.all+, with the latter always returning records with a created_at date between right now and 2 weeks ago. - -Remember that named scopes are stackable, so you will be able to do +Client.recent(2.weeks.ago).unlocked.all+ to find all clients created between right now and 2 weeks ago and have their locked field set to false. - -h4. Anonymous Scopes - -All Active Record models come with a named scope named +scoped+, which allows you to create anonymous scopes. For example: - - -class Client < ActiveRecord::Base - def self.recent - scoped :conditions => ["created_at > ?", 2.weeks.ago] - end -end - - -Anonymous scopes are most useful to create scopes "on the fly": - - -Client.scoped(:conditions => { :gender => "male" }) - - -Just like named scopes, anonymous scopes can be stacked, either with other anonymous scopes or with regular named scopes. - h3. Existence of Objects If you simply want to check for the existence of the object there's a method called +exists?+. This method will query the database using the same query as +find+, but instead of returning an object or collection of objects it will return either +true+ or false+. @@ -1007,4 +888,5 @@ h3. Changelog "Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/16 -* December 29 2008: Initial version by Ryan Bigg +* February 7, 2009: Second version by "Pratik":credits.html#lifo +* December 29 2008: Initial version by "Ryan Bigg":credits.html#radar -- cgit v1.2.3