active_record-mti 0.3.2 → 0.4.0.pre.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -6
- data/{LICENSE.txt → LICENSE} +0 -0
- data/README.md +47 -10
- data/lib/active_record/mti.rb +56 -56
- data/lib/active_record/mti/config.rb +26 -0
- data/lib/active_record/mti/connection_adapters/postgresql/adapter.rb +0 -8
- data/lib/active_record/mti/connection_adapters/postgresql/schema_statements.rb +30 -11
- data/lib/active_record/mti/core_extension.rb +170 -0
- data/lib/active_record/mti/railtie.rb +9 -4
- data/lib/active_record/mti/relation.rb +95 -0
- data/lib/active_record/mti/schema_dumper.rb +4 -4
- data/lib/active_record/mti/table.rb +19 -0
- data/lib/active_record/mti/table_oid.rb +6 -0
- data/lib/active_record/mti/version.rb +1 -1
- data/lib/core_ext/array.rb +14 -0
- data/lib/core_ext/hash.rb +1 -3
- data/lib/core_ext/thread.rb +14 -0
- metadata +94 -95
- data/.gitignore +0 -78
- data/.rspec +0 -2
- data/.travis.yml +0 -38
- data/Gemfile +0 -21
- data/Rakefile +0 -6
- data/active_record-mti.gemspec +0 -42
- data/gemfiles/activerecord-4.0.Gemfile +0 -3
- data/gemfiles/activerecord-4.1.Gemfile +0 -3
- data/gemfiles/activerecord-4.2.Gemfile +0 -3
- data/gemfiles/activerecord-5.0.Gemfile +0 -3
- data/gemfiles/activerecord-5.1.Gemfile +0 -3
- data/lib/active_record/mti/calculations.rb +0 -23
- data/lib/active_record/mti/inheritance.rb +0 -127
- data/lib/active_record/mti/model_schema.rb +0 -55
- data/lib/active_record/mti/query_methods.rb +0 -40
- data/lib/active_record/mti/querying.rb +0 -7
- data/lib/active_record/mti/registry.rb +0 -23
- data/spec/active_record/mti/calculations_spec.rb +0 -56
- data/spec/active_record/mti/inheritance_spec.rb +0 -184
- data/spec/active_record/mti/model_schema_spec.rb +0 -11
- data/spec/active_record/mti/query_methods_spec.rb +0 -12
- data/spec/active_record/mti/schema_dumper_spec.rb +0 -22
- data/spec/active_record/mti_spec.rb +0 -24
- data/spec/active_record/sti/inheritance_spec.rb +0 -24
- data/spec/spec_helper.rb +0 -28
- data/spec/support/rails/app/models/admin.rb +0 -3
- data/spec/support/rails/app/models/comment.rb +0 -4
- data/spec/support/rails/app/models/post.rb +0 -4
- data/spec/support/rails/app/models/transportation/military/vehicle.rb +0 -7
- data/spec/support/rails/app/models/transportation/truck.rb +0 -5
- data/spec/support/rails/app/models/transportation/vehicle.rb +0 -4
- data/spec/support/rails/app/models/user.rb +0 -6
- data/spec/support/rails/config/database.yml +0 -4
- data/spec/support/rails/config/routes.rb +0 -3
- data/spec/support/rails/db/schema.rb +0 -51
- data/spec/support/rails/log/.gitignore +0 -1
- data/spec/support/rails/public/favicon.ico +0 -0
@@ -1,23 +0,0 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module MTI
|
3
|
-
module Registry
|
4
|
-
|
5
|
-
mattr_accessor :tableoids
|
6
|
-
self.tableoids = { ActiveRecord::Base => false }
|
7
|
-
|
8
|
-
def self.[]=(klass, tableoid)
|
9
|
-
ActiveRecord::MTI.logger.debug "Adding #{klass} to MTI list with #{tableoid}"
|
10
|
-
tableoids[klass] = tableoid
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.find_mti_class(tableoid)
|
14
|
-
tableoids.key(tableoid)
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.tableoid?(klass)
|
18
|
-
tableoids[klass]
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,56 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ActiveRecord::MTI::Calculations do
|
4
|
-
|
5
|
-
context 'when an exception occurs' do
|
6
|
-
it 'does not continue to adversely affect additional queries' do
|
7
|
-
Admin.create(email: 'bob')
|
8
|
-
expect{ Admin.joins(Transportation::Vehicle).count }.to raise_error(RuntimeError)
|
9
|
-
expect(Thread.current['skip_tableoid_cast']).to_not eq(true)
|
10
|
-
expect(Admin.count).to eq(1)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
context "don't project tableoid on" do
|
15
|
-
it "grouping" do
|
16
|
-
|
17
|
-
Admin.create(email: 'foo@bar.baz', god_powers: 3)
|
18
|
-
Admin.create(email: 'foo@bar.baz', god_powers: 3)
|
19
|
-
Admin.create(email: 'foo24@bar.baz', god_powers: 3)
|
20
|
-
|
21
|
-
grouped_count = Admin.group(:email).count
|
22
|
-
|
23
|
-
expect(grouped_count['foo24@bar.baz']).to eq(1)
|
24
|
-
expect(grouped_count['foo@bar.baz']).to eq(2)
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
it "count calculations" do
|
29
|
-
|
30
|
-
Admin.create(email: 'foo@bar.baz', god_powers: 3)
|
31
|
-
Admin.create(email: 'foo@bar.baz', god_powers: 3)
|
32
|
-
Admin.create(email: 'foo24@bar.baz', god_powers: 3)
|
33
|
-
|
34
|
-
expect(Admin.count(:email)).to eq(3)
|
35
|
-
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
context "projects tableoid" do
|
40
|
-
it "and groups tableoid when selecting :tableoid" do
|
41
|
-
sql = Admin.select(:email, :tableoid).group(:email).to_sql
|
42
|
-
|
43
|
-
expect(sql).to match(/SELECT .*, \"admins\".\"tableoid\" AS tableoid FROM \"admins\"/)
|
44
|
-
|
45
|
-
expect(sql).to match(/GROUP BY .*, \"admins\".\"tableoid\"/)
|
46
|
-
end
|
47
|
-
|
48
|
-
it "when grouping :tableoid" do
|
49
|
-
sql = Admin.select(:email).group(:email, :tableoid).to_sql
|
50
|
-
|
51
|
-
expect(sql).to match(/SELECT .*, \"admins\".\"tableoid\" AS tableoid FROM \"admins\"/)
|
52
|
-
|
53
|
-
expect(sql).to match(/GROUP BY .*, \"admins\".\"tableoid\"/)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
@@ -1,184 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ActiveRecord::MTI::Inheritance do
|
4
|
-
|
5
|
-
it "creates a column even if class doesn't respond to :attribute" do
|
6
|
-
allow(Admin).to receive(:respond_to?).with(:attribute).and_return(false)
|
7
|
-
|
8
|
-
ActiveRecord::MTI::Registry.tableoids[Admin] = nil
|
9
|
-
|
10
|
-
expect(Admin.using_multi_table_inheritance?).to eq(true)
|
11
|
-
end
|
12
|
-
|
13
|
-
it "warns of deprication when using old `uses_mti`" do
|
14
|
-
expect { Admin.uses_mti }.to output("DEPRECATED - `uses_mti` is no longer needed (nor has any effect)\n").to_stderr
|
15
|
-
end
|
16
|
-
|
17
|
-
context 'class definition' do
|
18
|
-
|
19
|
-
describe 'for classes that use MTI' do
|
20
|
-
|
21
|
-
it 'has non-nil mti_type_column' do
|
22
|
-
expect(Admin.mti_type_column).to_not be_nil
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'has true tableoid_column' do
|
26
|
-
expect(Admin.tableoid_column).to eq(true)
|
27
|
-
end
|
28
|
-
|
29
|
-
it "doesn't check inheritance multiple times" do
|
30
|
-
# Due to the anonymous class ("god = Class.new(Admin)") rspec can't properly distinquish
|
31
|
-
# between the two classes. So at most 2 times!
|
32
|
-
expect(Admin).to receive(:check_inheritance_of).and_call_original.at_most(2).times
|
33
|
-
|
34
|
-
Admin.create(email: 'foo@bar.baz', god_powers: 3)
|
35
|
-
Admin.create(email: 'foo2@bar.baz', god_powers: 3)
|
36
|
-
Admin.create(email: 'foo24@bar.baz', god_powers: 3)
|
37
|
-
Admin.create(email: 'foo246@bar.baz', god_powers: 3)
|
38
|
-
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
describe "for classes that don't use MTI" do
|
43
|
-
|
44
|
-
it 'has nil tableoid_column' do
|
45
|
-
expect(Post.tableoid_column).to be_nil
|
46
|
-
end
|
47
|
-
|
48
|
-
it 'has nil mti_type_column' do
|
49
|
-
expect(Post.mti_type_column).to be_nil
|
50
|
-
end
|
51
|
-
|
52
|
-
it "doesn't check inheritance multiple times" do
|
53
|
-
# ActiveRecord::MTI::Inheritance.register(Post, false)
|
54
|
-
expect(Post).to receive(:check_inheritance_of).and_call_original.exactly(1).times
|
55
|
-
|
56
|
-
Post.create(title: 'foo@bar.baz')
|
57
|
-
Post.create(title: 'foo2@bar.baz')
|
58
|
-
Post.create(title: 'foo24@bar.baz')
|
59
|
-
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
end
|
64
|
-
|
65
|
-
context 'default inheritance_column model' do
|
66
|
-
let!(:user) { User.create(email: 'foo@bar.baz') }
|
67
|
-
let!(:admin) { Admin.create(email: 'foo@bar.baz', god_powers: 3) }
|
68
|
-
|
69
|
-
it 'casts properly' do
|
70
|
-
user = User.first
|
71
|
-
expect(user.class).to eq(User)
|
72
|
-
end
|
73
|
-
|
74
|
-
describe 'base class querying' do
|
75
|
-
it 'casts children properly' do
|
76
|
-
users = User.all
|
77
|
-
expect(users.select{ |u| u.is_a?(Admin) }.count).to eql(1)
|
78
|
-
end
|
79
|
-
|
80
|
-
xit 'deserializes children with child specific data' do
|
81
|
-
my_admin = User.find(admin.id)
|
82
|
-
expect(my_admin.god_powers).to eql(3)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
describe 'has the correct count for' do
|
87
|
-
it 'parents' do
|
88
|
-
users = User.all
|
89
|
-
expect(users.count).to eq(2)
|
90
|
-
end
|
91
|
-
|
92
|
-
it 'children' do
|
93
|
-
admins = Admin.all
|
94
|
-
expect(admins.count).to eq(1)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
describe 'dynamic class creation' do
|
99
|
-
it 'infers the table_name from superclass not base_class' do
|
100
|
-
god = Class.new(Admin)
|
101
|
-
expect(god.table_name).to eql(Admin.table_name)
|
102
|
-
end
|
103
|
-
|
104
|
-
it 'infers the table_name when defined dynamically' do
|
105
|
-
|
106
|
-
class Scrub < ActiveRecord::Base
|
107
|
-
const_set(:All, Class.new(Scrub) do |klass|
|
108
|
-
class_eval <<-AAA
|
109
|
-
self.table_name = 'scrubs/all'
|
110
|
-
AAA
|
111
|
-
end)
|
112
|
-
end
|
113
|
-
|
114
|
-
expect(Scrub::All.table_name).to eq('scrubs/all')
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
describe 'views' do
|
120
|
-
before(:each) do
|
121
|
-
|
122
|
-
User.connection.execute <<-SQL
|
123
|
-
CREATE OR REPLACE VIEW "users_all"
|
124
|
-
AS SELECT * FROM "users"
|
125
|
-
SQL
|
126
|
-
|
127
|
-
class UserView < User
|
128
|
-
self.table_name = "users_all"
|
129
|
-
end
|
130
|
-
|
131
|
-
end
|
132
|
-
|
133
|
-
if ActiveRecord::Base.connection.version >= Gem::Version.new('9.4')
|
134
|
-
it 'allows creation pass-through' do
|
135
|
-
|
136
|
-
UserView.create(email: 'dale@twilightcoders.net')
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
describe 'dynamic class creation' do
|
142
|
-
it 'infers the table_name from superclass not base_class' do
|
143
|
-
God = Class.new(Admin)
|
144
|
-
Hacker = Class.new(Admin)
|
145
|
-
|
146
|
-
expect(God.table_name).to eql(Admin.table_name)
|
147
|
-
expect(Hacker.table_name).to eql('admin/hackers')
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
describe 'custom inheritance_column model' do
|
152
|
-
let!(:vehicle) { Transportation::Vehicle.create(color: :red) }
|
153
|
-
let!(:truck) { Transportation::Truck.create(color: :blue, bed_size: 10) }
|
154
|
-
|
155
|
-
describe 'inheritance_column' do
|
156
|
-
xit 'should set the custom column correctly' do
|
157
|
-
expect(vehicle.type).to eql('vehicles')
|
158
|
-
expect(truck.type).to eql('trucks')
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
describe 'base class querying' do
|
163
|
-
it 'casts children properly' do
|
164
|
-
expect(Transportation::Vehicle.all.select{ |v| v.is_a?(Transportation::Truck) }.count).to eql(1)
|
165
|
-
end
|
166
|
-
|
167
|
-
xit 'deserializes children with child specific data' do
|
168
|
-
my_truck = Transportation::Vehicle.find(truck.id)
|
169
|
-
expect(my_truck.bed_size).to eql(10)
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
describe 'has the correct count for' do
|
174
|
-
it 'parents' do
|
175
|
-
expect(Transportation::Vehicle.count).to eql(2)
|
176
|
-
end
|
177
|
-
|
178
|
-
it 'children' do
|
179
|
-
expect(Transportation::Truck.count).to eql(1)
|
180
|
-
end
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
end
|
@@ -1,11 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ActiveRecord::MTI::ModelSchema do
|
4
|
-
|
5
|
-
it 'rescues suffix' do
|
6
|
-
f = ActiveRecord::ModelSchema::ClassMethods
|
7
|
-
allow_any_instance_of(f).to receive(:full_table_name_suffix).and_raise(NoMethodError)
|
8
|
-
expect( Admin.full_table_name_suffix ).to eq("")
|
9
|
-
end
|
10
|
-
|
11
|
-
end
|
@@ -1,12 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ActiveRecord::MTI::QueryMethods do
|
4
|
-
|
5
|
-
context "queries" do
|
6
|
-
it "select tableoid" do
|
7
|
-
sql = Admin.all.to_sql
|
8
|
-
expect(sql).to match(/SELECT .*, \"admins\".\"tableoid\" AS tableoid FROM \"admins\"/)
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ActiveRecord::MTI::SchemaDumper do
|
4
|
-
|
5
|
-
before(:each) do
|
6
|
-
ActiveRecord::SchemaMigration.create_table
|
7
|
-
end
|
8
|
-
|
9
|
-
let(:hacker_sql) {
|
10
|
-
<<-FOO
|
11
|
-
create_table "admin/hackers", inherits: 'admins' do |t|
|
12
|
-
end
|
13
|
-
FOO
|
14
|
-
}
|
15
|
-
|
16
|
-
it 'does not dump indexes for child table' do
|
17
|
-
stream = StringIO.new
|
18
|
-
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
19
|
-
|
20
|
-
expect(stream.string).to include(hacker_sql)
|
21
|
-
end
|
22
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ActiveRecord::MTI do
|
4
|
-
|
5
|
-
context 'helper' do
|
6
|
-
|
7
|
-
describe '#testify' do
|
8
|
-
it "returns true for truthy values" do
|
9
|
-
expect(ActiveRecord::MTI.testify('f')).to eq(false)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
it "root has the right value" do
|
14
|
-
expect(ActiveRecord::MTI.root).not_to be_nil
|
15
|
-
end
|
16
|
-
|
17
|
-
it "recovers if oid class candidate is not constantizable" do
|
18
|
-
ActiveRecord::MTI.oid_class_candidates.unshift("IDontExist")
|
19
|
-
expect(ActiveRecord::MTI.find_oid_class).not_to be_nil
|
20
|
-
end
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ActiveRecord::Inheritance do
|
4
|
-
|
5
|
-
context 'class definition' do
|
6
|
-
|
7
|
-
describe 'for classes that use STI' do
|
8
|
-
it "doesn't check inheritance multiple times" do
|
9
|
-
|
10
|
-
Transportation::Military::Vehicle.create(color: :red)
|
11
|
-
Transportation::Military::Vehicle.create(color: :blue)
|
12
|
-
Transportation::Military::Vehicle.create(color: :green)
|
13
|
-
Transportation::Military::Vehicle.create(color: :gold)
|
14
|
-
|
15
|
-
vehicle = Transportation::Military::Vehicle.first
|
16
|
-
expect(vehicle.class.name).to eq('Transportation::Military::Vehicle')
|
17
|
-
expect(vehicle.color).to eq('red')
|
18
|
-
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
ENV['RAILS_ENV'] = 'test'
|
2
|
-
|
3
|
-
require 'database_cleaner'
|
4
|
-
require 'combustion'
|
5
|
-
|
6
|
-
require 'simplecov'
|
7
|
-
SimpleCov.start do
|
8
|
-
add_filter 'spec'
|
9
|
-
end
|
10
|
-
|
11
|
-
Combustion.path = 'spec/support/rails'
|
12
|
-
Combustion.initialize! :active_record
|
13
|
-
|
14
|
-
RSpec.configure do |config|
|
15
|
-
config.order = 'random'
|
16
|
-
|
17
|
-
# Configure the DatabaseCleaner
|
18
|
-
config.before(:suite) do
|
19
|
-
DatabaseCleaner.strategy = :transaction
|
20
|
-
DatabaseCleaner.clean_with(:truncation)
|
21
|
-
end
|
22
|
-
|
23
|
-
config.around(:each) do |example|
|
24
|
-
DatabaseCleaner.cleaning do
|
25
|
-
example.run
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|