multiple_table_inheritance 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -10,58 +10,57 @@ describe MultipleTableInheritance::Parent do
10
10
  end
11
11
  end
12
12
 
13
- context 'non-namespaced classes' do
13
+ context 'non-namespaced classes with default subtype' do
14
14
  context 'retrieving records' do
15
15
  before do
16
16
  mock_employees!
17
17
  end
18
-
18
+
19
19
  it 'should retrieve child records' do
20
- Employee.find_each do |programmer_or_manager|
21
- programmer_or_manager.should_not be_instance_of(Employee)
22
- ['Programmer', 'Manager'].should include(programmer_or_manager.class.to_s)
20
+ Employee.find_each do |employee_subtype|
21
+ employee_subtype.should_not be_instance_of(Employee)
22
+ ['Programmer', 'Manager', 'Janitor'].should include(employee_subtype.class.to_s)
23
23
  end
24
24
  end
25
-
25
+
26
26
  it 'should allow access to parent record' do
27
- programmer_or_manager = Employee.first
28
- programmer_or_manager.employee.should be_instance_of(Employee)
27
+ employee_subtype = Employee.first
28
+ employee_subtype.employee.should be_instance_of(Employee)
29
29
  end
30
-
30
+
31
31
  it 'should include all records' do
32
32
  modified_results = Employee.all
33
33
  original_results = Employee.as_supertype.all
34
34
  modified_results.size.should == original_results.size
35
35
  end
36
-
36
+
37
37
  it 'should maintain result order' do
38
38
  modified_results = Employee.order("id desc").all
39
39
  original_results = Employee.as_supertype.order("id desc").all
40
40
  modified_results.collect(&:id).should == original_results.collect(&:id)
41
41
  end
42
-
42
+
43
43
  context 'associations preloading' do
44
44
  context 'is enabled' do
45
45
  before do
46
- @programmer_or_manager = Employee.includes(:team).first
46
+ @employee_subtype = Employee.includes(:team).first
47
47
  end
48
-
48
+
49
49
  it 'should not perform an extra find' do
50
- pending "ensure that team is not retrieved from the database"
51
- Team.any_instance.should_not_receive(:find_by_sql)
52
- @programmer_or_manager.employee.team
50
+ Team.should_not_receive(:find_by_sql)
51
+ @employee_subtype.employee.team
53
52
  end
54
53
  end
55
-
54
+
56
55
  context 'is disabled' do
57
56
  before do
58
- @programmer_or_manager = Employee.first
57
+ @employee_subtype = Employee.first
59
58
  end
60
-
59
+
61
60
  it 'should not perform an extra find' do
62
- pending "ensure that team is retrieved from the database"
63
- Team.any_instance.should_receive(:find_by_sql).at_least(:once)
64
- @programmer_or_manager.employee.team
61
+ pending "appears to be an rspec bug preventing this from working"
62
+ Team.should_not_receive(:find_by_sql).with(any_args).once
63
+ @employee_subtype.employee.team
65
64
  end
66
65
  end
67
66
  end
@@ -69,7 +68,7 @@ describe MultipleTableInheritance::Parent do
69
68
 
70
69
  context 'deleting records' do
71
70
  before do
72
- programmer = Programmer.create!(:first_name => 'Billy', :last_name => 'Ray', :salary => 50000, :team => @team)
71
+ programmer = Programmer.create!(:first_name => 'Billy', :last_name => 'Ray', :salary => 50000)
73
72
  @employee = programmer.employee
74
73
  @employee_id = programmer.id
75
74
  end
@@ -87,30 +86,45 @@ describe MultipleTableInheritance::Parent do
87
86
 
88
87
  context 'an invalid subtype exists' do
89
88
  before do
90
- @employee = Employee.create!(:first_name => 'Sub', :last_name => 'Type', :salary => 50000, :team => @team) do |employee|
89
+ @employee = Employee.create!(:first_name => 'Sub', :last_name => 'Type', :salary => 50000) do |employee|
91
90
  employee.subtype = 'DoesNotExist'
92
91
  end
93
92
  end
94
93
 
95
- it 'should return successfully' do
96
- @employee.should be_instance_of(Employee)
94
+ it 'should not have errors' do
95
+ @employee.errors.messages.should be_empty
97
96
  end
98
97
 
99
- it 'should log an error' do
100
- pending "logger.error should have been called"
98
+ it 'should have been saved' do
99
+ @employee.should_not be_new_record
100
+ end
101
+
102
+ context 'retrieving saved record' do
103
+ before do
104
+ @record = Employee.find_by_id(@employee.id)
105
+ end
106
+
107
+ it 'should not return the parent model instance' do
108
+ @record.should be_nil
109
+ end
110
+
111
+ context 'logger exists on model' do
112
+ before do
113
+ require 'logger'
114
+ @logger = Logger.new(nil)
115
+ ActiveRecord::Base.stub(:logger).and_return(@logger)
116
+ end
117
+
118
+ it 'should log a warning' do
119
+ @logger.should_receive(:warn)
120
+ Employee.find_by_id(@employee.id)
121
+ end
122
+ end
101
123
  end
102
- end
103
-
104
- context 'default subtype' do
105
- pending "test_everything"
106
- end
107
-
108
- context 'custom subtype' do
109
- pending "test_everything"
110
124
  end
111
125
  end
112
126
 
113
- context 'namespaced classes' do
127
+ context 'namespaced classes with custom subtype' do
114
128
  context 'retrieving records' do
115
129
  before(:each) do
116
130
  mock_pets!
data/spec/spec_helper.rb CHANGED
@@ -10,7 +10,7 @@ require 'support/models'
10
10
  module MultipleTableInheritanceSpecHelper
11
11
  def mock_employees!
12
12
  3.times do |i|
13
- team = Team.create!(:name => "Team#{i}")
13
+ team = Team.create!(:name => "Team #{i}")
14
14
  language = Language.create!(:name => "Java 1.#{i + 4}")
15
15
  end
16
16
 
@@ -28,6 +28,13 @@ module MultipleTableInheritanceSpecHelper
28
28
  :salary => 70000 + (i * 2500),
29
29
  :team => Team.first,
30
30
  :bonus => i * 2500) # manager-specific field
31
+
32
+ Janitor.create!(
33
+ :first_name => "Phil",
34
+ :last_name => "Moore #{i}",
35
+ :salary => 40000 + (i * 1000),
36
+ :team => Team.last,
37
+ :preferred_cleaner => %w{Comet Windex Swiffer}[i % 3]) # janitor-specific field
31
38
  end
32
39
  end
33
40
 
@@ -39,15 +46,13 @@ module MultipleTableInheritanceSpecHelper
39
46
 
40
47
  dog = Pet::Dog.create!(:name => "Rover #{i}") do |dog|
41
48
  dog.owner = owner
42
- dog.favorite_toy = "#{i + 1}-inch Bone"
49
+ dog.favorite_toy = "#{i + 1}-inch Bone" # dog-specific field
43
50
  end
44
- puts dog.inspect
45
51
 
46
52
  cat = Pet::Cat.create!(:name => "Mittens #{i}") do |cat|
47
53
  cat.owner = owner
48
- cat.longest_nap = 100 + i
54
+ cat.longest_nap = 100 + i # cat-specific field
49
55
  end
50
- puts cat.inspect
51
56
  end
52
57
  end
53
58
  end
@@ -1,6 +1,7 @@
1
- ###############################################
2
- # Non-namespaced models
3
- ###############################################
1
+ #########################################################
2
+ # Non-namespaced models with mass-assignment security
3
+ # everywhere or only on parent.
4
+ #########################################################
4
5
 
5
6
  class Employee < ActiveRecord::Base
6
7
  acts_as_superclass
@@ -9,21 +10,29 @@ class Employee < ActiveRecord::Base
9
10
  validates :first_name, :presence => true
10
11
  validates :last_name, :presence => true
11
12
  validates :salary, :presence => true, :numericality => { :min => 0 }
13
+
14
+ def give_raise!(amount)
15
+ Employee.update_counters self.id, :salary => amount
16
+ end
12
17
  end
13
18
 
14
19
  class Programmer < ActiveRecord::Base
15
- inherits_from :employee
20
+ inherits_from :employee #, :methods => true
16
21
  attr_accessible :languages, :language_ids
17
22
  has_many :known_languages
18
23
  has_many :languages, :through => :known_languages
19
24
  end
20
25
 
21
26
  class Manager < ActiveRecord::Base
22
- inherits_from :employee
27
+ inherits_from :employee #, :methods => true
23
28
  attr_accessible :bonus
24
29
  validates :bonus, :numericality => true
25
30
  end
26
31
 
32
+ class Janitor < ActiveRecord::Base
33
+ inherits_from :employee #, :methods => true
34
+ end
35
+
27
36
  class Team < ActiveRecord::Base
28
37
  attr_accessible :name, :description
29
38
  has_many :employees
@@ -44,9 +53,32 @@ class KnownLanguage < ActiveRecord::Base
44
53
  validates :language_id, :presence => true, :uniqueness => { :scope => :programmer_id }
45
54
  end
46
55
 
47
- ###############################################
48
- # Namespaced models
49
- ###############################################
56
+ #########################################################
57
+ # Non-namespaced models with mass assignment security
58
+ # only on children or not specified.
59
+ #########################################################
60
+
61
+ class Clothing < ActiveRecord::Base
62
+ acts_as_superclass
63
+ validates :color, :presence => true
64
+ end
65
+
66
+ class Shirt < ActiveRecord::Base
67
+ inherits_from :clothing
68
+ attr_accessible :size
69
+ validates :size, :presence => true
70
+ end
71
+
72
+ class Pants < ActiveRecord::Base
73
+ inherits_from :clothing
74
+ validates :waist_size, :presence => true
75
+ validates :length, :presence => true
76
+ end
77
+
78
+ #########################################################
79
+ # Namespaced models with mass assignment security
80
+ # everywhere or only on parent.
81
+ #########################################################
50
82
 
51
83
  module Pet
52
84
  def self.table_name_prefix
@@ -67,13 +99,47 @@ module Pet
67
99
  belongs_to :owner
68
100
  validates :owner_id, :presence => true
69
101
  validates :name, :presence => true
102
+
103
+ def rename!(new_name)
104
+ update_attributes!(:name => new_name)
105
+ end
70
106
  end
71
107
 
72
- class Dog < ActiveRecord::Base
108
+ class Cat < ActiveRecord::Base
73
109
  inherits_from :pet, :class_name => 'Pet::Pet'
110
+ attr_accessible :longest_nap
74
111
  end
75
112
 
76
113
  class Dog < ActiveRecord::Base
77
114
  inherits_from :pet, :class_name => 'Pet::Pet'
78
115
  end
79
116
  end
117
+
118
+ #########################################################
119
+ # Namespaced models with mass assignment security
120
+ # only on children or not specified.
121
+ #########################################################
122
+
123
+ module Store
124
+ def self.table_name_prefix
125
+ 'store_'
126
+ end
127
+
128
+ class Furniture < ActiveRecord::Base
129
+ acts_as_superclass
130
+ validates :brand, :presence => true
131
+ validates :name, :presence => true
132
+ end
133
+
134
+ class Bed < ActiveRecord::Base
135
+ inherits_from :furniture, :class_name => 'Store::Furniture'
136
+ validates :size, :presence => true
137
+ end
138
+
139
+ class Table < ActiveRecord::Base
140
+ inherits_from :furniture, :class_name => 'Store::Furniture'
141
+ attr_accessible :chairs, :color
142
+ validates :chairs, :presence => true, :numericality => { :min => 1 }
143
+ validates :color, :presence => true
144
+ end
145
+ end
@@ -1,14 +1,18 @@
1
- ActiveRecord::Base.establish_connection(
2
- :adapter => 'sqlite3',
3
- :database => File.expand_path(File.join(File.dirname(__FILE__), '../../db/multiple_table_inheritance.db'))
4
- )
1
+ db_path = File.expand_path(File.join(File.dirname(__FILE__), '../../db'))
2
+ db_file = File.join(db_path, 'multiple_table_inheritance.db')
5
3
 
4
+ # Create/Overwrite database file
5
+ File.delete(db_file) if File.exist?(db_file)
6
+ Dir.mkdir(db_path) unless File.directory?(db_path)
7
+ File.open(db_file, 'w') {}
8
+
9
+ # Open a database connection
10
+ ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => db_file)
6
11
  conn = ActiveRecord::Base.connection
7
12
 
8
- TABLES = ['employees', 'programmers', 'managers', 'teams', 'languages', 'known_languages', 'pet_owners', 'pet_pets', 'pet_dogs', 'pet_cats'].freeze
9
- TABLES.each do |table|
10
- conn.execute "DROP TABLE IF EXISTS '#{table}'"
11
- end
13
+ #########################################################
14
+ # Employee entities
15
+ #########################################################
12
16
 
13
17
  conn.create_table :employees do |t|
14
18
  t.string :subtype, :null => false
@@ -25,6 +29,10 @@ conn.create_table :managers, :inherits => :employee do |t|
25
29
  t.integer :bonus
26
30
  end
27
31
 
32
+ conn.create_table :janitors, :inherits => :employee do |t|
33
+ t.string :preferred_cleaner
34
+ end
35
+
28
36
  conn.create_table :teams do |t|
29
37
  t.string :name, :null => false
30
38
  end
@@ -38,6 +46,28 @@ conn.create_table :known_languages do |t|
38
46
  t.integer :language_id, :null => false
39
47
  end
40
48
 
49
+ #########################################################
50
+ # Clothing entities
51
+ #########################################################
52
+
53
+ conn.create_table :clothings do |t|
54
+ t.string :subtype, :null => false
55
+ t.string :color, :null => false
56
+ end
57
+
58
+ conn.create_table :shirts, :inherits => :clothing do |t|
59
+ t.string :size, :limit => 2, :null => false
60
+ end
61
+
62
+ conn.create_table :pants, :inherits => :clothing do |t|
63
+ t.integer :waist_size, :null => false
64
+ t.integer :length, :null => false
65
+ end
66
+
67
+ #########################################################
68
+ # Pet entities
69
+ #########################################################
70
+
41
71
  conn.create_table :pet_owners do |t|
42
72
  t.string :first_name, :null => false
43
73
  t.string :last_name, :null => false
@@ -51,10 +81,29 @@ conn.create_table :pet_pets do |t|
51
81
  t.string :color
52
82
  end
53
83
 
54
- conn.create_table :pet_dogs, :inherits => :pets do |t|
84
+ conn.create_table :pet_dogs, :inherits => :pet do |t|
55
85
  t.string :favorite_toy
56
86
  end
57
87
 
58
- conn.create_table :pet_cats, :inherits => :pets do |t|
88
+ conn.create_table :pet_cats, :inherits => :pet do |t|
59
89
  t.integer :longest_nap
60
90
  end
91
+
92
+ #########################################################
93
+ # Store entities
94
+ #########################################################
95
+
96
+ conn.create_table :store_furnitures do |t|
97
+ t.string :subtype, :null => false
98
+ t.string :brand, :null => false
99
+ t.string :name, :null => false
100
+ end
101
+
102
+ conn.create_table :store_beds, :inherits => :furniture do |t|
103
+ t.string :size, :null => false
104
+ end
105
+
106
+ conn.create_table :store_tables, :inherits => :furniture do |t|
107
+ t.integer :chairs, :null => false
108
+ t.string :color, :null => false
109
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: multiple_table_inheritance
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-11 00:00:00.000000000Z
12
+ date: 2012-03-13 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
16
- requirement: &2161139800 !ruby/object:Gem::Requirement
16
+ requirement: &2153195660 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 3.0.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2161139800
24
+ version_requirements: *2153195660
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: activesupport
27
- requirement: &2161139340 !ruby/object:Gem::Requirement
27
+ requirement: &2153195200 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 3.0.0
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *2161139340
35
+ version_requirements: *2153195200
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec-rails
38
- requirement: &2161138880 !ruby/object:Gem::Requirement
38
+ requirement: &2153194720 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 2.8.0
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *2161138880
46
+ version_requirements: *2153194720
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rspec_tag_matchers
49
- requirement: &2161138420 !ruby/object:Gem::Requirement
49
+ requirement: &2153194240 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 1.0.0
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *2161138420
57
+ version_requirements: *2153194240
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: sqlite3-ruby
60
- requirement: &2161137960 !ruby/object:Gem::Requirement
60
+ requirement: &2153193740 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 1.3.3
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *2161137960
68
+ version_requirements: *2153193740
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: database_cleaner
71
- requirement: &2161137500 !ruby/object:Gem::Requirement
71
+ requirement: &2153142060 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,7 +76,7 @@ dependencies:
76
76
  version: 0.7.1
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *2161137500
79
+ version_requirements: *2153142060
80
80
  description: ActiveRecord plugin designed to allow simple multiple table inheritance.
81
81
  email:
82
82
  - matt@matthuggins.com
@@ -87,6 +87,7 @@ extra_rdoc_files:
87
87
  files:
88
88
  - .gitignore
89
89
  - .rspec
90
+ - .travis.yml
90
91
  - CHANGELOG.md
91
92
  - Gemfile
92
93
  - README.md
@@ -94,13 +95,14 @@ files:
94
95
  - lib/multiple_table_inheritance.rb
95
96
  - lib/multiple_table_inheritance/child.rb
96
97
  - lib/multiple_table_inheritance/child/base.rb
98
+ - lib/multiple_table_inheritance/child/sanitizer.rb
97
99
  - lib/multiple_table_inheritance/migration.rb
98
100
  - lib/multiple_table_inheritance/parent.rb
99
101
  - lib/multiple_table_inheritance/parent/base.rb
100
102
  - lib/multiple_table_inheritance/parent/relation.rb
101
103
  - lib/multiple_table_inheritance/railtie.rb
102
104
  - lib/multiple_table_inheritance/version.rb
103
- - multiiple_table_inheritance.gemspec
105
+ - multiple_table_inheritance.gemspec
104
106
  - spec/active_record/child_spec.rb
105
107
  - spec/active_record/parent_spec.rb
106
108
  - spec/spec_helper.rb