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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -6
  3. data/{LICENSE.txt → LICENSE} +0 -0
  4. data/README.md +47 -10
  5. data/lib/active_record/mti.rb +56 -56
  6. data/lib/active_record/mti/config.rb +26 -0
  7. data/lib/active_record/mti/connection_adapters/postgresql/adapter.rb +0 -8
  8. data/lib/active_record/mti/connection_adapters/postgresql/schema_statements.rb +30 -11
  9. data/lib/active_record/mti/core_extension.rb +170 -0
  10. data/lib/active_record/mti/railtie.rb +9 -4
  11. data/lib/active_record/mti/relation.rb +95 -0
  12. data/lib/active_record/mti/schema_dumper.rb +4 -4
  13. data/lib/active_record/mti/table.rb +19 -0
  14. data/lib/active_record/mti/table_oid.rb +6 -0
  15. data/lib/active_record/mti/version.rb +1 -1
  16. data/lib/core_ext/array.rb +14 -0
  17. data/lib/core_ext/hash.rb +1 -3
  18. data/lib/core_ext/thread.rb +14 -0
  19. metadata +94 -95
  20. data/.gitignore +0 -78
  21. data/.rspec +0 -2
  22. data/.travis.yml +0 -38
  23. data/Gemfile +0 -21
  24. data/Rakefile +0 -6
  25. data/active_record-mti.gemspec +0 -42
  26. data/gemfiles/activerecord-4.0.Gemfile +0 -3
  27. data/gemfiles/activerecord-4.1.Gemfile +0 -3
  28. data/gemfiles/activerecord-4.2.Gemfile +0 -3
  29. data/gemfiles/activerecord-5.0.Gemfile +0 -3
  30. data/gemfiles/activerecord-5.1.Gemfile +0 -3
  31. data/lib/active_record/mti/calculations.rb +0 -23
  32. data/lib/active_record/mti/inheritance.rb +0 -127
  33. data/lib/active_record/mti/model_schema.rb +0 -55
  34. data/lib/active_record/mti/query_methods.rb +0 -40
  35. data/lib/active_record/mti/querying.rb +0 -7
  36. data/lib/active_record/mti/registry.rb +0 -23
  37. data/spec/active_record/mti/calculations_spec.rb +0 -56
  38. data/spec/active_record/mti/inheritance_spec.rb +0 -184
  39. data/spec/active_record/mti/model_schema_spec.rb +0 -11
  40. data/spec/active_record/mti/query_methods_spec.rb +0 -12
  41. data/spec/active_record/mti/schema_dumper_spec.rb +0 -22
  42. data/spec/active_record/mti_spec.rb +0 -24
  43. data/spec/active_record/sti/inheritance_spec.rb +0 -24
  44. data/spec/spec_helper.rb +0 -28
  45. data/spec/support/rails/app/models/admin.rb +0 -3
  46. data/spec/support/rails/app/models/comment.rb +0 -4
  47. data/spec/support/rails/app/models/post.rb +0 -4
  48. data/spec/support/rails/app/models/transportation/military/vehicle.rb +0 -7
  49. data/spec/support/rails/app/models/transportation/truck.rb +0 -5
  50. data/spec/support/rails/app/models/transportation/vehicle.rb +0 -4
  51. data/spec/support/rails/app/models/user.rb +0 -6
  52. data/spec/support/rails/config/database.yml +0 -4
  53. data/spec/support/rails/config/routes.rb +0 -3
  54. data/spec/support/rails/db/schema.rb +0 -51
  55. data/spec/support/rails/log/.gitignore +0 -1
  56. data/spec/support/rails/public/favicon.ico +0 -0
@@ -1,15 +1,20 @@
1
- require 'rails/railtie'
1
+ require 'active_record/mti/core_extension'
2
+ require 'active_record/mti/connection_adapters/postgresql/schema_statements'
3
+ require 'active_record/mti/connection_adapters/postgresql/adapter'
4
+ require 'active_record/mti/schema_dumper'
2
5
 
3
6
  module ActiveRecord
4
7
  module MTI
5
8
  class Railtie < Rails::Railtie
6
9
  initializer 'active_record-mti.load' do |_app|
7
- ActiveRecord::MTI.logger.debug "active_record-mti.load"
8
10
  ActiveSupport.on_load(:active_record) do
9
- ActiveRecord::MTI.load
11
+ ::ActiveRecord::Base.prepend(::ActiveRecord::MTI::CoreExtension)
12
+
13
+ ::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(ConnectionAdapters::PostgreSQL::Adapter)
14
+ ::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(ConnectionAdapters::PostgreSQL::SchemaStatements)
15
+ ::ActiveRecord::SchemaDumper.prepend(SchemaDumper)
10
16
  end
11
17
  end
12
18
  end
13
19
  end
14
20
  end
15
-
@@ -0,0 +1,95 @@
1
+ require 'active_support/core_ext/object/blank'
2
+
3
+ module ActiveRecord
4
+ module MTI
5
+ module Relation
6
+
7
+ # Consider using a join to avoid complicated selects?
8
+ # Maybe each "mti" belongs_to :mti_table foreign_key: :tableoid?
9
+ # SELECT p.relname, c.name, c.altitude
10
+ # FROM cities c, pg_class p
11
+ # WHERE c.altitude > 500 AND c.tableoid = p.oid;
12
+
13
+
14
+ # TODO: Introduce natural joins
15
+ # https://dba.stackexchange.com/questions/94050/query-parent-table-and-get-child-tables-columns
16
+ # EXPLAIN ANALYSE SELECT * FROM ONLY listeners NATURAL FULL JOIN "listeners/bridge";
17
+
18
+ # EXPLAIN ANALYSE SELECT * FROM "listeners/bridge";
19
+
20
+ # EXPLAIN ANALYSE SELECT * FROM listeners;
21
+
22
+ # EXPLAIN ANALYSE SELECT * FROM ONLY listeners
23
+ # NATURAL FULL JOIN "listeners/bridge"
24
+ # NATURAL FULL JOIN "listeners/integration"
25
+ # NATURAL FULL JOIN "listeners/nest_thermostat"
26
+ # NATURAL FULL JOIN "listeners/sensor"
27
+ # NATURAL FULL JOIN "listeners/system"
28
+ # NATURAL FULL JOIN "listeners/system_users"
29
+ # NATURAL FULL JOIN "listeners/user";
30
+
31
+ # table_name = mti_table.name
32
+ # scope :naturally, -> {
33
+ # descendants.inject(only) { |ar|
34
+ # ar.join
35
+ # }
36
+ # }
37
+
38
+ def build_arel(*)
39
+ super.tap do |ar|
40
+ build_mti(ar)
41
+ end
42
+ end
43
+
44
+ def build_mti(arel)
45
+ if klass.tableoid?
46
+ arel.project(tableoid_project) if !projecting_tableoid?(arel)
47
+ arel.group(tableoid_group) if group_values.any?
48
+ end
49
+ end
50
+
51
+ def projecting_tableoid?(arel)
52
+ arel.projections.any? do |projection|
53
+ tableoid_projection?(projection)
54
+ end
55
+ end
56
+
57
+ def tableoid_projection?(projection)
58
+ case projection
59
+ when Arel::Attributes::Attribute
60
+ projection.relation.name == klass.table_name && projection.name.to_s == 'tableoid'
61
+ # when Arel::Nodes::As
62
+ # tableoid_projection?(projection.left)
63
+ when Arel::Nodes::SqlLiteral
64
+ projection == 'tableoid'
65
+ else
66
+ false
67
+ end
68
+ end
69
+
70
+ # def exclusively(tables=[klass])
71
+ # @table = table.dup.tap do |t|
72
+ # t.only!
73
+ # end
74
+ # binding.pry
75
+ # self
76
+ # end
77
+
78
+ private
79
+
80
+ def perform_calculation(*)
81
+ Thread.currently(:skip_tableoid_cast, true) do
82
+ super
83
+ end
84
+ end
85
+
86
+ def tableoid_project
87
+ arel_table[:tableoid]#.as('tableoid')
88
+ end
89
+
90
+ def tableoid_group
91
+ arel_table[:tableoid]
92
+ end
93
+ end
94
+ end
95
+ end
@@ -1,3 +1,5 @@
1
+ require 'core_ext/hash'
2
+
1
3
  # Modified SchemaDumper that knows how to dump
2
4
  # inherited tables. Key is that we have to dump parent
3
5
  # tables before we dump child tables (of course).
@@ -10,7 +12,6 @@ module ActiveRecord
10
12
  # output format (i.e., ActiveRecord::Schema).
11
13
  module MTI
12
14
  module SchemaDumper #:nodoc:
13
-
14
15
  def dumped_tables
15
16
  @dumped_tables ||= []
16
17
  end
@@ -44,7 +45,7 @@ module ActiveRecord
44
45
 
45
46
  def inject_inherits_for_create_table(string, table, parent_table)
46
47
  tbl_start = "create_table #{remove_prefix_and_suffix(table).inspect}"
47
- tbl_end = " do |t|"
48
+ tbl_end = ' do |t|'
48
49
  tbl_inherit = ", inherits: '#{parent_table}'"
49
50
  string.gsub!(/#{Regexp.escape(tbl_start)}.*#{Regexp.escape(tbl_end)}/, tbl_start + tbl_inherit + tbl_end)
50
51
  end
@@ -65,13 +66,12 @@ module ActiveRecord
65
66
  end
66
67
 
67
68
  def remove_prefix_and_suffix(table)
68
- table.gsub(/^(#{ActiveRecord::Base.table_name_prefix})(.+)(#{ActiveRecord::Base.table_name_suffix})$/, "\\2")
69
+ table.gsub(/^(#{ActiveRecord::Base.table_name_prefix})(.+)(#{ActiveRecord::Base.table_name_suffix})$/, '\\2')
69
70
  end
70
71
 
71
72
  def already_dumped?(table)
72
73
  dumped_tables.include? table
73
74
  end
74
-
75
75
  end
76
76
  end
77
77
  end
@@ -0,0 +1,19 @@
1
+ module ActiveRecord
2
+ module MTI
3
+ module Table
4
+
5
+ def self.find(klass, table_name, parent_class=klass.superclass)
6
+ if concrete?(parent_class) && parent_mti_table = parent_class.mti_table
7
+ ::ActiveRecord::MTI.child_tables.find(inhparent: parent_mti_table.oid, name: table_name) #|| parent_mti_table
8
+ else
9
+ ::ActiveRecord::MTI.parent_tables.find(name: table_name)
10
+ end
11
+ end
12
+
13
+ def self.concrete?(klass)
14
+ klass < ::ActiveRecord::Base && !klass.try(:abstract_class?)
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,6 @@
1
+ module ActiveRecord
2
+ module MTI
3
+ module TableOID
4
+ end
5
+ end
6
+ end
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module MTI
3
- VERSION = '0.3.2'
3
+ VERSION = '0.4.0-1'.freeze
4
4
  end
5
5
  end
@@ -0,0 +1,14 @@
1
+ Array.class_eval do
2
+
3
+ alias_method :join_original, :join
4
+ def join(separator=$,)
5
+ if block_given?
6
+ inject(String.new) do |collector, item|
7
+ collector << yield(item).to_s + separator
8
+ end.chomp(separator)
9
+ else
10
+ join_original(separator)
11
+ end
12
+ end
13
+
14
+ end
data/lib/core_ext/hash.rb CHANGED
@@ -1,7 +1,5 @@
1
1
  class Hash
2
-
3
2
  def &(other)
4
- Hash[(self.keys & other.keys).zip(other.values_at(*(self.keys & other.keys)))]
3
+ Hash[(keys & other.keys).zip(other.values_at(*(keys & other.keys)))]
5
4
  end
6
-
7
5
  end
@@ -0,0 +1,14 @@
1
+ class Thread
2
+ def self.currently(key, value=true)
3
+ __currently_org__, Thread.current[key] = Thread.current[key], value
4
+ yield if block_given?
5
+ ensure
6
+ Thread.current[key] = __currently_org__
7
+ end
8
+
9
+ def self.currently?(key, value=true)
10
+ if Thread.current[key] == value
11
+ block_given? ? yield : true
12
+ end
13
+ end
14
+ end
metadata CHANGED
@@ -1,105 +1,155 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_record-mti
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.0.pre.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dale Stevens
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-16 00:00:00.000000000 Z
11
+ date: 2019-06-12 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '4.2'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: pg
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
- - - "~>"
31
+ - - ">="
18
32
  - !ruby/object:Gem::Version
19
33
  version: '0'
20
34
  type: :runtime
21
35
  prerelease: false
22
36
  version_requirements: !ruby/object:Gem::Requirement
23
37
  requirements:
24
- - - "~>"
38
+ - - ">="
25
39
  - !ruby/object:Gem::Version
26
40
  version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
- name: activerecord
42
+ name: registry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.2.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.2.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
29
57
  requirement: !ruby/object:Gem::Requirement
30
58
  requirements:
31
59
  - - ">="
32
60
  - !ruby/object:Gem::Version
33
- version: '4'
34
- - - "<"
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
35
74
  - !ruby/object:Gem::Version
36
- version: '6'
37
- type: :runtime
75
+ version: '0'
76
+ type: :development
38
77
  prerelease: false
39
78
  version_requirements: !ruby/object:Gem::Requirement
40
79
  requirements:
41
80
  - - ">="
42
81
  - !ruby/object:Gem::Version
43
- version: '4'
44
- - - "<"
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: combustion
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
45
95
  - !ruby/object:Gem::Version
46
- version: '6'
96
+ version: '0'
47
97
  - !ruby/object:Gem::Dependency
48
98
  name: pry-byebug
49
99
  requirement: !ruby/object:Gem::Requirement
50
100
  requirements:
51
- - - "~>"
101
+ - - ">="
52
102
  - !ruby/object:Gem::Version
53
- version: '3'
103
+ version: '0'
54
104
  type: :development
55
105
  prerelease: false
56
106
  version_requirements: !ruby/object:Gem::Requirement
57
107
  requirements:
58
- - - "~>"
108
+ - - ">="
59
109
  - !ruby/object:Gem::Version
60
- version: '3'
110
+ version: '0'
61
111
  - !ruby/object:Gem::Dependency
62
- name: bundler
112
+ name: rake
63
113
  requirement: !ruby/object:Gem::Requirement
64
114
  requirements:
65
- - - "~>"
115
+ - - ">="
66
116
  - !ruby/object:Gem::Version
67
- version: '1.3'
117
+ version: '0'
68
118
  type: :development
69
119
  prerelease: false
70
120
  version_requirements: !ruby/object:Gem::Requirement
71
121
  requirements:
72
- - - "~>"
122
+ - - ">="
73
123
  - !ruby/object:Gem::Version
74
- version: '1.3'
124
+ version: '0'
75
125
  - !ruby/object:Gem::Dependency
76
- name: rake
126
+ name: database_cleaner
77
127
  requirement: !ruby/object:Gem::Requirement
78
128
  requirements:
79
- - - "~>"
129
+ - - ">="
80
130
  - !ruby/object:Gem::Version
81
- version: '12.0'
131
+ version: '0'
82
132
  type: :development
83
133
  prerelease: false
84
134
  version_requirements: !ruby/object:Gem::Requirement
85
135
  requirements:
86
- - - "~>"
136
+ - - ">="
87
137
  - !ruby/object:Gem::Version
88
- version: '12.0'
138
+ version: '0'
89
139
  - !ruby/object:Gem::Dependency
90
- name: combustion
140
+ name: simplecov
91
141
  requirement: !ruby/object:Gem::Requirement
92
142
  requirements:
93
- - - "~>"
143
+ - - ">="
94
144
  - !ruby/object:Gem::Version
95
- version: '0.7'
145
+ version: '0'
96
146
  type: :development
97
147
  prerelease: false
98
148
  version_requirements: !ruby/object:Gem::Requirement
99
149
  requirements:
100
- - - "~>"
150
+ - - ">="
101
151
  - !ruby/object:Gem::Version
102
- version: '0.7'
152
+ version: '0'
103
153
  description: Gives ActiveRecord support for PostgreSQL's native inherited tables
104
154
  email:
105
155
  - dale@twilightcoders.net
@@ -107,53 +157,23 @@ executables: []
107
157
  extensions: []
108
158
  extra_rdoc_files: []
109
159
  files:
110
- - ".gitignore"
111
- - ".rspec"
112
- - ".travis.yml"
113
160
  - CHANGELOG.md
114
- - Gemfile
115
- - LICENSE.txt
161
+ - LICENSE
116
162
  - README.md
117
- - Rakefile
118
- - active_record-mti.gemspec
119
- - gemfiles/activerecord-4.0.Gemfile
120
- - gemfiles/activerecord-4.1.Gemfile
121
- - gemfiles/activerecord-4.2.Gemfile
122
- - gemfiles/activerecord-5.0.Gemfile
123
- - gemfiles/activerecord-5.1.Gemfile
124
163
  - lib/active_record/mti.rb
125
- - lib/active_record/mti/calculations.rb
164
+ - lib/active_record/mti/config.rb
126
165
  - lib/active_record/mti/connection_adapters/postgresql/adapter.rb
127
166
  - lib/active_record/mti/connection_adapters/postgresql/schema_statements.rb
128
- - lib/active_record/mti/inheritance.rb
129
- - lib/active_record/mti/model_schema.rb
130
- - lib/active_record/mti/query_methods.rb
131
- - lib/active_record/mti/querying.rb
167
+ - lib/active_record/mti/core_extension.rb
132
168
  - lib/active_record/mti/railtie.rb
133
- - lib/active_record/mti/registry.rb
169
+ - lib/active_record/mti/relation.rb
134
170
  - lib/active_record/mti/schema_dumper.rb
171
+ - lib/active_record/mti/table.rb
172
+ - lib/active_record/mti/table_oid.rb
135
173
  - lib/active_record/mti/version.rb
174
+ - lib/core_ext/array.rb
136
175
  - lib/core_ext/hash.rb
137
- - spec/active_record/mti/calculations_spec.rb
138
- - spec/active_record/mti/inheritance_spec.rb
139
- - spec/active_record/mti/model_schema_spec.rb
140
- - spec/active_record/mti/query_methods_spec.rb
141
- - spec/active_record/mti/schema_dumper_spec.rb
142
- - spec/active_record/mti_spec.rb
143
- - spec/active_record/sti/inheritance_spec.rb
144
- - spec/spec_helper.rb
145
- - spec/support/rails/app/models/admin.rb
146
- - spec/support/rails/app/models/comment.rb
147
- - spec/support/rails/app/models/post.rb
148
- - spec/support/rails/app/models/transportation/military/vehicle.rb
149
- - spec/support/rails/app/models/transportation/truck.rb
150
- - spec/support/rails/app/models/transportation/vehicle.rb
151
- - spec/support/rails/app/models/user.rb
152
- - spec/support/rails/config/database.yml
153
- - spec/support/rails/config/routes.rb
154
- - spec/support/rails/db/schema.rb
155
- - spec/support/rails/log/.gitignore
156
- - spec/support/rails/public/favicon.ico
176
+ - lib/core_ext/thread.rb
157
177
  homepage: https://github.com/twilightcoders/active_record-mti
158
178
  licenses:
159
179
  - MIT
@@ -168,36 +188,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
168
188
  requirements:
169
189
  - - ">="
170
190
  - !ruby/object:Gem::Version
171
- version: '2.1'
191
+ version: '2.3'
172
192
  required_rubygems_version: !ruby/object:Gem::Requirement
173
193
  requirements:
174
- - - ">="
194
+ - - ">"
175
195
  - !ruby/object:Gem::Version
176
- version: '0'
196
+ version: 1.3.1
177
197
  requirements: []
178
- rubyforge_project:
179
- rubygems_version: 2.7.7
198
+ rubygems_version: 3.0.3
180
199
  signing_key:
181
200
  specification_version: 4
182
201
  summary: Multi Table Inheritance for PostgreSQL in Rails
183
- test_files:
184
- - spec/active_record/mti/calculations_spec.rb
185
- - spec/active_record/mti/inheritance_spec.rb
186
- - spec/active_record/mti/model_schema_spec.rb
187
- - spec/active_record/mti/query_methods_spec.rb
188
- - spec/active_record/mti/schema_dumper_spec.rb
189
- - spec/active_record/mti_spec.rb
190
- - spec/active_record/sti/inheritance_spec.rb
191
- - spec/spec_helper.rb
192
- - spec/support/rails/app/models/admin.rb
193
- - spec/support/rails/app/models/comment.rb
194
- - spec/support/rails/app/models/post.rb
195
- - spec/support/rails/app/models/transportation/military/vehicle.rb
196
- - spec/support/rails/app/models/transportation/truck.rb
197
- - spec/support/rails/app/models/transportation/vehicle.rb
198
- - spec/support/rails/app/models/user.rb
199
- - spec/support/rails/config/database.yml
200
- - spec/support/rails/config/routes.rb
201
- - spec/support/rails/db/schema.rb
202
- - spec/support/rails/log/.gitignore
203
- - spec/support/rails/public/favicon.ico
202
+ test_files: []