views:

84

answers:

3

Hey! Maybe I am getting the idea of a subclass wrong, but I have a Person model and it has an attrib called "age" so

Person.first.age #=> '20'

Now I want to have a model that's basically persons 55 or older so I know I can have a class like this: class Senior < Person end

But how can I "pre-filter" the Senior class so that every object belonging to that class has age >= 55?

Senior.first.age #=> 56

UPDATE1: So say I have Company has_many people, and Person belongs_to Company, so Company.first.people #=> ["Jack", "Kate"]

If Jack's age is > 55, will it work then: Company.first.seniors #=> "jack"

Or

Company.first.people.senior(s) #=> "jack"?

I know that named_scope might be what I want, but I also notice that named_scope seems to be a method on the Class variable Person. Not its instances, which does make sense to me. -- So if I were to devise such a convenience filter for a collection of activerecord models (objects of the same class), how do I go about it? I am guessing I'd have to use a "detect" for such an array, but where will this go inside the Model's definition?

Update 2 I am quite sure I haven't been clear, so example Want: first company's 55 or older people Company.first.people.detect{|p| p.age > 54}

I know this isn't very long, but my conditions will go farther than just > 54 and it becomes clumsy to do this detect each time.

Thanks!

+6  A: 

You can use named scopes

class Person < ActiveRecord::Base
  named_scope :seniors, :conditions => ['age >= ?', 55]
end

Person.seniors.first.age #=> 83
fl00r
I would totally recommend to use this approach.
Marcel J.
I guess I forgot another use that I do want in having a subclass senior, it is added as an update to the original queston. Thanks for the quick answer
Nik
so you can use default_scope in Senior < Person class and Person abstraction as Marcel offered
fl00r
to fl00r's comment: with Marcel J.'s method, even though I have never explicitly defined Company has_many seniors, Senior belongs_to Company, I can still do Company.first.seniors?
Nik
Use fl00rs approach and define `def seniors; people.seniors; end` in Company. This will behave exactly like a `has_many :seniors`, but will be much better design.
Marcel J.
Got it! Thanks fl00r, Marcel, and Salil.
Nik
+2  A: 

This should do the trick.

class Person
  def self.abstract_class?
    true
  end
end

class Junior < Person
  set_table_name "people"
  default_scope :conditions => "people.age < 55"
end

class Senior < Person
  set_table_name "people"
  default_scope :conditions => "people.age >= 55"
end

But I would reconsider whether this is a good idea. But if you decide to go for it, please use an abstract "Person" class, to avoid problems with Rails' STI implementation.

Marcel J.
A: 

Hi,

I don't know how to do it using Subclass but You can do it using class method as following.

class Person < ActiveRecord::Base

def self.senior
find(:all, :conditions=>["age>=?"], 55)
end

end

and you can call it from the any controller as follows

senior_age= Person.senior.first.age unless Person.senior.blank?

Salil