active_record-mti 0.0.7 → 0.1.0
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/.gitignore +1 -0
- data/.travis.yml +1 -1
- data/active_record-mti.gemspec +3 -2
- data/lib/active_record/mti.rb +7 -5
- data/lib/active_record/mti/calculations.rb +2 -2
- data/lib/active_record/mti/connection_adapters/postgresql/adapter.rb +30 -0
- data/lib/active_record/mti/inheritance.rb +21 -4
- data/lib/active_record/mti/model_schema.rb +37 -2
- data/lib/active_record/mti/query_methods.rb +1 -1
- data/lib/active_record/mti/version.rb +1 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 184ec1c49f5ccb8a375f7780684e265bb4132b13
|
4
|
+
data.tar.gz: 74679030c66bf141020f7e58c4aed0597cc83dd6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9e9d8a6e8f9b116529d648bed2893e8cf85f5c479791362d5dcd903fd502d012557dc8f1f46c4953e4fe0a2c6a982197efa3bf3bc52f46c8661adf788026bbb3
|
7
|
+
data.tar.gz: b78dac12e338c6cb5d236efb59486b34dae3280902097b5daa03eb297513ab9eaff8e61619cec283c97acc56b818ad6e411460bd5fd42d4ade2f6e0b59c705e4
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/active_record-mti.gemspec
CHANGED
@@ -37,7 +37,8 @@ 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
|
41
|
-
spec.add_development_dependency
|
40
|
+
spec.add_development_dependency 'simplecov', ['>= 0.9.0', '<1.0.0']
|
41
|
+
spec.add_development_dependency 'codeclimate-test-reporter', '~> 1.0'
|
42
|
+
spec.add_development_dependency 'database_cleaner', '~> 1.6'
|
42
43
|
|
43
44
|
end
|
data/lib/active_record/mti.rb
CHANGED
@@ -7,6 +7,7 @@ require 'active_record/mti/model_schema'
|
|
7
7
|
require 'active_record/mti/query_methods'
|
8
8
|
require 'active_record/mti/calculations'
|
9
9
|
require 'active_record/mti/connection_adapters/postgresql/schema_statements'
|
10
|
+
require 'active_record/mti/connection_adapters/postgresql/adapter'
|
10
11
|
|
11
12
|
require 'active_record/mti/railtie' if defined?(Rails::Railtie)
|
12
13
|
|
@@ -18,12 +19,13 @@ module ActiveRecord
|
|
18
19
|
end
|
19
20
|
|
20
21
|
def self.load
|
21
|
-
::ActiveRecord::Base.send
|
22
|
-
::ActiveRecord::Base.send
|
23
|
-
::ActiveRecord::Relation.send
|
24
|
-
::ActiveRecord::Relation.send
|
22
|
+
::ActiveRecord::Base.send :include, Inheritance
|
23
|
+
::ActiveRecord::Base.send :include, ModelSchema
|
24
|
+
::ActiveRecord::Relation.send :include, QueryMethods
|
25
|
+
::ActiveRecord::Relation.send :include, Calculations
|
26
|
+
::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.send :prepend, ConnectionAdapters::PostgreSQL::Adapter
|
25
27
|
::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.send :include, ConnectionAdapters::PostgreSQL::SchemaStatements
|
26
|
-
::ActiveRecord::SchemaDumper.send
|
28
|
+
::ActiveRecord::SchemaDumper.send :include, SchemaDumper
|
27
29
|
end
|
28
30
|
end
|
29
31
|
end
|
@@ -52,7 +52,7 @@ module ActiveRecord
|
|
52
52
|
relation.select_values = select_values
|
53
53
|
|
54
54
|
# Remove our cast otherwise PSQL will insist that it be included in the GROUP
|
55
|
-
relation.arel.projections.select!{ |p| p.to_s !=
|
55
|
+
relation.arel.projections.select!{ |p| p.to_s != tableoid_cast(klass) } if @klass.using_multi_table_inheritance?
|
56
56
|
|
57
57
|
calculated_data = @klass.connection.select_all(relation, nil, relation.arel.bind_values + bind_values)
|
58
58
|
|
@@ -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.to_s !=
|
105
|
+
relation.arel.projections.select!{ |p| p.to_s != 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
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module MTI
|
3
|
+
module ConnectionAdapters
|
4
|
+
module PostgreSQL
|
5
|
+
module Adapter
|
6
|
+
|
7
|
+
def version
|
8
|
+
Gem::Version.new exec_query(<<-SQL, 'SCHEMA').rows.first.first
|
9
|
+
SHOW server_version;
|
10
|
+
SQL
|
11
|
+
end
|
12
|
+
|
13
|
+
def column_definitions(table_name) # :nodoc:
|
14
|
+
exec_query(<<-SQL, 'SCHEMA').rows
|
15
|
+
SELECT a.attname, format_type(a.atttypid, a.atttypmod),
|
16
|
+
pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
|
17
|
+
FROM pg_attribute a LEFT JOIN pg_attrdef d
|
18
|
+
ON a.attrelid = d.adrelid AND a.attnum = d.adnum
|
19
|
+
WHERE a.attrelid = '#{quote_table_name(table_name)}'::regclass
|
20
|
+
AND a.attnum > 0 AND NOT a.attisdropped
|
21
|
+
AND a.attname != 'tableoid'
|
22
|
+
ORDER BY a.attnum
|
23
|
+
SQL
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -34,12 +34,13 @@ module ActiveRecord
|
|
34
34
|
module ClassMethods
|
35
35
|
|
36
36
|
def inherited(child)
|
37
|
-
child.uses_mti if self.uses_mti?
|
38
37
|
super
|
39
38
|
end
|
40
39
|
|
41
|
-
def uses_mti
|
42
|
-
self.
|
40
|
+
def uses_mti(table_name = nil, inheritance_column = nil)
|
41
|
+
# self.table_name ||= table_name
|
42
|
+
self.inheritance_column = inheritance_column
|
43
|
+
|
43
44
|
@uses_mti = true
|
44
45
|
end
|
45
46
|
|
@@ -48,11 +49,27 @@ module ActiveRecord
|
|
48
49
|
end
|
49
50
|
|
50
51
|
def uses_mti?
|
51
|
-
@uses_mti ||=
|
52
|
+
@uses_mti ||= check_inheritence_of(@table_name)
|
52
53
|
end
|
53
54
|
|
54
55
|
private
|
55
56
|
|
57
|
+
def check_inheritence_of(table_name)
|
58
|
+
return nil unless table_name
|
59
|
+
|
60
|
+
result = connection.execute <<-SQL
|
61
|
+
SELECT EXISTS ( SELECT 1
|
62
|
+
FROM pg_catalog.pg_inherits
|
63
|
+
WHERE inhrelid = 'public.#{table_name}'::regclass::oid
|
64
|
+
OR inhparent = 'public.#{table_name}'::regclass::oid);
|
65
|
+
SQL
|
66
|
+
|
67
|
+
# Some versions of PSQL return {"?column?"=>"t"}
|
68
|
+
# instead of {"first"=>"t"}, so we're saying screw it,
|
69
|
+
# just give me the first value of whatever is returned
|
70
|
+
result.try(:first).try(:values).try(:first) == 't'
|
71
|
+
end
|
72
|
+
|
56
73
|
# Called by +instantiate+ to decide which class to use for a new
|
57
74
|
# record instance. For single-table inheritance, we check the record
|
58
75
|
# for a +type+ column and return the corresponding class.
|
@@ -8,16 +8,51 @@ module ActiveRecord
|
|
8
8
|
|
9
9
|
# Computes the table name, (re)sets it internally, and returns it.
|
10
10
|
def reset_table_name #:nodoc:
|
11
|
-
# binding.pry
|
12
11
|
self.table_name = if abstract_class?
|
13
12
|
superclass == Base ? nil : superclass.table_name
|
14
|
-
elsif superclass.abstract_class
|
13
|
+
elsif superclass.abstract_class?# || superclass.using_multi_table_inheritance?
|
15
14
|
superclass.table_name || compute_table_name
|
16
15
|
else
|
17
16
|
compute_table_name
|
18
17
|
end
|
19
18
|
end
|
20
19
|
|
20
|
+
# Computes and returns a table name according to default conventions.
|
21
|
+
def compute_table_name
|
22
|
+
base = base_class
|
23
|
+
if self == base
|
24
|
+
# Nested classes are prefixed with singular parent table name.
|
25
|
+
if parent < Base && !parent.abstract_class?
|
26
|
+
contained = parent.table_name
|
27
|
+
contained = contained.singularize if parent.pluralize_table_names
|
28
|
+
contained += '_'
|
29
|
+
end
|
30
|
+
|
31
|
+
"#{full_table_name_prefix}#{contained}#{undecorated_table_name(name)}#{full_table_name_suffix}"
|
32
|
+
elsif uses_mti?
|
33
|
+
|
34
|
+
# Nested classes are prefixed with singular parent table name.
|
35
|
+
if superclass < Base && !superclass.abstract_class?
|
36
|
+
contained = superclass.table_name
|
37
|
+
contained = contained.singularize if superclass.pluralize_table_names
|
38
|
+
contained += '/'
|
39
|
+
end
|
40
|
+
|
41
|
+
"#{full_table_name_prefix}#{contained}#{decorated_table_name(name)}#{full_table_name_suffix}"
|
42
|
+
else
|
43
|
+
# STI subclasses always use their superclass' table.
|
44
|
+
superclass.table_name
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
# Guesses the table name, but does not decorate it with prefix and suffix information.
|
51
|
+
def decorated_table_name(class_name = base_class.name)
|
52
|
+
table_name = class_name.to_s.underscore
|
53
|
+
pluralize_table_names ? table_name.pluralize : table_name
|
54
|
+
end
|
55
|
+
|
21
56
|
end
|
22
57
|
end
|
23
58
|
end
|
@@ -18,7 +18,7 @@ module ActiveRecord
|
|
18
18
|
def tableoid_cast(klass)
|
19
19
|
# Arel::Nodes::NamedFunction.new('CAST', [klass.arel_table[:tableoid].as('regclass')])
|
20
20
|
# Arel::Nodes::NamedFunction.new('CAST', [@klass.arel_table['tableoid::regclass'].as('regclass')])
|
21
|
-
"CAST(\"#{klass.table_name}\".\"tableoid\"::regclass AS text)"
|
21
|
+
"TRIM(BOTH '\"' FROM CAST(\"#{klass.table_name}\".\"tableoid\"::regclass AS text)) AS tableoid"
|
22
22
|
end
|
23
23
|
|
24
24
|
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.0
|
4
|
+
version: 0.1.0
|
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-05-
|
11
|
+
date: 2017-05-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pg
|
@@ -134,6 +134,20 @@ dependencies:
|
|
134
134
|
- - "~>"
|
135
135
|
- !ruby/object:Gem::Version
|
136
136
|
version: '1.0'
|
137
|
+
- !ruby/object:Gem::Dependency
|
138
|
+
name: database_cleaner
|
139
|
+
requirement: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - "~>"
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '1.6'
|
144
|
+
type: :development
|
145
|
+
prerelease: false
|
146
|
+
version_requirements: !ruby/object:Gem::Requirement
|
147
|
+
requirements:
|
148
|
+
- - "~>"
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '1.6'
|
137
151
|
description: Allows use of native inherited tables in PostgreSQL
|
138
152
|
email:
|
139
153
|
- dale@twilightcoders.net
|
@@ -151,6 +165,7 @@ files:
|
|
151
165
|
- active_record-mti.gemspec
|
152
166
|
- lib/active_record/mti.rb
|
153
167
|
- lib/active_record/mti/calculations.rb
|
168
|
+
- lib/active_record/mti/connection_adapters/postgresql/adapter.rb
|
154
169
|
- lib/active_record/mti/connection_adapters/postgresql/schema_statements.rb
|
155
170
|
- lib/active_record/mti/inheritance.rb
|
156
171
|
- lib/active_record/mti/model_schema.rb
|