Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add some new tests, mark those not working as pending, and fix automa…

…tic child deletion when a parent record is destroyed
  • Loading branch information...
commit d3bb630e6b46fdf9fdce3fff91baff0b2d32be28 1 parent cbe2e9f
@mhuggins authored
View
7 README.md
@@ -65,6 +65,13 @@ extended.
acts_as_superclass
end
+As mentioned in the migration section, the name of the subtype column can be
+defined here if it's something other than the default of "subtype".
+
+ class Employee < ActiveRecord::Base
+ acts_as_superclass, :subtype => 'employee_type'
+ end
+
Conversely, the `inherits_from` method is used to represent that a given model
extends another model. It takes one optional parameter, which is the symbol
desired for referencing the relationship.
View
7 lib/multiple_table_inheritance/active_record/child.rb
@@ -16,6 +16,7 @@ def inherits_from(association_name, options={})
options = Child::default_options.merge(options.to_options.reject { |k,v| v.nil? })
inherit_methods = options.delete(:inherit_methods)
+ extend InheritClassMethods
include InstanceMethods
include DelegateMethods if inherit_methods
@@ -72,6 +73,12 @@ def inherited_columns_and_associations
end
end
+ module InheritClassMethods
+ def find_by_id(*args)
+ send("find_by_#{parent_association_name}_id", *args)
+ end
+ end
+
module InstanceMethods
private
View
22 lib/multiple_table_inheritance/active_record/parent.rb
@@ -14,7 +14,12 @@ module ClassMethods
def acts_as_superclass(options={})
options = Parent::default_options.merge(options.to_options.reject { |k,v| v.nil? })
self.subtype_column = options[:subtype]
- extend FinderMethods if column_names.include?(subtype_column.to_s)
+
+ if column_names.include?(subtype_column.to_s)
+ extend FinderMethods
+ include InstanceMethods
+ before_destroy :destroy_child_association
+ end
end
end
@@ -60,6 +65,21 @@ def ids_by_type(records)
Hash[subtypes]
end
end
+
+ module InstanceMethods
+ def destroy_child_association
+ child_class = send(subtype_column.to_sym).constantize
+ if child = child_class.find_by_id(id)
+ child.delete
+ end
+ rescue NameError => e
+ # TODO log error
+ end
+
+ def find_by_subtype(*args)
+ super || send("find_by_#{subtype_column}", *args)
+ end
+ end
end
end
end
View
47 spec/active_record/child_spec.rb
@@ -2,46 +2,7 @@
describe MultipleTableInheritance::ActiveRecord::Child do
context 'retrieving records' do
- it 'should only fetch subtypes' do
- subtypes = Employee.all.collect(&:subtype).uniq
- subtypes.each do |subtype|
- ['Programmer', 'Manager'].should include(subtype)
- end
- end
-
- it 'should fetch all child records' do
- pending "find_by_sql_without_inherit.size.should == find_by_sql_with_inherit.size"
- end
-
- context 'an invalid subtype is included' do
- it 'should return successfully' do
- pending "error should not be thrown"
- end
-
- it 'should generate log entry' do
- pending "logger.error should have been called"
- end
- end
-
- it 'should maintain result order' do
- pending "find_by_sql_without_inherit.collect(&:id).should == find_by_sql_with_inherit.collect(&:id)"
- end
-
- context 'default subtype used' do
- pending "test_everything"
- end
-
- context 'custom subtype used' do
- pending "test_everything"
- end
-
- it 'should work with namespaced classes' do
- pending "test_everything"
- end
-
- it 'should inherit parent methods' do
- pending 'todo'
- end
+ pending "todo"
end
context 'creating records' do
@@ -55,4 +16,10 @@
context 'deleting records' do
pending "todo"
end
+
+ context 'when instructed to inherit parent methods' do
+ it 'should inherit parent methods' do
+ pending "todo"
+ end
+ end
end
View
11 spec/active_record/helper_spec.rb
@@ -0,0 +1,11 @@
+require 'spec_helper'
+
+describe MultipleTableInheritanceSpecHelper do
+ it 'should allow records to be found without inheritance' do
+ pending "find_without_inheritance is not working as intended"
+ employees = Employee.find_without_inheritance { Employee.all }
+ employees.each do |employee|
+ employee.should be_instance_of(Employee)
+ end
+ end
+end
View
69 spec/active_record/parent_spec.rb
@@ -1,7 +1,72 @@
require 'spec_helper'
describe MultipleTableInheritance::ActiveRecord::Parent do
- it 'should do something' do
- pending "test everything"
+ context 'retrieving records' do
+ it 'should only fetch child records' do
+ Employee.find_each do |employee|
+ employee.should_not be_instance_of(Employee)
+ ['Programmer', 'Manager'].should include(employee.class.to_s)
+ end
+ end
+
+ it 'should fetch all child records' do
+ pending "find_without_inheritance is not working as intended"
+ modified_results = Employee.all
+ original_results = Employee.find_without_inheritance { Employee.all }
+ modified_results.size.should == original_results.size
+ end
+
+ it 'should maintain result order' do
+ pending "find_without_inheritance is not working as intended"
+ modified_results = Employee.order("id desc").all
+ original_results = Employee.find_without_inheritance { Employee.order("id desc").all }
+ modified_results.collect(&:id).should == original_results.collect(&:id)
+ end
+
+ context 'an invalid subtype exists' do
+ before do
+ @employee = Employee.create!(:first_name => 'Sub', :last_name => 'Type', :salary => 50000, :team => @team) do |employee|
+ employee.subtype = 'DoesNotExist'
+ end
+ end
+
+ it 'should return successfully' do
+ @employee.should be_instance_of(Employee)
+ end
+
+ it 'should log an error' do
+ pending "logger.error should have been called"
+ end
+ end
+
+ context 'default subtype used' do
+ pending "test_everything"
+ end
+
+ context 'custom subtype used' do
+ pending "test_everything"
+ end
+
+ context 'namespaced classes are being used' do
+ pending "test_everything"
+ end
+ end
+
+ context 'deleting records' do
+ before do
+ programmer = Programmer.create!(:first_name => 'Billy', :last_name => 'Ray', :salary => 50000, :team => @team)
+ @employee = programmer.employee
+ @employee_id = programmer.id
+ end
+
+ it 'should delete the parent record' do
+ @employee.destroy.should be_true
+ Employee.find_by_id(@employee_id).should be_nil
+ end
+
+ it 'should delete the child record' do
+ @employee.destroy.should be_true
+ Programmer.find_by_id(@employee_id).should be_nil
+ end
end
end
View
17 spec/spec_helper.rb
@@ -1,8 +1,21 @@
require 'active_record'
require 'database_cleaner'
-require File.expand_path(File.join(File.dirname(__FILE__), '../lib/multiple_table_inheritance'))
+require 'multiple_table_inheritance'
+
+MultipleTableInheritance::ActiveRecord::Parent::ClassMethods.module_eval do
+ def find_without_inheritance(&block)
+ # remove_method :find_by_sql
+ extend ActiveRecord::Querying
+ result = yield
+ extend MultipleTableInheritance::ActiveRecord::Parent::FinderMethods
+ result
+ end
+end
+
+MultipleTableInheritance::Railtie.insert
+
require 'support/tables'
-require 'support/classes'
+require 'support/models'
module MultipleTableInheritanceSpecHelper
def mock_everything
View
15 spec/support/classes.rb → spec/support/models.rb
@@ -1,38 +1,39 @@
-class ::Employee < ActiveRecord::Base
+class Employee < ActiveRecord::Base
acts_as_superclass
- attr_accessible :first_name, :last_name, :salary
+ attr_accessible :first_name, :last_name, :salary, :team, :team_id
belongs_to :team
validates :first_name, :presence => true
validates :last_name, :presence => true
validates :salary, :presence => true, :numericality => { :min => 0 }
end
-class ::Programmer < ActiveRecord::Base
+class Programmer < ActiveRecord::Base
inherits_from :employee
+ attr_accessible :languages, :language_ids
has_many :known_languages
has_many :languages, :through => :known_languages
end
-class ::Manager < ActiveRecord::Base
+class Manager < ActiveRecord::Base
inherits_from :employee
attr_accessible :bonus
validates :bonus, :numericality => true
end
-class ::Team < ActiveRecord::Base
+class Team < ActiveRecord::Base
attr_accessible :name, :description
has_many :employees
validates :name, :presence => true, :uniqueness => true
end
-class ::Language < ActiveRecord::Base
+class Language < ActiveRecord::Base
attr_accessible :name
has_many :known_languages
has_many :programmers, :through => :known_languages
validates :name, :presence => true, :uniqueness => true
end
-class ::KnownLanguage < ActiveRecord::Base
+class KnownLanguage < ActiveRecord::Base
belongs_to :programmer
belongs_to :language
validates :programmer_id, :presence => true
View
4 spec/support/tables.rb
@@ -1,7 +1,3 @@
-require 'multiple_table_inheritance/railtie'
-
-MultipleTableInheritance::Railtie.insert
-
ActiveRecord::Base.establish_connection(
:adapter => 'sqlite3',
:database => File.expand_path(File.join(File.dirname(__FILE__), '../../db/multiple_table_inheritance.db'))
Please sign in to comment.
Something went wrong with that request. Please try again.