active_record-mti 0.3.2 → 0.4.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
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: []