Using a class method with or without named scopes
Here’s a quick one, building off of the previous post on Geokit and Named Scopes.
If you have defined a class method you want to run which operates on a collection of records, you can share it with named scopes.
class Project < ActiveRecord::Base
validates_presence_of :name
named_scope :completed, :conditions => {:completed => true}
# returns array of names for projects
def self.names
scope = self.scoped({})
scope.all.collect{|record| record.name}
end
end
This allows you to do
@project_names = Project.names
Or
@project_names = Project.completed.names
If you return the scope, you can continue chaining. If you don’t return the scope, then you can’t. This comes in handy though for creating a method that returns other objects than the object you’re working with. Here’s a completely contrived example:
Say you want to find the actual hours you’ve spent on all your completed projects:
class Project < ActiveRecord::Base
named_scope :completed, :conditions => {:completed => true}
def self.tasks
tasks = []
self.scoped({}).all.each do |project|
tasks += (project.tasks)
end
tasks
end
def self.actual_hours
hours = 0
tasks.each do |task|
hours += task.hours
end
hours
end
Grab the value like this:
actual_hours = Project.completed.actual_hours
Now, of course there are other ways to do this, and this particular method will result in a lot of queries. If you were doing this hours counting in a real app, you’d be better off using SQL. This example illustrates the point though. Now go build something more awesome.