active_record-mti 0.1.1 → 0.2.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/README.md +6 -1
- data/active_record-mti.gemspec +1 -1
- data/lib/active_record/mti.rb +11 -0
- data/lib/active_record/mti/calculations.rb +1 -1
- data/lib/active_record/mti/inheritance.rb +66 -6
- data/lib/active_record/mti/query_methods.rb +5 -3
- data/lib/active_record/mti/railtie.rb +1 -1
- data/lib/active_record/mti/version.rb +1 -1
- metadata +6 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 83f66dc4e6bb45b2ca6a075be93334d2f9e761f3
|
4
|
+
data.tar.gz: 4e4f3ec52bf515e9d9ffdfaab67306b480bbbdd1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0d08825e3d3f51e944963bcf9cf64cf27c16a9b3319fe2ccd50022d26ece1f608cae5f23d6ea8576b2fc98c4859726e72ee39a544aad33d8ebf38b4621528efc
|
7
|
+
data.tar.gz: babb8e13a0371b408f3670059bb5482c4db455dd881c801c4ef1f62ddec542b36d79e0592a5e067a203cc3b2ee7b02e7fe9856bef3a0cc8aee1b1752f22cf696
|
data/README.md
CHANGED
@@ -1,4 +1,9 @@
|
|
1
|
-
|
1
|
+
[](https://rubygems.org/gems/active_record-mti)
|
2
|
+
[](https://travis-ci.org/TwilightCoders/active_record-mti)
|
3
|
+
[](https://codeclimate.com/github/TwilightCoders/active_record-mti)
|
4
|
+
[](https://codeclimate.com/github/TwilightCoders/active_record-mti/coverage)
|
5
|
+
|
6
|
+
# ActiveRecord::MTI
|
2
7
|
|
3
8
|
Allows for true native inheritance of tables in PostgreSQL
|
4
9
|
|
data/active_record-mti.gemspec
CHANGED
@@ -37,7 +37,7 @@ Gem::Specification.new do |spec|
|
|
37
37
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
38
38
|
spec.add_development_dependency 'rake', '~> 10.0'
|
39
39
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
40
|
-
spec.add_development_dependency 'simplecov',
|
40
|
+
spec.add_development_dependency 'simplecov', '~> 0.1'
|
41
41
|
spec.add_development_dependency 'codeclimate-test-reporter', '~> 1.0'
|
42
42
|
spec.add_development_dependency 'database_cleaner', '~> 1.6'
|
43
43
|
|
data/lib/active_record/mti.rb
CHANGED
@@ -14,6 +14,17 @@ require 'active_record/mti/railtie' if defined?(Rails::Railtie)
|
|
14
14
|
module ActiveRecord
|
15
15
|
module MTI
|
16
16
|
|
17
|
+
class << self
|
18
|
+
attr_writer :logger
|
19
|
+
|
20
|
+
def logger
|
21
|
+
@logger ||= Logger.new($stdout).tap do |log|
|
22
|
+
log.progname = self.name
|
23
|
+
log.level = Logger::INFO
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
17
28
|
def self.root
|
18
29
|
@root ||= Pathname.new(File.expand_path('../../', File.dirname(__FILE__)))
|
19
30
|
end
|
@@ -102,7 +102,7 @@ module ActiveRecord
|
|
102
102
|
|
103
103
|
# Remove our cast otherwise PSQL will insist that it be included in the GROUP
|
104
104
|
# Somewhere between line 82 and 101 relation.arel.projections gets reset :/
|
105
|
-
relation.arel.projections.select!{ |p| p
|
105
|
+
relation.arel.projections.select!{ |p| p != tableoid_cast(klass) } if @klass.using_multi_table_inheritance?
|
106
106
|
|
107
107
|
query_builder = relation.arel
|
108
108
|
bind_values = query_builder.bind_values + relation.bind_values
|
@@ -24,6 +24,7 @@ module ActiveRecord
|
|
24
24
|
module MTI
|
25
25
|
module Inheritance
|
26
26
|
extend ActiveSupport::Concern
|
27
|
+
@mti_tableoids = {}
|
27
28
|
|
28
29
|
included do
|
29
30
|
scope :discern_inheritance, -> {
|
@@ -37,6 +38,9 @@ module ActiveRecord
|
|
37
38
|
self.inheritance_column = inheritance_column
|
38
39
|
|
39
40
|
@uses_mti = true
|
41
|
+
@mti_setup = false
|
42
|
+
@mti_tableoid_projection = nil
|
43
|
+
@tableoid_column = nil
|
40
44
|
end
|
41
45
|
|
42
46
|
def using_multi_table_inheritance?(klass = self)
|
@@ -44,15 +48,31 @@ module ActiveRecord
|
|
44
48
|
end
|
45
49
|
|
46
50
|
def uses_mti?
|
47
|
-
|
51
|
+
inheritence_check = check_inheritence_of(@table_name) unless @mti_setup
|
52
|
+
@uses_mti = inheritence_check if @uses_mti.nil?
|
48
53
|
@uses_mti
|
49
54
|
end
|
50
55
|
|
56
|
+
def has_tableoid_column?
|
57
|
+
@tableoid_column != false
|
58
|
+
end
|
59
|
+
|
60
|
+
def mti_tableoid_projection
|
61
|
+
@mti_tableoid_projection
|
62
|
+
end
|
63
|
+
|
64
|
+
def mti_tableoid_projection=(value)
|
65
|
+
@mti_tableoid_projection = value
|
66
|
+
end
|
67
|
+
|
51
68
|
private
|
52
69
|
|
53
70
|
def check_inheritence_of(table_name)
|
71
|
+
ActiveRecord::MTI.logger.debug "Trying to check inheritance of table with no table name (#{self})" unless table_name
|
54
72
|
return nil unless table_name
|
55
73
|
|
74
|
+
ActiveRecord::MTI.logger.debug "Checking inheritance for #{table_name}"
|
75
|
+
|
56
76
|
result = connection.execute <<-SQL
|
57
77
|
SELECT EXISTS (
|
58
78
|
SELECT 1
|
@@ -65,10 +85,40 @@ module ActiveRecord
|
|
65
85
|
);
|
66
86
|
SQL
|
67
87
|
|
88
|
+
uses_inheritence = result.try(:first).try(:values).try(:first) == 't'
|
89
|
+
|
90
|
+
register_tableoid(table_name, uses_inheritence)
|
91
|
+
|
92
|
+
@mti_setup = true
|
68
93
|
# Some versions of PSQL return {"?column?"=>"t"}
|
69
94
|
# instead of {"exists"=>"t"}, so we're saying screw it,
|
70
95
|
# just give me the first value of whatever is returned
|
71
|
-
return
|
96
|
+
return uses_inheritence
|
97
|
+
end
|
98
|
+
|
99
|
+
def register_tableoid(table_name, uses_mti=false)
|
100
|
+
|
101
|
+
tableoid_query = connection.execute(<<-SQL
|
102
|
+
SELECT '#{table_name}'::regclass::oid AS tableoid, (SELECT EXISTS (
|
103
|
+
SELECT 1
|
104
|
+
FROM pg_catalog.pg_attribute
|
105
|
+
WHERE attrelid = '#{table_name}'::regclass
|
106
|
+
AND attname = 'tableoid'
|
107
|
+
AND NOT attisdropped
|
108
|
+
)) AS has_tableoid_column
|
109
|
+
SQL
|
110
|
+
).first
|
111
|
+
tableoid = tableoid_query['tableoid']
|
112
|
+
@tableoid_column = tableoid_query['has_tableoid_column'] == 't'
|
113
|
+
|
114
|
+
if (has_tableoid_column?)
|
115
|
+
ActiveRecord::MTI.logger.debug "#{table_name} has tableoid column!"
|
116
|
+
@mti_tableoid_projection = arel_table[:tableoid].as('tableoid')
|
117
|
+
else
|
118
|
+
@mti_tableoid_projection = nil
|
119
|
+
end
|
120
|
+
|
121
|
+
Inheritance.add_mti(tableoid, self)
|
72
122
|
end
|
73
123
|
|
74
124
|
# Called by +instantiate+ to decide which class to use for a new
|
@@ -76,7 +126,7 @@ module ActiveRecord
|
|
76
126
|
# for a +type+ column and return the corresponding class.
|
77
127
|
def discriminate_class_for_record(record)
|
78
128
|
if using_multi_table_inheritance?(base_class)
|
79
|
-
find_mti_class(record)
|
129
|
+
find_mti_class(record) || base_class
|
80
130
|
elsif using_single_table_inheritance?(record)
|
81
131
|
find_sti_class(record[inheritance_column])
|
82
132
|
else
|
@@ -87,9 +137,11 @@ module ActiveRecord
|
|
87
137
|
# Search descendants for one who's table_name is equal to the returned tableoid.
|
88
138
|
# This indicates the class of the record
|
89
139
|
def find_mti_class(record)
|
90
|
-
|
91
|
-
|
92
|
-
|
140
|
+
if (has_tableoid_column?)
|
141
|
+
Inheritance.find_mti(record['tableoid'])
|
142
|
+
else
|
143
|
+
self
|
144
|
+
end
|
93
145
|
end
|
94
146
|
|
95
147
|
# Type condition only applies if it's STI, otherwise it's
|
@@ -104,8 +156,16 @@ module ActiveRecord
|
|
104
156
|
sti_column.in(sti_names)
|
105
157
|
end
|
106
158
|
end
|
159
|
+
end
|
107
160
|
|
161
|
+
def self.add_mti(tableoid, klass)
|
162
|
+
@mti_tableoids[tableoid.to_s.to_sym] = klass
|
108
163
|
end
|
164
|
+
|
165
|
+
def self.find_mti(tableoid)
|
166
|
+
@mti_tableoids[tableoid.to_s.to_sym]
|
167
|
+
end
|
168
|
+
|
109
169
|
end
|
110
170
|
end
|
111
171
|
end
|
@@ -6,8 +6,10 @@ module ActiveRecord
|
|
6
6
|
|
7
7
|
# Retrieve the OID as well on a default select
|
8
8
|
def build_select(arel)
|
9
|
-
|
10
|
-
|
9
|
+
if @klass.using_multi_table_inheritance? && @klass.has_tableoid_column?
|
10
|
+
arel.project(tableoid_cast(@klass))
|
11
|
+
end
|
12
|
+
|
11
13
|
if select_values.any?
|
12
14
|
arel.project(*arel_columns(select_values.uniq))
|
13
15
|
else
|
@@ -18,7 +20,7 @@ module ActiveRecord
|
|
18
20
|
def tableoid_cast(klass)
|
19
21
|
# Arel::Nodes::NamedFunction.new('CAST', [klass.arel_table[:tableoid].as('regclass')])
|
20
22
|
# Arel::Nodes::NamedFunction.new('CAST', [@klass.arel_table['tableoid::regclass'].as('regclass')])
|
21
|
-
|
23
|
+
@klass.mti_tableoid_projection
|
22
24
|
end
|
23
25
|
|
24
26
|
end
|
@@ -4,7 +4,7 @@ module ActiveRecord
|
|
4
4
|
module MTI
|
5
5
|
class Railtie < Rails::Railtie
|
6
6
|
initializer 'active_record-mti.load' do |_app|
|
7
|
-
|
7
|
+
ActiveRecord::MTI.logger.info "ActiveRecord::MTI railtie initializer"
|
8
8
|
ActiveSupport.on_load(:active_record) do
|
9
9
|
ActiveRecord::MTI.load
|
10
10
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_record-mti
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dale Stevens
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-09-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pg
|
@@ -104,22 +104,16 @@ dependencies:
|
|
104
104
|
name: simplecov
|
105
105
|
requirement: !ruby/object:Gem::Requirement
|
106
106
|
requirements:
|
107
|
-
- - "
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
version: 0.9.0
|
110
|
-
- - "<"
|
107
|
+
- - "~>"
|
111
108
|
- !ruby/object:Gem::Version
|
112
|
-
version:
|
109
|
+
version: '0.1'
|
113
110
|
type: :development
|
114
111
|
prerelease: false
|
115
112
|
version_requirements: !ruby/object:Gem::Requirement
|
116
113
|
requirements:
|
117
|
-
- - "
|
118
|
-
- !ruby/object:Gem::Version
|
119
|
-
version: 0.9.0
|
120
|
-
- - "<"
|
114
|
+
- - "~>"
|
121
115
|
- !ruby/object:Gem::Version
|
122
|
-
version:
|
116
|
+
version: '0.1'
|
123
117
|
- !ruby/object:Gem::Dependency
|
124
118
|
name: codeclimate-test-reporter
|
125
119
|
requirement: !ruby/object:Gem::Requirement
|