torque-postgresql 1.1.7 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/lib/torque/postgresql.rb +0 -2
  3. data/lib/torque/postgresql/adapter.rb +7 -1
  4. data/lib/torque/postgresql/adapter/database_statements.rb +6 -15
  5. data/lib/torque/postgresql/adapter/oid.rb +3 -1
  6. data/lib/torque/postgresql/adapter/oid/box.rb +2 -0
  7. data/lib/torque/postgresql/adapter/oid/circle.rb +2 -0
  8. data/lib/torque/postgresql/adapter/oid/enum.rb +2 -0
  9. data/lib/torque/postgresql/adapter/oid/enum_set.rb +2 -0
  10. data/lib/torque/postgresql/adapter/oid/interval.rb +2 -0
  11. data/lib/torque/postgresql/adapter/oid/line.rb +2 -0
  12. data/lib/torque/postgresql/adapter/oid/range.rb +2 -0
  13. data/lib/torque/postgresql/adapter/oid/segment.rb +2 -0
  14. data/lib/torque/postgresql/adapter/quoting.rb +2 -0
  15. data/lib/torque/postgresql/adapter/schema_creation.rb +20 -23
  16. data/lib/torque/postgresql/adapter/schema_definitions.rb +9 -21
  17. data/lib/torque/postgresql/adapter/schema_dumper.rb +76 -11
  18. data/lib/torque/postgresql/adapter/schema_statements.rb +4 -12
  19. data/lib/torque/postgresql/arel/infix_operation.rb +5 -1
  20. data/lib/torque/postgresql/arel/join_source.rb +2 -0
  21. data/lib/torque/postgresql/arel/nodes.rb +2 -0
  22. data/lib/torque/postgresql/arel/operations.rb +2 -0
  23. data/lib/torque/postgresql/arel/select_manager.rb +2 -0
  24. data/lib/torque/postgresql/arel/visitors.rb +6 -3
  25. data/lib/torque/postgresql/associations.rb +0 -3
  26. data/lib/torque/postgresql/associations/association.rb +5 -1
  27. data/lib/torque/postgresql/associations/association_scope.rb +20 -60
  28. data/lib/torque/postgresql/associations/belongs_to_many_association.rb +5 -1
  29. data/lib/torque/postgresql/associations/builder/belongs_to_many.rb +2 -0
  30. data/lib/torque/postgresql/associations/builder/has_many.rb +2 -0
  31. data/lib/torque/postgresql/associations/preloader.rb +0 -32
  32. data/lib/torque/postgresql/associations/preloader/association.rb +42 -10
  33. data/lib/torque/postgresql/attributes/builder.rb +2 -0
  34. data/lib/torque/postgresql/attributes/builder/enum.rb +5 -3
  35. data/lib/torque/postgresql/attributes/builder/period.rb +6 -4
  36. data/lib/torque/postgresql/attributes/enum.rb +5 -10
  37. data/lib/torque/postgresql/attributes/enum_set.rb +2 -0
  38. data/lib/torque/postgresql/attributes/lazy.rb +3 -1
  39. data/lib/torque/postgresql/attributes/period.rb +2 -0
  40. data/lib/torque/postgresql/autosave_association.rb +9 -3
  41. data/lib/torque/postgresql/auxiliary_statement.rb +3 -13
  42. data/lib/torque/postgresql/auxiliary_statement/settings.rb +2 -0
  43. data/lib/torque/postgresql/base.rb +2 -0
  44. data/lib/torque/postgresql/coder.rb +6 -5
  45. data/lib/torque/postgresql/collector.rb +2 -0
  46. data/lib/torque/postgresql/config.rb +3 -4
  47. data/lib/torque/postgresql/geometry_builder.rb +2 -0
  48. data/lib/torque/postgresql/i18n.rb +2 -0
  49. data/lib/torque/postgresql/inheritance.rb +15 -17
  50. data/lib/torque/postgresql/migration/command_recorder.rb +2 -0
  51. data/lib/torque/postgresql/railtie.rb +2 -0
  52. data/lib/torque/postgresql/reflection.rb +2 -0
  53. data/lib/torque/postgresql/reflection/abstract_reflection.rb +28 -26
  54. data/lib/torque/postgresql/reflection/association_reflection.rb +2 -0
  55. data/lib/torque/postgresql/reflection/belongs_to_many_reflection.rb +6 -26
  56. data/lib/torque/postgresql/reflection/has_many_reflection.rb +2 -0
  57. data/lib/torque/postgresql/reflection/runtime_reflection.rb +2 -0
  58. data/lib/torque/postgresql/reflection/through_reflection.rb +2 -0
  59. data/lib/torque/postgresql/relation.rb +10 -11
  60. data/lib/torque/postgresql/relation/auxiliary_statement.rb +7 -8
  61. data/lib/torque/postgresql/relation/distinct_on.rb +3 -1
  62. data/lib/torque/postgresql/relation/inheritance.rb +2 -0
  63. data/lib/torque/postgresql/relation/merger.rb +2 -0
  64. data/lib/torque/postgresql/schema_cache.rb +2 -0
  65. data/lib/torque/postgresql/version.rb +3 -1
  66. data/spec/en.yml +19 -0
  67. data/spec/factories/authors.rb +6 -0
  68. data/spec/factories/comments.rb +13 -0
  69. data/spec/factories/posts.rb +6 -0
  70. data/spec/factories/tags.rb +5 -0
  71. data/spec/factories/texts.rb +5 -0
  72. data/spec/factories/users.rb +6 -0
  73. data/spec/factories/videos.rb +5 -0
  74. data/spec/mocks/cache_query.rb +16 -0
  75. data/spec/mocks/create_table.rb +35 -0
  76. data/spec/models/activity.rb +3 -0
  77. data/spec/models/activity_book.rb +4 -0
  78. data/spec/models/activity_post.rb +7 -0
  79. data/spec/models/activity_post/sample.rb +4 -0
  80. data/spec/models/author.rb +4 -0
  81. data/spec/models/author_journalist.rb +4 -0
  82. data/spec/models/comment.rb +3 -0
  83. data/spec/models/course.rb +2 -0
  84. data/spec/models/geometry.rb +2 -0
  85. data/spec/models/guest_comment.rb +4 -0
  86. data/spec/models/post.rb +6 -0
  87. data/spec/models/tag.rb +2 -0
  88. data/spec/models/text.rb +2 -0
  89. data/spec/models/time_keeper.rb +2 -0
  90. data/spec/models/user.rb +8 -0
  91. data/spec/models/video.rb +2 -0
  92. data/spec/schema.rb +141 -0
  93. data/spec/spec_helper.rb +59 -0
  94. data/spec/tests/arel_spec.rb +74 -0
  95. data/spec/tests/auxiliary_statement_spec.rb +593 -0
  96. data/spec/tests/belongs_to_many_spec.rb +246 -0
  97. data/spec/tests/coder_spec.rb +367 -0
  98. data/spec/tests/collector_spec.rb +59 -0
  99. data/spec/tests/distinct_on_spec.rb +65 -0
  100. data/spec/tests/enum_set_spec.rb +306 -0
  101. data/spec/tests/enum_spec.rb +628 -0
  102. data/spec/tests/geometric_builder_spec.rb +221 -0
  103. data/spec/tests/has_many_spec.rb +400 -0
  104. data/spec/tests/interval_spec.rb +167 -0
  105. data/spec/tests/lazy_spec.rb +24 -0
  106. data/spec/tests/period_spec.rb +954 -0
  107. data/spec/tests/quoting_spec.rb +24 -0
  108. data/spec/tests/range_spec.rb +36 -0
  109. data/spec/tests/relation_spec.rb +57 -0
  110. data/spec/tests/table_inheritance_spec.rb +416 -0
  111. metadata +102 -14
  112. data/lib/torque/postgresql/associations/join_dependency/join_association.rb +0 -15
  113. data/lib/torque/postgresql/schema_dumper.rb +0 -91
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Torque
2
4
  module PostgreSQL
3
5
  module Relation
@@ -33,14 +35,11 @@ module Torque
33
35
  # Get all auxiliary statements bound attributes and the base bound
34
36
  # attributes as well
35
37
  def bound_attributes
36
- if Torque::PostgreSQL::AR521
37
- visitor = ::Arel::Visitors::PostgreSQL.new(ActiveRecord::Base.connection)
38
- visitor.accept(self.arel.ast, ::Arel::Collectors::Bind.new).value
39
- else
40
- return super unless self.auxiliary_statements_values.present?
41
- bindings = self.auxiliary_statements_values.map(&:bound_attributes)
42
- (bindings + super).flatten
43
- end
38
+ visitor = ::Arel::Visitors::PostgreSQL.new(ActiveRecord::Base.connection)
39
+ visitor.accept(self.arel.ast, ::Arel::Collectors::Composite.new(
40
+ ::Arel::Collectors::SQLString.new,
41
+ ::Arel::Collectors::Bind.new,
42
+ )).value.last
44
43
  end
45
44
 
46
45
  private
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Torque
2
4
  module PostgreSQL
3
5
  module Relation
@@ -33,7 +35,7 @@ module Torque
33
35
 
34
36
  # Hook arel build to add the distinct on clause
35
37
  def build_arel(*)
36
- arel = Torque::PostgreSQL::AR521 ? super : super()
38
+ arel = super
37
39
  value = self.distinct_on_values
38
40
  arel.distinct_on(resolve_column(value)) if value.present?
39
41
  arel
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Torque
2
4
  module PostgreSQL
3
5
  module Relation
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Torque
2
4
  module PostgreSQL
3
5
  module Relation
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Torque
2
4
  module PostgreSQL
3
5
  LookupError = Class.new(ArgumentError)
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Torque
2
4
  module PostgreSQL
3
- VERSION = '1.1.7'
5
+ VERSION = '2.0.4'
4
6
  end
5
7
  end
@@ -0,0 +1,19 @@
1
+ en:
2
+ torque: 'Torque Rocks!'
3
+ activerecord:
4
+ attributes:
5
+ user:
6
+ role:
7
+ visitor: 'A simple Visitor'
8
+ role:
9
+ assistant: 'An Assistant'
10
+ enums:
11
+ content_status:
12
+ created: '1 - Created'
13
+ roles:
14
+ manager: 'The Manager'
15
+ enum:
16
+ content_status:
17
+ draft: 'Draft (2)'
18
+ published: 'Finally published'
19
+ admin: 'Super Duper Admin'
@@ -0,0 +1,6 @@
1
+ FactoryBot.define do
2
+ factory :author do
3
+ name { Faker::Name.name }
4
+ specialty { Enum::Specialties.values.sample }
5
+ end
6
+ end
@@ -0,0 +1,13 @@
1
+ FactoryBot.define do
2
+ factory :comment do
3
+ content { Faker::Lorem.paragraph }
4
+
5
+ factory :comment_recursive do
6
+ comment_id { Comment.order('RANDOM()').first.id }
7
+ end
8
+
9
+ trait :random_user do
10
+ user_id { User.order('RANDOM()').first.id }
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,6 @@
1
+ FactoryBot.define do
2
+ factory :post do
3
+ title { Faker::Lorem.sentence }
4
+ content { Faker::Lorem.paragraph }
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ FactoryBot.define do
2
+ factory :tag do
3
+ name { Faker::Lorem.sentence }
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ FactoryBot.define do
2
+ factory :text do
3
+ content { Faker::Lorem.sentence }
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ FactoryBot.define do
2
+ factory :user do
3
+ name { Faker::Name.name }
4
+ role { 'visitor' }
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ FactoryBot.define do
2
+ factory :video do
3
+ title { Faker::Lorem.sentence }
4
+ end
5
+ end
@@ -0,0 +1,16 @@
1
+ module Mocks
2
+ module CacheQuery
3
+ def get_last_executed_query(&block)
4
+ conn = ActiveRecord::Base.connection
5
+ conn.instance_variable_set(:@query_cache_enabled, true)
6
+
7
+ block.call
8
+ result = conn.query_cache.keys.first
9
+
10
+ conn.instance_variable_set(:@query_cache_enabled, false)
11
+ conn.instance_variable_get(:@query_cache).delete(result)
12
+
13
+ result
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,35 @@
1
+ module Mocks
2
+ module CreateTable
3
+ def mock_create_table
4
+ path = ActiveRecord::Base.connection.method(:create_table).super_method.source_location[0]
5
+
6
+ before :all do
7
+ ActiveRecord::ConnectionAdapters::SchemaStatements.send(:define_method, :create_table) do |table_name, **options, &block|
8
+ td = create_table_definition(table_name, **options)
9
+
10
+ # Does things as the same as schema statements
11
+ if options[:id] != false && !options[:as]
12
+ pk = options.fetch(:primary_key) do
13
+ ActiveRecord::Base.get_primary_key table_name.to_s.singularize
14
+ end
15
+
16
+ if pk.is_a?(Array)
17
+ td.primary_keys pk
18
+ else
19
+ td.primary_key pk, options.fetch(:id, :primary_key), **options
20
+ end
21
+ end
22
+
23
+ block.call(td) if block.present?
24
+
25
+ # Now generate the SQL and return it
26
+ schema_creation.accept td
27
+ end
28
+ end
29
+
30
+ after :all do
31
+ load path
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,3 @@
1
+ class Activity < ActiveRecord::Base
2
+ belongs_to :author
3
+ end
@@ -0,0 +1,4 @@
1
+ require_relative 'activity'
2
+
3
+ class ActivityBook < Activity
4
+ end
@@ -0,0 +1,7 @@
1
+ require_relative 'activity'
2
+
3
+ class ActivityPost < Activity
4
+ belongs_to :post
5
+ end
6
+
7
+ require_relative 'activity_post/sample'
@@ -0,0 +1,4 @@
1
+ class ActivityPost < Activity
2
+ class Sample < ActivityPost
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ class Author < ActiveRecord::Base
2
+ has_many :activities, -> { cast_records }
3
+ has_many :posts
4
+ end
@@ -0,0 +1,4 @@
1
+ require_relative 'author'
2
+
3
+ class AuthorJournalist < Author
4
+ end
@@ -0,0 +1,3 @@
1
+ class Comment < ActiveRecord::Base
2
+ belongs_to :user
3
+ end
@@ -0,0 +1,2 @@
1
+ class Course < ActiveRecord::Base
2
+ end
@@ -0,0 +1,2 @@
1
+ class Geometry < ActiveRecord::Base
2
+ end
@@ -0,0 +1,4 @@
1
+ require_relative 'comment'
2
+
3
+ class GuestComment < Comment
4
+ end
@@ -0,0 +1,6 @@
1
+ class Post < ActiveRecord::Base
2
+ belongs_to :author
3
+ belongs_to :activity
4
+
5
+ scope :test_scope, -> { where('1=1') }
6
+ end
@@ -0,0 +1,2 @@
1
+ class Tag < ActiveRecord::Base
2
+ end
@@ -0,0 +1,2 @@
1
+ class Text < ActiveRecord::Base
2
+ end
@@ -0,0 +1,2 @@
1
+ class TimeKeeper < ActiveRecord::Base
2
+ end
@@ -0,0 +1,8 @@
1
+ class User < ActiveRecord::Base
2
+ has_many :comments
3
+
4
+ auxiliary_statement :last_comment do |cte|
5
+ cte.query Comment.distinct_on(:user_id).order(:user_id, id: :desc)
6
+ cte.attributes id: :comment_id, content: :comment_content
7
+ end
8
+ end
@@ -0,0 +1,2 @@
1
+ class Video < ActiveRecord::Base
2
+ end
@@ -0,0 +1,141 @@
1
+ # This file is auto-generated from the current state of the database. Instead
2
+ # of editing this file, please use the migrations feature of Active Record to
3
+ # incrementally modify your database, and then regenerate this schema definition.
4
+ #
5
+ # Note that this schema.rb definition is the authoritative source for your
6
+ # database schema. If you need to create the application database on another
7
+ # system, you should be using db:schema:load, not running all the migrations
8
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
10
+ #
11
+ # It's strongly recommended that you check this file into your version control system.
12
+
13
+ begin
14
+ version = 62
15
+
16
+ raise SystemExit if ActiveRecord::Migrator.current_version == version
17
+ ActiveRecord::Schema.define(version: version) do
18
+ self.verbose = false
19
+
20
+ # These are extensions that must be enabled in order to support this database
21
+ enable_extension "plpgsql"
22
+
23
+ # These are user-defined types used on this database
24
+ create_enum "content_status", ["created", "draft", "published", "archived"], force: :cascade
25
+ create_enum "specialties", ["books", "movies", "plays"], force: :cascade
26
+ create_enum "roles", ["visitor", "assistant", "manager", "admin"], force: :cascade
27
+ create_enum "conflicts", ["valid", "invalid", "untrusted"], force: :cascade
28
+ create_enum "types", ["A", "B", "C", "D"], force: :cascade
29
+
30
+ create_table "geometries", force: :cascade do |t|
31
+ t.point "point"
32
+ t.line "line"
33
+ t.lseg "lseg"
34
+ t.box "box"
35
+ t.path "closed_path"
36
+ t.path "open_path"
37
+ t.polygon "polygon"
38
+ t.circle "circle"
39
+ end
40
+
41
+ create_table "time_keepers", force: :cascade do |t|
42
+ t.daterange "available"
43
+ t.tsrange "period"
44
+ t.tstzrange "tzperiod"
45
+ t.interval "th"
46
+ end
47
+
48
+ create_table "tags", force: :cascade do |t|
49
+ t.string "name"
50
+ end
51
+
52
+ create_table "videos", force: :cascade do |t|
53
+ t.bigint "tag_ids", array: true
54
+ t.string "title"
55
+ t.string "url"
56
+ t.enum "type", subtype: :types
57
+ t.enum "conflicts", subtype: :conflicts, array: true
58
+ t.datetime "created_at", null: false
59
+ t.datetime "updated_at", null: false
60
+ end
61
+
62
+ create_table "authors", force: :cascade do |t|
63
+ t.string "name"
64
+ t.string "type"
65
+ t.enum "specialty", subtype: :specialties
66
+ end
67
+
68
+ create_table "texts", force: :cascade do |t|
69
+ t.integer "user_id"
70
+ t.string "content"
71
+ t.enum "conflict", subtype: :conflicts
72
+ end
73
+
74
+ create_table "comments", force: :cascade do |t|
75
+ t.integer "user_id", null: false
76
+ t.integer "comment_id"
77
+ t.text "content", null: false
78
+ t.string "kind"
79
+ t.index ["user_id"], name: "index_comments_on_user_id", using: :btree
80
+ t.index ["comment_id"], name: "index_comments_on_comment_id", using: :btree
81
+ end
82
+
83
+ create_table "courses", force: :cascade do |t|
84
+ t.string "title", null: false
85
+ t.interval "duration"
86
+ t.enum "types", subtype: :types, array: true
87
+ t.datetime "created_at", null: false
88
+ t.datetime "updated_at", null: false
89
+ end
90
+
91
+ create_table "images", force: :cascade, id: false do |t|
92
+ t.string "file"
93
+ end
94
+
95
+ create_table "posts", force: :cascade do |t|
96
+ t.integer "author_id"
97
+ t.integer "activity_id"
98
+ t.string "title"
99
+ t.text "content"
100
+ t.enum "status", subtype: :content_status
101
+ t.index ["author_id"], name: "index_posts_on_author_id", using: :btree
102
+ end
103
+
104
+ create_table "users", force: :cascade do |t|
105
+ t.string "name", null: false
106
+ t.enum "role", subtype: :roles, default: :visitor
107
+ t.datetime "created_at", null: false
108
+ t.datetime "updated_at", null: false
109
+ end
110
+
111
+ create_table "activities", force: :cascade do |t|
112
+ t.integer "author_id"
113
+ t.string "title"
114
+ t.boolean "active"
115
+ t.enum "kind", subtype: :types
116
+ t.datetime "created_at", null: false
117
+ t.datetime "updated_at", null: false
118
+ end
119
+
120
+ create_table "activity_books", force: :cascade, inherits: :activities do |t|
121
+ t.text "description"
122
+ t.string "url"
123
+ t.boolean "activated"
124
+ end
125
+
126
+ create_table "activity_posts", force: :cascade, inherits: [:activities, :images] do |t|
127
+ t.integer "post_id"
128
+ t.string "url"
129
+ t.integer "activated"
130
+ end
131
+
132
+ create_table "activity_post_samples", force: :cascade, inherits: :activity_posts
133
+
134
+ # create_table "activity_blanks", force: :cascade, inherits: :activities
135
+
136
+ # create_table "activity_images", force: :cascade, inherits: [:activities, :images]
137
+
138
+ add_foreign_key "posts", "authors"
139
+ end
140
+ rescue SystemExit
141
+ end
@@ -0,0 +1,59 @@
1
+ require 'torque-postgresql'
2
+ require 'database_cleaner'
3
+ require 'factory_bot'
4
+ require 'dotenv'
5
+ require 'faker'
6
+ require 'rspec'
7
+ require 'byebug'
8
+
9
+ Dotenv.load
10
+
11
+ ActiveRecord::Base.establish_connection(ENV['DATABASE_URL'])
12
+ cache = ActiveRecord::Base.connection.schema_cache
13
+
14
+ cleaner = ->() do
15
+ cache.instance_variable_set(:@inheritance_loaded, false)
16
+ cache.instance_variable_set(:@inheritance_dependencies, {})
17
+ cache.instance_variable_set(:@inheritance_associations, {})
18
+ end
19
+
20
+ load File.join('schema.rb')
21
+ Dir.glob(File.join('spec', '{models,factories,mocks}', '*.rb')) do |file|
22
+ require file[5..-4]
23
+ end
24
+
25
+ cleaner.call
26
+ I18n.load_path << Pathname.pwd.join('spec', 'en.yml')
27
+ RSpec.configure do |config|
28
+ config.extend Mocks::CreateTable
29
+ config.include Mocks::CacheQuery
30
+
31
+ config.formatter = :documentation
32
+ config.color = true
33
+ config.tty = true
34
+
35
+ # Handles acton before rspec initialize
36
+ config.before(:suite) do
37
+ DatabaseCleaner.clean_with(:truncation)
38
+ end
39
+
40
+ config.before(:each) do
41
+ DatabaseCleaner.strategy = :transaction
42
+ end
43
+
44
+ config.before(:each, js: true) do
45
+ DatabaseCleaner.strategy = :truncation
46
+ end
47
+
48
+ config.before(:each) do
49
+ DatabaseCleaner.start
50
+ end
51
+
52
+ config.after(:each) do
53
+ DatabaseCleaner.clean
54
+ end
55
+
56
+ config.before(:each) do
57
+ cleaner.call
58
+ end
59
+ end