active_record-mti 0.1.1 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Version ](https://img.shields.io/gem/v/active_record-mti.svg?maxAge=2592000)](https://rubygems.org/gems/active_record-mti)
|
2
|
+
[![Build Status ](https://travis-ci.org/TwilightCoders/active_record-mti.svg)](https://travis-ci.org/TwilightCoders/active_record-mti)
|
3
|
+
[![Code Climate ](https://codeclimate.com/github/TwilightCoders/active_record-mti/badges/gpa.svg)](https://codeclimate.com/github/TwilightCoders/active_record-mti)
|
4
|
+
[![Test Coverage](https://codeclimate.com/github/TwilightCoders/active_record-mti/badges/coverage.svg)](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
|