Permalink
Browse files

Initial import.

git-svn-id: svn+ssh://svn0.sea.apvio.net/home/rwl4/inherits_from@1 bd10a536-b517-0410-99c0-c9a68740b5c0
  • Loading branch information...
0 parents commit 7e682f9d5ec137df2e03e8bc497041d55f560f15 rwl4 committed Jul 3, 2006
6 README
@@ -0,0 +1,6 @@
+InheritsFrom
+============
+
+Allows class inheritance with ActiveRecord.
+
+It is very basic at the moment, and might even be fundamentally flawed.
@@ -0,0 +1,22 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the inherits_from plugin.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = true
+end
+
+desc 'Generate documentation for the inherits_from plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'InheritsFrom'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
@@ -0,0 +1 @@
+require 'inherits_from'
@@ -0,0 +1,81 @@
+require 'active_record'
+
+# +inherits_from+ is an +ActiveRecord+ plugin designed to allow simple multiple table (class) inheritance.
+#
+# Example:
+# class Product < ActiveRecord::Base
+# inherits_from :product
+# end
+#
+# class Book < ActiveRecord::Base
+# inherits_from :product
+# end
+#
+# class Video < ActiveRecord::Base
+# inherits_from :product
+# end
+#
+# book = Book.find(1)
+# book.name => "Agile Development with Rails"
+# book.author => "Dave Thomas"
+#
+# video = Video.find(2)
+# book.name => "Twilight Zone Season 1"
+# book.actors => "Rod Serling"
+
+class ActiveRecord::Base
+ attr_reader :reflection
+
+ # Creates an inheritance association and generates proxy methods in the inherited object for easy access to the parent.
+ # Currently, the options are ignored.
+ #
+ # Example:
+ # class Book < ActiveRecord::Base
+ # inherits_from :product
+ # end
+ def self.inherits_from(association_id, options = {})
+ belongs_to association_id
+
+ reflection = create_reflection(:belongs_to, association_id, options, self)
+
+ association_class = Object.const_get(reflection.class_name)
+
+ inherited_column_names = association_class.column_names.reject { |c| self.column_names.grep(c).length > 0 || c == "type"}
+
+ inherited_column_names.each { |name| alias_associated_attr(association_id, name) }
+
+ before_callback = <<-end_eval
+ init_inherited("#{association_id}")
+ instance_variable_get("@#{association_id}").save
+ end_eval
+
+ before_create(before_callback)
+ before_update(before_callback)
+ end
+
+ # Creates a proxy accessor method for an inherited object.
+ def self.alias_associated_attr(association_id, name)
+ define_method(name) do
+ init_inherited_assoc(association_id)
+ klass = send(association_id)
+
+ klass.send(name)
+ end
+
+ define_method("#{name}=") do |new_value|
+ init_inherited_assoc(association_id)
+ klass = send(association_id)
+
+ klass.send("#{name}=", new_value)
+ end
+ end
+
+ private
+ # Ensures that there is an association to access, if not, creates one.
+ def init_inherited_assoc(association_id)
+ if new_record? and instance_variable_get("@#{association_id}").nil?
+ send("build_#{association_id}")
+ instance_variable_get("@#{association_id}").type = self.class.to_s
+ end
+ end
+end
@@ -0,0 +1,5 @@
+class Book < ActiveRecord::Base
+ inherits_from :product
+
+ validates_presence_of :name, :price, :pages
+end
@@ -0,0 +1,5 @@
+agile_book:
+ author: Dave Thomas
+ product_id: 1
+ id: 1
+ pages: 300
@@ -0,0 +1,3 @@
+class Product < ActiveRecord::Base
+ validates_presence_of :name
+end
@@ -0,0 +1,10 @@
+agile_book:
+ name: Agile Web Development with Rails
+ price: 2995
+ type: Book
+ id: 1
+twilight_video:
+ name: Twilight Zone Season 1
+ price: 8945
+ type: Video
+ id: 2
@@ -0,0 +1,5 @@
+class Video < ActiveRecord::Base
+ inherits_from :product
+
+ validates_presence_of :name, :price, :minutes, :starring
+end
@@ -0,0 +1,5 @@
+twilight_video:
+ minutes: 490
+ product_id: 2
+ id: 1
+ starring: Rod Serling
@@ -0,0 +1,7 @@
+require 'test/unit'
+
+class InheritsFromTest < Test::Unit::TestCase
+ def test_code_needs_to_be_written
+ flunk "Anyone care to write some tests for me? ActiveRecord tests are painful."
+ end
+end

0 comments on commit 7e682f9

Please sign in to comment.