Classy Inheritance¶
"You stay classy, inheritance" - Gibson
Installing¶
$ sudo gem install classy-inheritance # in environment.rb add: require "classy-inheritance"
What¶
Classy Inheritance provides two methods:- depends_on allows you to define requisite objects.
- can_be allows you to associate the various ActiveRecord models your polymorphic class can represent.
More functionality coming for optional relationships.
When using depends_on for both polymorphic and belongs_to relationships you will get the following added to your calling class. For instance if you have defined:1 class User < ActiveRecord::Base
2 depends_on :profile, :attrs => [:first_name, :last_name, :email]
3 end
You will get the following added to the User class: 1 class User < ActiveRecord::Base
2 validates_presence_of :profile
3 validates_associated :profile
4 before_save :save_requisite_profile
5
6 #...
7 def save_requisite_profile
8 self.profile.save
9 end
10 end
Polymorphic¶
1 class Picture < ActiveRecord::Base
2 depends_on :image, :attrs => [:filename, :height, :width], :as => "imageable"
3 end
This will look for "imageable_type" and "imageable_id" on the images table add set them accordingly.
Polymorphic relationships have another feature. The above definition will add two methods to an image object: 1 # automatically do :include => :image
2 Picture.find_with_image
3
4 # getters/setters for the attributes defined:
5 @picture.height
6 @picture.height = 100
7 @picture.width
8 @picture.width = 150
9 @picture.filename
10 @picture.filename = "/some/path/file.ext"
11
12 # return @image.imageable_type == 'Picture'
13 @image.is_a_picture?
14
15 # return Picture.find_with_image(@image.presentable_id)
16 @image.as_a_picture
17
In addition, you can define the different types of models a polymorphic class can represent:1 class Image < ActiveRecord::Base
2 can_be :picture, :as => "imageable"
3 end
This will give you the following methods:1 # return @image.imageable_type == 'Picture'
2 @image.is_a_picture?
3
4 # return Picture.find_with_image(@image.presentable_id)
5 @image.as_a_picture
As you may have guessed, belongs_to will call can_be on the requisite class.
Note: If you are intending on calling Image.find (and you most likely are), it's best to manually add the can_be methods to Image. With class reloading in development mode, you won't get the methods from the Picture.depends_on call.
Belongs_To¶
You can define a standard belongs_to relationship:1 class User < ActiveRecord::Base
2 depends_on :profile, :attrs => [:first_name, :last_name, :email]
3 end
Similar to the polymorphic use, you will get pass-through methods for each attribute:
1 @user.first_name
2 @user.last_name
3 @user.email
4 @user.first_name=
5 @user.last_name=
6 @user.email=
This means you can use these attributes on your form and in your controller instead of having to worry about creating/updating a separate Profile model.
For the above example, you'll also get a "find_with_profile" class method that will do the :include => :profile addition to your find call for you.
Additional options¶
Option: prefix1 class Bakery < ActiveRecord::Base
2 depends_on :business, :attrs => [:name], :prefix => true
3 end
4
5 #Will give you:
6 @bakery.business_name
1 class Bakery < ActiveRecord::Base
2 depends_on :business, :attrs => [:name], :prefix => "bakery"
3 end
4
5 #Will give you:
6 @bakery.bakery_business_name
Option: postfix 1 Office.depends_on :billing_address,
2 :attrs => [:line_one, :line_two, :city, :state_code, :postal_code],
3 :class_name => "Address",
4 :foreign_key => "billing_address_id",
5 :postfix => true
6 #Will give you:
7 @office.line_one_billing_address
8 @office.line_two_billing_address
9 @office.city_billing_address
10 @office.state_code_billing_address
11 @office.postal_code_billing_address
1 Office.depends_on :billing_address,
2 :attrs => [:line_one, :line_two, :city, :state_code, :postal_code],
3 :class_name => "Address",
4 :foreign_key => "billing_address_id",
5 :postfix => "billing"
6 #Will give you:
7 @office.line_one_billing
8 @office.line_two_billing
9 @office.city_billing
10 @office.state_code_billing
11 @office.postal_code_billing
Option: Standard Rails Options
Introduced with release 0.4.0, you can now add the Rails options provided for the type of association. If you use the :as option, the association is a :has_one, otherwise it's a :belongs_to association.
This means you can do the following:1
2 class Document < ActiveRecord::Base
3 depends_on :content, :attrs => [:name],
4 :as => :presentable, :dependent => :destroy
5 ...
6 end
Options: validates_presence_if, validates_associated_if
You can now use these options to determine whether or not the validates_presence_of and validates_associated methods are called. By default, both methods are called. You can pass in true, false, string/symbol (for methods reference) or a Proc.
Github¶
http://github.com/stonean/classy-inheritance/tree/master
git://github.com/stonean/classy-inheritance.git
Contact¶
Please use the forum to ask questions and the issue tracker to report problems or submit a pull request.
License¶
This code is free to use under the terms of the MIT license.
Copyright (c) 2008 Andrew Stone