torque-postgresql 3.0.0 → 3.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d4fac19ef8680f477df0f79502331ddda06266658a54c8128321d68145a9f18b
4
- data.tar.gz: 0e93ec49f80d40ec9ce9b7fcc5ef0eff65a882cad79a63e5429657ad9c66691b
3
+ metadata.gz: dc0fe29b7ec2c1478b6718efaddbb7ba2be2c6fd18dc56dc5e52ca52575811dd
4
+ data.tar.gz: b1f7c28054bb9ed68ebc2506ca71cb0d4c42563102438f39202d638278d45ee9
5
5
  SHA512:
6
- metadata.gz: 4a9abd492b544296c29e0949e1ad0ad4852a1ed0c48379551e5ffbbaad7018579cad994ac2a841231603bdddd8da4b448d7771a9086312289f818124d842d6a6
7
- data.tar.gz: 8019255d20eff471ed177078e1bd6042a0a9b95752d32578bdb8ce86afdf9cffbefa8ed181caab0143f0dbbf80cfc39c99fd005cfc2b28089687b26a635268ef
6
+ metadata.gz: a13fa4357d31fed2106ebcef94ff51decb7003e30a1f0a2fe5af83ceb3d18cc7d909fcf1c6f65ea63c7c11eccb1e312d7c85ff66d16125d50bd10b1e1772ab14
7
+ data.tar.gz: 7f2a2951c337e2326ad0c808423f6017b11086538a8bcd0b40078729e26b02232f7b97c39de96ab70e81c5eac5382ce7f0aff9965e4fbd36571b4b89bcdcbcab
@@ -40,34 +40,29 @@ module Torque
40
40
  result
41
41
  end
42
42
 
43
- # Build the id constraint checking if both types are perfect matching
43
+ # Build the id constraint checking if both types are perfect matching.
44
+ # The klass attribute (left side) will always be a column attribute
44
45
  def build_id_constraint(klass_attr, source_attr)
45
46
  return klass_attr.eq(source_attr) unless connected_through_array?
46
47
 
47
48
  # Klass and key are associated with the reflection Class
48
- klass_type = klass.columns_hash[join_primary_key.to_s]
49
- # active_record and foreign_key are associated with the source Class
50
- source_type = active_record.columns_hash[join_foreign_key.to_s]
51
-
52
- # If both are attributes but the left side is not an array, and the
53
- # right side is, use the ANY operation
54
- any_operation = arel_array_to_any(klass_attr, source_attr, klass_type, source_type)
55
- return klass_attr.eq(any_operation) if any_operation
49
+ klass_type = klass.columns_hash[join_keys.key.to_s]
50
+
51
+ # Apply an ANY operation which checks if the single value on the left
52
+ # side exists in the array on the right side
53
+ if source_attr.is_a?(AREL_ATTR)
54
+ any_value = [klass_attr, source_attr]
55
+ any_value.reverse! if klass_type.try(:array?)
56
+ return any_value.shift.eq(::Arel::Nodes::NamedFunction.new('ANY', any_value))
57
+ end
56
58
 
57
59
  # If the left side is not an array, just use the IN condition
58
60
  return klass_attr.in(source_attr) unless klass_type.try(:array)
59
61
 
60
- # Decide if should apply a cast to ensure same type comparision
61
- should_cast = klass_type.type.eql?(:integer) && source_type.type.eql?(:integer)
62
- should_cast &= !klass_type.sql_type.eql?(source_type.sql_type)
63
- should_cast |= !(klass_attr.is_a?(AREL_ATTR) && source_attr.is_a?(AREL_ATTR))
64
-
65
- # Apply necessary transformations to values
66
- klass_attr = cast_constraint_to_array(klass_type, klass_attr, should_cast)
67
- source_attr = cast_constraint_to_array(source_type, source_attr, should_cast)
68
-
69
- # Return the overlap condition
70
- klass_attr.overlaps(source_attr)
62
+ # Build the overlap condition (array && array) ensuring that the right
63
+ # side has the same type as the left side
64
+ source_attr = ::Arel::Nodes.build_quoted(Array.wrap(source_attr))
65
+ klass_attr.overlaps(source_attr.cast(klass_type.sql_type_metadata.sql_type))
71
66
  end
72
67
 
73
68
  # TODO: Deprecate this method
@@ -83,24 +78,6 @@ module Torque
83
78
 
84
79
  build_id_constraint(klass_attr, source_attr)
85
80
  end
86
-
87
- # Prepare a value for an array constraint overlap condition
88
- def cast_constraint_to_array(type, value, should_cast)
89
- base_ready = type.try(:array) && value.is_a?(AREL_ATTR)
90
- return value if base_ready && (type.sql_type.eql?(ARR_NO_CAST) || !should_cast)
91
-
92
- value = ::Arel::Nodes.build_quoted(Array.wrap(value)) unless base_ready
93
- value = value.cast(ARR_CAST) if should_cast
94
- value
95
- end
96
-
97
- # Check if it's possible to turn both attributes into an ANY condition
98
- def arel_array_to_any(klass_attr, source_attr, klass_type, source_type)
99
- return unless !klass_type.try(:array) && source_type.try(:array) &&
100
- klass_attr.is_a?(AREL_ATTR) && source_attr.is_a?(AREL_ATTR)
101
-
102
- ::Arel::Nodes::NamedFunction.new('ANY', [source_attr])
103
- end
104
81
  end
105
82
 
106
83
  ::ActiveRecord::Reflection::AbstractReflection.prepend(AbstractReflection)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Torque
4
4
  module PostgreSQL
5
- VERSION = '3.0.0'
5
+ VERSION = '3.0.1'
6
6
  end
7
7
  end
data/spec/spec_helper.rb CHANGED
@@ -39,6 +39,7 @@ RSpec.configure do |config|
39
39
 
40
40
  # Handles acton before rspec initialize
41
41
  config.before(:suite) do
42
+ ActiveSupport::Deprecation.silenced = true
42
43
  DatabaseCleaner.clean_with(:truncation)
43
44
  end
44
45
 
@@ -393,4 +393,51 @@ RSpec.describe 'BelongsToMany' do
393
393
  end
394
394
  end
395
395
  end
396
+
397
+ context 'using uuid' do
398
+ let(:connection) { ActiveRecord::Base.connection }
399
+ let(:game) { Class.new(ActiveRecord::Base) }
400
+ let(:player) { Class.new(ActiveRecord::Base) }
401
+ let(:other) { player.create }
402
+
403
+ # TODO: Set as a shred example
404
+ before do
405
+ connection.create_table(:players, id: :uuid) { |t| t.string :name }
406
+ connection.create_table(:games, id: :uuid) { |t| t.uuid :player_ids, array: true }
407
+
408
+ game.table_name = 'games'
409
+ player.table_name = 'players'
410
+ game.belongs_to_many :players, anonymous_class: player,
411
+ inverse_of: false, foreign_key: :player_ids
412
+ end
413
+
414
+ subject { game.create }
415
+
416
+ it 'loads associated records' do
417
+ subject.update(player_ids: [other.id])
418
+ expect(subject.players.to_sql).to be_eql(<<-SQL.squish)
419
+ SELECT "players".* FROM "players" WHERE "players"."id" IN ('#{other.id}')
420
+ SQL
421
+
422
+ expect(subject.players.load).to be_a(ActiveRecord::Associations::CollectionProxy)
423
+ expect(subject.players.to_a).to be_eql([other])
424
+ end
425
+
426
+ it 'can preload records' do
427
+ records = 5.times.map { player.create }
428
+ subject.players.concat(records)
429
+
430
+ entries = game.all.includes(:players).load
431
+
432
+ expect(entries.size).to be_eql(1)
433
+ expect(entries.first.players).to be_loaded
434
+ expect(entries.first.players.size).to be_eql(5)
435
+ end
436
+
437
+ it 'can joins records' do
438
+ query = game.all.joins(:players)
439
+ expect(query.to_sql).to match(/INNER JOIN "players"/)
440
+ expect { query.load }.not_to raise_error
441
+ end
442
+ end
396
443
  end
@@ -411,4 +411,48 @@ RSpec.describe 'HasMany' do
411
411
  expect { query.load }.not_to raise_error
412
412
  end
413
413
  end
414
+
415
+ context 'using uuid' do
416
+ let(:connection) { ActiveRecord::Base.connection }
417
+ let(:game) { Class.new(ActiveRecord::Base) }
418
+ let(:player) { Class.new(ActiveRecord::Base) }
419
+
420
+ # TODO: Set as a shred example
421
+ before do
422
+ connection.create_table(:players, id: :uuid) { |t| t.string :name }
423
+ connection.create_table(:games, id: :uuid) { |t| t.uuid :player_ids, array: true }
424
+
425
+ game.table_name = 'games'
426
+ player.table_name = 'players'
427
+ player.has_many :games, array: true, anonymous_class: game,
428
+ inverse_of: false, foreign_key: :player_ids
429
+ end
430
+
431
+ subject { player.create }
432
+
433
+ it 'loads associated records' do
434
+ expect(subject.games.to_sql).to match(Regexp.new(<<-SQL.squish))
435
+ SELECT "games"\\.\\* FROM "games"
436
+ WHERE \\(?"games"\\."player_ids" && ARRAY\\['#{subject.id}'\\]::uuid\\[\\]\\)?
437
+ SQL
438
+
439
+ expect(subject.games.load).to be_a(ActiveRecord::Associations::CollectionProxy)
440
+ expect(subject.games.to_a).to be_eql([])
441
+ end
442
+
443
+ it 'can preload records' do
444
+ 5.times { game.create(player_ids: [subject.id]) }
445
+ entries = player.all.includes(:games).load
446
+
447
+ expect(entries.size).to be_eql(1)
448
+ expect(entries.first.games).to be_loaded
449
+ expect(entries.first.games.size).to be_eql(5)
450
+ end
451
+
452
+ it 'can joins records' do
453
+ query = player.all.joins(:games)
454
+ expect(query.to_sql).to match(/INNER JOIN "games"/)
455
+ expect { query.load }.not_to raise_error
456
+ end
457
+ end
414
458
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: torque-postgresql
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carlos Silva
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-04 00:00:00.000000000 Z
11
+ date: 2022-04-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails