"You stay classy, inheritance" - Gibson
$ sudo gem install classy-inheritance # in environment.rb add: require "classy-inheritance"
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:
class User < ActiveRecord::Base
depends_on :profile, :attrs => [:first_name, :last_name, :email]
end
You will get the following added to the User class:
class User < ActiveRecord::Base
validates_presence_of :profile
validates_associated :profile
before_save :save_requisite_profile
#...
def save_requisite_profile
self.profile.save
end
end
class Picture < ActiveRecord::Base
depends_on :image, :attrs => [:filename, :height, :width], :as => "imageable"
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:
# automatically do :include => :image
Picture.find_with_image
# getters/setters for the attributes defined:
@picture.height
@picture.height = 100
@picture.width
@picture.width = 150
@picture.filename
@picture.filename = "/some/path/file.ext"
# return @image.imageable_type == 'Picture'
@image.is_a_picture?
# return Picture.find_with_image(@image.presentable_id)
@image.as_a_picture
In addition, you can define the different types of models a polymorphic class can represent:
class Image < ActiveRecord::Base
can_be :picture, :as => "imageable"
end
This will give you the following methods:
# return @image.imageable_type == 'Picture'
@image.is_a_picture?
# return Picture.find_with_image(@image.presentable_id)
@image.as_a_picture
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.
class User < ActiveRecord::Base
depends_on :profile, :attrs => [:first_name, :last_name, :email]
end
Similar to the polymorphic use, you will get pass-through methods for each attribute:
@user.first_name
@user.last_name
@user.email
@user.first_name=
@user.last_name=
@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.
class Bakery < ActiveRecord::Base
depends_on :business, :attrs => [:name], :prefix => true
end
#Will give you:
@bakery.business_name
class Bakery < ActiveRecord::Base
depends_on :business, :attrs => [:name], :prefix => "bakery"
end
#Will give you:
@bakery.bakery_business_name
Option: postfix
Office.depends_on :billing_address,
:attrs => [:line_one, :line_two, :city, :state_code, :postal_code],
:class_name => "Address",
:foreign_key => "billing_address_id",
:postfix => true
#Will give you:
@office.line_one_billing_address
@office.line_two_billing_address
@office.city_billing_address
@office.state_code_billing_address
@office.postal_code_billing_address
Office.depends_on :billing_address,
:attrs => [:line_one, :line_two, :city, :state_code, :postal_code],
:class_name => "Address",
:foreign_key => "billing_address_id",
:postfix => "billing"
#Will give you:
@office.line_one_billing
@office.line_two_billing
@office.city_billing
@office.state_code_billing
@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:
class Document < ActiveRecord::Base
depends_on :content, :attrs => [:name],
:as => :presentable, :dependent => :destroy
...
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.
http://github.com/stonean/classy-inheritance/tree/master
git://github.com/stonean/classy-inheritance.git
Please use the forum to ask questions and the issue tracker to report problems or submit a pull request.
This code is free to use under the terms of the MIT license.
Copyright (c) 2008 Andrew Stone
t