torque-postgresql 2.2.3 → 3.0.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/lib/torque/postgresql/adapter/database_statements.rb +12 -1
- data/lib/torque/postgresql/adapter/oid/enum_set.rb +1 -1
- data/lib/torque/postgresql/adapter/oid.rb +0 -3
- data/lib/torque/postgresql/adapter/quoting.rb +12 -20
- data/lib/torque/postgresql/adapter/schema_creation.rb +1 -2
- data/lib/torque/postgresql/adapter/schema_definitions.rb +0 -37
- data/lib/torque/postgresql/adapter/schema_dumper.rb +0 -40
- data/lib/torque/postgresql/adapter/schema_statements.rb +0 -15
- data/lib/torque/postgresql/adapter.rb +0 -9
- data/lib/torque/postgresql/associations/belongs_to_many_association.rb +5 -4
- data/lib/torque/postgresql/associations/{association.rb → foreign_association.rb} +1 -4
- data/lib/torque/postgresql/associations/preloader/association.rb +53 -26
- data/lib/torque/postgresql/associations/preloader/loader_query.rb +36 -0
- data/lib/torque/postgresql/associations/preloader.rb +1 -0
- data/lib/torque/postgresql/associations.rb +6 -1
- data/lib/torque/postgresql/attributes/builder/period.rb +6 -2
- data/lib/torque/postgresql/config.rb +2 -12
- data/lib/torque/postgresql/reflection/abstract_reflection.rb +5 -7
- data/lib/torque/postgresql/relation.rb +10 -12
- data/lib/torque/postgresql/schema_cache.rb +2 -1
- data/lib/torque/postgresql/version.rb +1 -1
- data/lib/torque-postgresql.rb +0 -1
- data/spec/schema.rb +16 -15
- data/spec/spec_helper.rb +0 -4
- data/spec/tests/arel_spec.rb +17 -8
- data/spec/tests/belongs_to_many_spec.rb +2 -1
- data/spec/tests/enum_set_spec.rb +5 -4
- data/spec/tests/enum_spec.rb +0 -84
- metadata +7 -9
- data/lib/torque/range.rb +0 -20
- data/spec/tests/range_spec.rb +0 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4fac19ef8680f477df0f79502331ddda06266658a54c8128321d68145a9f18b
|
4
|
+
data.tar.gz: 0e93ec49f80d40ec9ce9b7fcc5ef0eff65a882cad79a63e5429657ad9c66691b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a9abd492b544296c29e0949e1ad0ad4852a1ed0c48379551e5ffbbaad7018579cad994ac2a841231603bdddd8da4b448d7771a9086312289f818124d842d6a6
|
7
|
+
data.tar.gz: 8019255d20eff471ed177078e1bd6042a0a9b95752d32578bdb8ce86afdf9cffbefa8ed181caab0143f0dbbf80cfc39c99fd005cfc2b28089687b26a635268ef
|
@@ -34,6 +34,15 @@ module Torque
|
|
34
34
|
execute("SET SESSION IntervalStyle TO 'iso_8601'", 'SCHEMA')
|
35
35
|
end
|
36
36
|
|
37
|
+
# Since enums create new types, type map needs to be rebooted to include
|
38
|
+
# the new ones, both normal and array one
|
39
|
+
def create_enum(name, *)
|
40
|
+
super
|
41
|
+
|
42
|
+
oid = query_value("SELECT #{quote(name)}::regtype::oid", "SCHEMA").to_i
|
43
|
+
load_additional_types([oid])
|
44
|
+
end
|
45
|
+
|
37
46
|
# Change some of the types being mapped
|
38
47
|
def initialize_type_map(m = type_map)
|
39
48
|
super
|
@@ -54,7 +63,7 @@ module Torque
|
|
54
63
|
|
55
64
|
# Add the composite types to be loaded too.
|
56
65
|
def torque_load_additional_types(oids = nil)
|
57
|
-
filter = "AND a.typelem::integer IN (%s)" % oids.join(
|
66
|
+
filter = ("AND a.typelem::integer IN (%s)" % oids.join(', ')) if oids
|
58
67
|
|
59
68
|
query = <<-SQL
|
60
69
|
SELECT a.typelem AS oid, t.typname, t.typelem,
|
@@ -132,7 +141,9 @@ module Torque
|
|
132
141
|
# Get the list of columns, and their definition, but only from the
|
133
142
|
# actual table, does not include columns that comes from inherited table
|
134
143
|
def column_definitions(table_name) # :nodoc:
|
144
|
+
# Only affects inheritance
|
135
145
|
local_condition = 'AND a.attislocal IS TRUE' if @_dump_mode
|
146
|
+
|
136
147
|
query(<<-SQL, 'SCHEMA')
|
137
148
|
SELECT a.attname, format_type(a.atttypid, a.atttypmod),
|
138
149
|
pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
|
@@ -19,9 +19,6 @@ module Torque
|
|
19
19
|
ActiveRecord::Type.register(:enum_set, OID::EnumSet, adapter: :postgresql)
|
20
20
|
ActiveRecord::Type.register(:line, OID::Line, adapter: :postgresql)
|
21
21
|
ActiveRecord::Type.register(:segment, OID::Segment, adapter: :postgresql)
|
22
|
-
|
23
|
-
ActiveRecord::Type.register(:interval, OID::Interval, adapter: :postgresql) \
|
24
|
-
unless PostgreSQL::AR610
|
25
22
|
end
|
26
23
|
end
|
27
24
|
end
|
@@ -22,27 +22,19 @@ module Torque
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def quote_default_expression(value, column)
|
25
|
-
return super unless value.class <= Array
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
return super unless value.class <= Array || value.class <= Set
|
26
|
+
|
27
|
+
type =
|
28
|
+
if column.is_a?(ColumnDefinition) && column.options.try(:[], :array)
|
29
|
+
# This is the general way
|
30
|
+
lookup_cast_type(column.sql_type)
|
31
|
+
elsif column.is_a?(Column) && column.array?
|
32
|
+
# When using +change_column_default+
|
33
|
+
lookup_cast_type_from_column(column)
|
34
|
+
end
|
35
|
+
|
36
|
+
type.nil? ? super : quote(type.serialize(value.to_a))
|
31
37
|
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def _quote(value)
|
36
|
-
return super unless value.is_a?(Array)
|
37
|
-
|
38
|
-
values = value.map(&method(:quote))
|
39
|
-
"ARRAY[#{values.join(','.freeze)}]"
|
40
|
-
end
|
41
|
-
|
42
|
-
def _type_cast(value)
|
43
|
-
return super unless value.is_a?(Array)
|
44
|
-
value.map(&method(:quote)).join(','.freeze)
|
45
|
-
end
|
46
38
|
end
|
47
39
|
end
|
48
40
|
end
|
@@ -33,8 +33,7 @@ module Torque
|
|
33
33
|
create_sql << "(#{statements.join(', ')})" \
|
34
34
|
if statements.present? || o.inherits.present?
|
35
35
|
|
36
|
-
|
37
|
-
add_table_options!(create_sql, options)
|
36
|
+
add_table_options!(create_sql, o)
|
38
37
|
|
39
38
|
if o.inherits.present?
|
40
39
|
tables = o.inherits.map(&method(:quote_table_name))
|
@@ -3,35 +3,7 @@
|
|
3
3
|
module Torque
|
4
4
|
module PostgreSQL
|
5
5
|
module Adapter
|
6
|
-
module ColumnMethods
|
7
|
-
|
8
|
-
# Creates a column with an interval type, allowing span of times and
|
9
|
-
# dates to be stored without having to store a seconds-based integer
|
10
|
-
# or any sort of other approach
|
11
|
-
def interval(*args, **options)
|
12
|
-
args.each { |name| column(name, :interval, **options) }
|
13
|
-
end
|
14
|
-
|
15
|
-
# Creates a column with an enum type, needing to specify the subtype,
|
16
|
-
# which is basically the name of the type defined prior creating the
|
17
|
-
# column
|
18
|
-
def enum(*args, **options)
|
19
|
-
subtype = options.delete(:subtype)
|
20
|
-
args.each { |name| column(name, (subtype || name), **options) }
|
21
|
-
end
|
22
|
-
|
23
|
-
# Creates a column with an enum array type, needing to specify the
|
24
|
-
# subtype, which is basically the name of the type defined prior
|
25
|
-
# creating the column
|
26
|
-
def enum_set(*args, **options)
|
27
|
-
super(*args, **options.merge(array: true))
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
6
|
module TableDefinition
|
33
|
-
include ColumnMethods
|
34
|
-
|
35
7
|
attr_reader :inherits
|
36
8
|
|
37
9
|
def initialize(*args, **options)
|
@@ -42,16 +14,7 @@ module Torque
|
|
42
14
|
end
|
43
15
|
end
|
44
16
|
|
45
|
-
ActiveRecord::ConnectionAdapters::PostgreSQL::Table.include ColumnMethods
|
46
17
|
ActiveRecord::ConnectionAdapters::PostgreSQL::TableDefinition.include TableDefinition
|
47
|
-
|
48
|
-
if ActiveRecord::ConnectionAdapters::PostgreSQL.const_defined?('ColumnDefinition')
|
49
|
-
module ColumnDefinition
|
50
|
-
attr_accessor :subtype
|
51
|
-
end
|
52
|
-
|
53
|
-
ActiveRecord::ConnectionAdapters::PostgreSQL::ColumnDefinition.include ColumnDefinition
|
54
|
-
end
|
55
18
|
end
|
56
19
|
end
|
57
20
|
end
|
@@ -12,33 +12,13 @@ module Torque
|
|
12
12
|
stream
|
13
13
|
end
|
14
14
|
|
15
|
-
def extensions(stream) # :nodoc:
|
16
|
-
super
|
17
|
-
user_defined_types(stream)
|
18
|
-
end
|
19
|
-
|
20
15
|
# Translate +:enum_set+ into +:enum+
|
21
16
|
def schema_type(column)
|
22
17
|
column.type == :enum_set ? :enum : super
|
23
18
|
end
|
24
19
|
|
25
|
-
# Adds +:subtype+ option to the default set
|
26
|
-
def prepare_column_options(column)
|
27
|
-
spec = super
|
28
|
-
|
29
|
-
if subtype = schema_subtype(column)
|
30
|
-
spec[:subtype] = subtype
|
31
|
-
end
|
32
|
-
|
33
|
-
spec
|
34
|
-
end
|
35
|
-
|
36
20
|
private
|
37
21
|
|
38
|
-
def schema_subtype(column)
|
39
|
-
column.sql_type.to_sym.inspect if column.type == :enum || column.type == :enum_set
|
40
|
-
end
|
41
|
-
|
42
22
|
def tables(stream) # :nodoc:
|
43
23
|
inherited_tables = @connection.inherited_tables
|
44
24
|
sorted_tables = @connection.tables.sort - @connection.views
|
@@ -83,26 +63,6 @@ module Torque
|
|
83
63
|
functions(stream) if defined?(::Fx::SchemaDumper::Function)
|
84
64
|
triggers(stream) if defined?(::Fx::SchemaDumper::Trigger)
|
85
65
|
end
|
86
|
-
|
87
|
-
# Dump user defined types like enum
|
88
|
-
def user_defined_types(stream)
|
89
|
-
types = @connection.user_defined_types('e')
|
90
|
-
return unless types.any?
|
91
|
-
|
92
|
-
stream.puts " # These are user-defined types used on this database"
|
93
|
-
types.sort_by(&:first).each { |(name, type)| send(type.to_sym, name, stream) }
|
94
|
-
stream.puts
|
95
|
-
rescue => e
|
96
|
-
stream.puts "# Could not dump user-defined types because of following #{e.class}"
|
97
|
-
stream.puts "# #{e.message}"
|
98
|
-
stream.puts
|
99
|
-
end
|
100
|
-
|
101
|
-
# Dump enum custom type
|
102
|
-
def enum(name, stream)
|
103
|
-
values = @connection.enum_values(name).map { |v| "\"#{v}\"" }
|
104
|
-
stream.puts " create_enum \"#{name}\", [#{values.join(', ')}], force: :cascade"
|
105
|
-
end
|
106
66
|
end
|
107
67
|
|
108
68
|
ActiveRecord::ConnectionAdapters::PostgreSQL::SchemaDumper.prepend SchemaDumper
|
@@ -25,21 +25,6 @@ module Torque
|
|
25
25
|
SQL
|
26
26
|
end
|
27
27
|
|
28
|
-
# Creates a new PostgreSQL enumerator type
|
29
|
-
#
|
30
|
-
# Example:
|
31
|
-
# create_enum 'status', ['foo', 'bar']
|
32
|
-
# create_enum 'status', ['foo', 'bar'], prefix: true
|
33
|
-
# create_enum 'status', ['foo', 'bar'], suffix: 'test'
|
34
|
-
# create_enum 'status', ['foo', 'bar'], force: true
|
35
|
-
def create_enum(name, values, options = {})
|
36
|
-
drop_type(name, options) if options[:force]
|
37
|
-
execute <<-SQL.squish
|
38
|
-
CREATE TYPE #{quote_type_name(name, options[:schema])} AS ENUM
|
39
|
-
(#{quote_enum_values(name, values, options).join(', ')})
|
40
|
-
SQL
|
41
|
-
end
|
42
|
-
|
43
28
|
# Changes the enumerator by adding new values
|
44
29
|
#
|
45
30
|
# Example:
|
@@ -49,15 +49,6 @@ module Torque
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
end
|
52
|
-
|
53
|
-
# Extend the extract default value to support array
|
54
|
-
def extract_value_from_default(default)
|
55
|
-
return super unless Torque::PostgreSQL.config.use_extended_defaults
|
56
|
-
return super unless default&.match(/ARRAY\[(.*?)\](?:::"?([\w. ]+)"?(?:\[\])+)?$/)
|
57
|
-
|
58
|
-
arr = $1.split(/(?!\B\[[^\]]*), ?(?![^\[]*\]\B)/)
|
59
|
-
DeduplicatableArray.new(arr.map(&method(:extract_value_from_default)))
|
60
|
-
end
|
61
52
|
end
|
62
53
|
|
63
54
|
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend Adapter
|
@@ -53,8 +53,8 @@ module Torque
|
|
53
53
|
|
54
54
|
def load_target
|
55
55
|
if stale_target? || find_target?
|
56
|
-
|
57
|
-
@target = merge_target_lists(
|
56
|
+
persisted_records = (find_target || []) + target.extract!(&:persisted?)
|
57
|
+
@target = merge_target_lists(persisted_records, target)
|
58
58
|
end
|
59
59
|
|
60
60
|
loaded!
|
@@ -228,8 +228,9 @@ module Torque
|
|
228
228
|
end
|
229
229
|
|
230
230
|
def invertible_for?(record)
|
231
|
-
inverse = inverse_reflection_for(record)
|
232
|
-
|
231
|
+
return unless (inverse = inverse_reflection_for(record))
|
232
|
+
collection_class = ::ActiveRecord::Associations::HasManyAssociation
|
233
|
+
inverse.is_a?(collection_class) && inverse.connected_through_array?
|
233
234
|
end
|
234
235
|
|
235
236
|
def stale_state
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module Torque
|
4
4
|
module PostgreSQL
|
5
5
|
module Associations
|
6
|
-
module
|
6
|
+
module ForeignAssociation
|
7
7
|
|
8
8
|
# There is no problem of adding temporary items on target because
|
9
9
|
# CollectionProxy will handle memory and persisted relationship
|
@@ -33,9 +33,6 @@ module Torque
|
|
33
33
|
end
|
34
34
|
|
35
35
|
end
|
36
|
-
|
37
|
-
::ActiveRecord::Associations::Association.prepend(Association)
|
38
|
-
::ActiveRecord::Associations::HasManyAssociation.prepend(Association)
|
39
36
|
end
|
40
37
|
end
|
41
38
|
end
|
@@ -11,8 +11,61 @@ module Torque
|
|
11
11
|
# For reflections connected through an array, make sure to properly
|
12
12
|
# decuple the list of ids and set them as associated with the owner
|
13
13
|
def run
|
14
|
+
return self if run?
|
14
15
|
return super unless connected_through_array?
|
16
|
+
|
17
|
+
@run = true
|
15
18
|
send("run_array_for_#{@reflection.macro}")
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
# Correctly correlate records when they are connected theough an array
|
23
|
+
def set_inverse(record)
|
24
|
+
return super unless connected_through_array? && @reflection.macro == :has_many
|
25
|
+
|
26
|
+
# Only the first owner is associated following the same instruction
|
27
|
+
# on the original implementation
|
28
|
+
convert_key(record[association_key_name])&.each do |key|
|
29
|
+
if owners = owners_by_key[key]
|
30
|
+
association = owners.first.association(reflection.name)
|
31
|
+
association.set_inverse_instance(record)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Requires a slight change when running on has many since the value
|
37
|
+
# of the foreign key being an array
|
38
|
+
def load_records(raw_records = nil)
|
39
|
+
return super unless connected_through_array? && @reflection.macro == :has_many
|
40
|
+
|
41
|
+
@records_by_owner = {}.compare_by_identity
|
42
|
+
raw_records ||= loader_query.records_for([self])
|
43
|
+
|
44
|
+
@preloaded_records = raw_records.select do |record|
|
45
|
+
assignments = false
|
46
|
+
|
47
|
+
keys = convert_key(record[association_key_name]) || []
|
48
|
+
owners_by_key.values_at(*keys).each do |owner|
|
49
|
+
entries = (@records_by_owner[owner] ||= [])
|
50
|
+
|
51
|
+
if reflection.collection? || entries.empty?
|
52
|
+
entries << record
|
53
|
+
assignments = true
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
assignments
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Make sure to change the process when connected through an array
|
62
|
+
def owners_by_key
|
63
|
+
return super unless connected_through_array?
|
64
|
+
@owners_by_key ||= owners.each_with_object({}) do |owner, result|
|
65
|
+
Array.wrap(convert_key(owner[owner_key_name])).each do |key|
|
66
|
+
(result[key] ||= []) << owner
|
67
|
+
end
|
68
|
+
end
|
16
69
|
end
|
17
70
|
|
18
71
|
private
|
@@ -41,32 +94,6 @@ module Torque
|
|
41
94
|
end
|
42
95
|
end
|
43
96
|
|
44
|
-
if PostgreSQL::AR604
|
45
|
-
# This is how Rails 6.0.4 and 6.1 now load the records
|
46
|
-
def load_records
|
47
|
-
return super unless connected_through_array?
|
48
|
-
|
49
|
-
@records_by_owner = {}.compare_by_identity
|
50
|
-
raw_records = owner_keys.empty? ? [] : records_for(owner_keys)
|
51
|
-
|
52
|
-
@preloaded_records = raw_records.select do |record|
|
53
|
-
assignments = false
|
54
|
-
|
55
|
-
ids = convert_key(record[association_key_name])
|
56
|
-
owners_by_key.values_at(*ids).flat_map do |owner|
|
57
|
-
entries = (@records_by_owner[owner] ||= [])
|
58
|
-
|
59
|
-
if reflection.collection? || entries.empty?
|
60
|
-
entries << record
|
61
|
-
assignments = true
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
assignments
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
97
|
# Build correctly the constraint condition in order to get the
|
71
98
|
# associated ids
|
72
99
|
def records_for(ids, &block)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Torque
|
4
|
+
module PostgreSQL
|
5
|
+
module Associations
|
6
|
+
module Preloader
|
7
|
+
module LoaderQuery
|
8
|
+
def foreign_column
|
9
|
+
@foreign_column ||= scope.columns_hash[association_key_name]
|
10
|
+
end
|
11
|
+
|
12
|
+
def load_records_for_keys(keys, &block)
|
13
|
+
condition = query_condition_for(keys)
|
14
|
+
scope.where(condition).load(&block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def query_condition_for(keys)
|
18
|
+
if connected_through_array?
|
19
|
+
value = scope.cast_for_condition(foreign_column, keys.to_a)
|
20
|
+
scope.table[association_key_name].overlaps(value)
|
21
|
+
else
|
22
|
+
{ association_key_name => keys }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def connected_through_array?
|
27
|
+
foreign_column.array?
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
::ActiveRecord::Associations::Preloader::Association::LoaderQuery
|
32
|
+
.prepend(LoaderQuery)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -1,5 +1,10 @@
|
|
1
|
-
require_relative 'associations/association'
|
2
1
|
require_relative 'associations/association_scope'
|
3
2
|
require_relative 'associations/belongs_to_many_association'
|
3
|
+
require_relative 'associations/foreign_association'
|
4
|
+
|
4
5
|
require_relative 'associations/builder'
|
5
6
|
require_relative 'associations/preloader'
|
7
|
+
|
8
|
+
association_mod = Torque::PostgreSQL::Associations::ForeignAssociation
|
9
|
+
::ActiveRecord::Associations::HasManyAssociation.prepend(association_mod)
|
10
|
+
::ActiveRecord::Associations::BelongsToManyAssociation.prepend(association_mod)
|
@@ -220,7 +220,7 @@ module Torque
|
|
220
220
|
@arel_threshold_value ||= begin
|
221
221
|
case threshold
|
222
222
|
when Symbol, String
|
223
|
-
"
|
223
|
+
"arel_table['#{threshold}']"
|
224
224
|
when ActiveSupport::Duration
|
225
225
|
value = "'#{threshold.to_i} seconds'"
|
226
226
|
"::Arel.sql(\"#{value}\").cast(:interval)"
|
@@ -453,7 +453,11 @@ module Torque
|
|
453
453
|
attr_value = threshold.present? ? method_names[:real] : attribute
|
454
454
|
default_value = default.inspect
|
455
455
|
|
456
|
-
|
456
|
+
[
|
457
|
+
"return #{default_value} if #{attr_value}.nil?",
|
458
|
+
"(#{attr_value}.min.try(:infinite?) || #{attr_value}.min <= value) &&",
|
459
|
+
" (#{attr_value}.max.try(:infinite?) || #{attr_value}.max > value)",
|
460
|
+
].join("\n")
|
457
461
|
end
|
458
462
|
|
459
463
|
def instance_start
|
@@ -4,11 +4,6 @@ module Torque
|
|
4
4
|
module PostgreSQL
|
5
5
|
include ActiveSupport::Configurable
|
6
6
|
|
7
|
-
# Stores a version check for compatibility purposes
|
8
|
-
AR604 = (ActiveRecord.gem_version >= Gem::Version.new('6.0.4'))
|
9
|
-
AR610 = (ActiveRecord.gem_version >= Gem::Version.new('6.1.0'))
|
10
|
-
AR615 = (ActiveRecord.gem_version >= Gem::Version.new('6.1.5'))
|
11
|
-
|
12
7
|
# Use the same logger as the Active Record one
|
13
8
|
def self.logger
|
14
9
|
ActiveRecord::Base.logger
|
@@ -27,11 +22,6 @@ module Torque
|
|
27
22
|
# same configuration is set to true
|
28
23
|
config.eager_load = false
|
29
24
|
|
30
|
-
# This allows default values to have extended values like arrays and casted
|
31
|
-
# values. Extended defaults are still experimental, so enable and test it
|
32
|
-
# before using it in prod
|
33
|
-
config.use_extended_defaults = false
|
34
|
-
|
35
25
|
# Set a list of irregular model name when associated with table names
|
36
26
|
config.irregular_models = {}
|
37
27
|
def config.irregular_models=(hash)
|
@@ -67,11 +57,11 @@ module Torque
|
|
67
57
|
|
68
58
|
# The name of the method to be used on any ActiveRecord::Base to
|
69
59
|
# initialize model-based enum features
|
70
|
-
enum.base_method = :
|
60
|
+
enum.base_method = :torque_enum
|
71
61
|
|
72
62
|
# The name of the method to be used on any ActiveRecord::Base to
|
73
63
|
# initialize model-based enum set features
|
74
|
-
enum.set_method = :
|
64
|
+
enum.set_method = :torque_enum_set
|
75
65
|
|
76
66
|
# Indicates if bang methods like 'disabled!' should update the record on
|
77
67
|
# database or not
|
@@ -45,9 +45,9 @@ module Torque
|
|
45
45
|
return klass_attr.eq(source_attr) unless connected_through_array?
|
46
46
|
|
47
47
|
# Klass and key are associated with the reflection Class
|
48
|
-
klass_type = klass.columns_hash[
|
48
|
+
klass_type = klass.columns_hash[join_primary_key.to_s]
|
49
49
|
# active_record and foreign_key are associated with the source Class
|
50
|
-
source_type = active_record.columns_hash[
|
50
|
+
source_type = active_record.columns_hash[join_foreign_key.to_s]
|
51
51
|
|
52
52
|
# If both are attributes but the left side is not an array, and the
|
53
53
|
# right side is, use the ANY operation
|
@@ -70,11 +70,9 @@ module Torque
|
|
70
70
|
klass_attr.overlaps(source_attr)
|
71
71
|
end
|
72
72
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
OpenStruct.new(key: join_primary_key, foreign_key: join_foreign_key)
|
77
|
-
end
|
73
|
+
# TODO: Deprecate this method
|
74
|
+
def join_keys
|
75
|
+
OpenStruct.new(key: join_primary_key, foreign_key: join_foreign_key)
|
78
76
|
end
|
79
77
|
|
80
78
|
private
|
@@ -19,6 +19,8 @@ module Torque
|
|
19
19
|
MULTI_VALUE_METHODS = [:distinct_on, :auxiliary_statements, :cast_records, :select_extra]
|
20
20
|
VALUE_METHODS = SINGLE_VALUE_METHODS + MULTI_VALUE_METHODS
|
21
21
|
|
22
|
+
ARColumn = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Column
|
23
|
+
|
22
24
|
# :nodoc:
|
23
25
|
def select_extra_values; get_value(:select_extra); end
|
24
26
|
# :nodoc:
|
@@ -74,6 +76,14 @@ module Torque
|
|
74
76
|
end
|
75
77
|
end
|
76
78
|
|
79
|
+
# Serialize the given value so it can be used in a condition tha involves
|
80
|
+
# the given column
|
81
|
+
def cast_for_condition(column, value)
|
82
|
+
column = columns_hash[column.to_s] unless column.is_a?(ARColumn)
|
83
|
+
caster = connection.lookup_cast_type_from_column(column)
|
84
|
+
connection.type_cast(caster.serialize(value))
|
85
|
+
end
|
86
|
+
|
77
87
|
private
|
78
88
|
|
79
89
|
def build_arel(*)
|
@@ -140,18 +150,6 @@ module Torque
|
|
140
150
|
ActiveRecord::QueryMethods::VALID_UNSCOPING_VALUES += %i[cast_records itself_only
|
141
151
|
distinct_on auxiliary_statements]
|
142
152
|
|
143
|
-
unless AR610
|
144
|
-
Relation::SINGLE_VALUE_METHODS.each do |value|
|
145
|
-
ActiveRecord::QueryMethods::DEFAULT_VALUES[value] = nil \
|
146
|
-
if ActiveRecord::QueryMethods::DEFAULT_VALUES[value].nil?
|
147
|
-
end
|
148
|
-
|
149
|
-
Relation::MULTI_VALUE_METHODS.each do |value|
|
150
|
-
ActiveRecord::QueryMethods::DEFAULT_VALUES[value] ||= \
|
151
|
-
ActiveRecord::QueryMethods::FROZEN_EMPTY_ARRAY
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
153
|
$VERBOSE = warn_level
|
156
154
|
end
|
157
155
|
end
|
@@ -109,6 +109,7 @@ module Torque
|
|
109
109
|
|
110
110
|
# Try to find a model based on a given table
|
111
111
|
def lookup_model(table_name, scoped_class = '')
|
112
|
+
# byebug if table_name == 'activities'
|
112
113
|
scoped_class = scoped_class.name if scoped_class.is_a?(Class)
|
113
114
|
return @data_sources_model_names[table_name] \
|
114
115
|
if @data_sources_model_names.key?(table_name)
|
@@ -123,7 +124,7 @@ module Torque
|
|
123
124
|
|
124
125
|
# Test all the possible names against all the possible scopes
|
125
126
|
until scopes.size == 0
|
126
|
-
scope = scopes.join.safe_constantize
|
127
|
+
scope = scopes.join.chomp('::').safe_constantize
|
127
128
|
model = find_model(max_name, table_name, scope) unless scope.nil?
|
128
129
|
return @data_sources_model_names[table_name] = model unless model.nil?
|
129
130
|
scopes.pop
|
data/lib/torque-postgresql.rb
CHANGED
data/spec/schema.rb
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
#
|
11
11
|
# It's strongly recommended that you check this file into your version control system.
|
12
12
|
|
13
|
-
version =
|
13
|
+
version = 2
|
14
14
|
|
15
15
|
return if ActiveRecord::Migrator.current_version == version
|
16
16
|
ActiveRecord::Schema.define(version: version) do
|
@@ -20,12 +20,13 @@ ActiveRecord::Schema.define(version: version) do
|
|
20
20
|
enable_extension "pgcrypto"
|
21
21
|
enable_extension "plpgsql"
|
22
22
|
|
23
|
-
#
|
24
|
-
|
25
|
-
create_enum "
|
26
|
-
create_enum "
|
27
|
-
create_enum "
|
28
|
-
create_enum "
|
23
|
+
# Custom types defined in this database.
|
24
|
+
# Note that some types may not work with other database engines. Be careful if changing database.
|
25
|
+
create_enum "content_status", ["created", "draft", "published", "archived"]
|
26
|
+
create_enum "specialties", ["books", "movies", "plays"]
|
27
|
+
create_enum "roles", ["visitor", "assistant", "manager", "admin"]
|
28
|
+
create_enum "conflicts", ["valid", "invalid", "untrusted"]
|
29
|
+
create_enum "types", ["A", "B", "C", "D"]
|
29
30
|
|
30
31
|
create_table "geometries", force: :cascade do |t|
|
31
32
|
t.point "point"
|
@@ -53,8 +54,8 @@ ActiveRecord::Schema.define(version: version) do
|
|
53
54
|
t.bigint "tag_ids", array: true
|
54
55
|
t.string "title"
|
55
56
|
t.string "url"
|
56
|
-
t.enum "type",
|
57
|
-
t.enum "conflicts",
|
57
|
+
t.enum "type", enum_type: :types
|
58
|
+
t.enum "conflicts", enum_type: :conflicts, array: true
|
58
59
|
t.datetime "created_at", null: false
|
59
60
|
t.datetime "updated_at", null: false
|
60
61
|
end
|
@@ -62,13 +63,13 @@ ActiveRecord::Schema.define(version: version) do
|
|
62
63
|
create_table "authors", force: :cascade do |t|
|
63
64
|
t.string "name"
|
64
65
|
t.string "type"
|
65
|
-
t.enum "specialty",
|
66
|
+
t.enum "specialty", enum_type: :specialties
|
66
67
|
end
|
67
68
|
|
68
69
|
create_table "texts", force: :cascade do |t|
|
69
70
|
t.integer "user_id"
|
70
71
|
t.string "content"
|
71
|
-
t.enum "conflict",
|
72
|
+
t.enum "conflict", enum_type: :conflicts
|
72
73
|
end
|
73
74
|
|
74
75
|
create_table "comments", force: :cascade do |t|
|
@@ -84,7 +85,7 @@ ActiveRecord::Schema.define(version: version) do
|
|
84
85
|
create_table "courses", force: :cascade do |t|
|
85
86
|
t.string "title", null: false
|
86
87
|
t.interval "duration"
|
87
|
-
t.enum "types",
|
88
|
+
t.enum "types", enum_type: :types, array: true
|
88
89
|
t.datetime "created_at", null: false
|
89
90
|
t.datetime "updated_at", null: false
|
90
91
|
end
|
@@ -98,7 +99,7 @@ ActiveRecord::Schema.define(version: version) do
|
|
98
99
|
t.integer "activity_id"
|
99
100
|
t.string "title"
|
100
101
|
t.text "content"
|
101
|
-
t.enum "status",
|
102
|
+
t.enum "status", enum_type: :content_status
|
102
103
|
t.index ["author_id"], name: "index_posts_on_author_id", using: :btree
|
103
104
|
end
|
104
105
|
|
@@ -111,7 +112,7 @@ ActiveRecord::Schema.define(version: version) do
|
|
111
112
|
|
112
113
|
create_table "users", force: :cascade do |t|
|
113
114
|
t.string "name", null: false
|
114
|
-
t.enum "role",
|
115
|
+
t.enum "role", enum_type: :roles, default: :visitor
|
115
116
|
t.datetime "created_at", null: false
|
116
117
|
t.datetime "updated_at", null: false
|
117
118
|
end
|
@@ -120,7 +121,7 @@ ActiveRecord::Schema.define(version: version) do
|
|
120
121
|
t.integer "author_id"
|
121
122
|
t.string "title"
|
122
123
|
t.boolean "active"
|
123
|
-
t.enum "kind",
|
124
|
+
t.enum "kind", enum_type: :types
|
124
125
|
t.datetime "created_at", null: false
|
125
126
|
t.datetime "updated_at", null: false
|
126
127
|
end
|
data/spec/spec_helper.rb
CHANGED
data/spec/tests/arel_spec.rb
CHANGED
@@ -51,8 +51,6 @@ RSpec.describe 'Arel' do
|
|
51
51
|
context 'on default value' do
|
52
52
|
let(:connection) { ActiveRecord::Base.connection }
|
53
53
|
|
54
|
-
before(:context) { Torque::PostgreSQL.config.use_extended_defaults = true }
|
55
|
-
after(:context) { Torque::PostgreSQL.config.use_extended_defaults = false }
|
56
54
|
after { Author.reset_column_information }
|
57
55
|
|
58
56
|
it 'does not break the change column default value method' do
|
@@ -68,26 +66,37 @@ RSpec.describe 'Arel' do
|
|
68
66
|
|
69
67
|
it 'works properly when column is an array' do
|
70
68
|
expect { connection.add_column(:authors, :tag_ids, :bigint, array: true, default: []) }.not_to raise_error
|
71
|
-
expect(Author.
|
69
|
+
expect(Author.new.tag_ids).to eq([])
|
72
70
|
end
|
73
71
|
|
74
|
-
it 'works with an array with enum values' do
|
72
|
+
it 'works with an array with enum values for a new enum' do
|
73
|
+
value = ['a', 'b']
|
74
|
+
|
75
|
+
expect do
|
76
|
+
connection.create_enum(:samples, %i[a b c d])
|
77
|
+
connection.add_column(:authors, :samples, :enum, enum_type: :samples, array: true, default: value)
|
78
|
+
end.not_to raise_error
|
79
|
+
|
80
|
+
expect(Author.new.samples).to eq(value)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'works with an array with enum values for an existing enum' do
|
75
84
|
value = ['visitor', 'assistant']
|
76
|
-
expect { connection.add_column(:authors, :roles, :roles, array: true, default: value) }.not_to raise_error
|
77
|
-
expect(Author.
|
85
|
+
expect { connection.add_column(:authors, :roles, :enum, enum_type: :roles, array: true, default: value) }.not_to raise_error
|
86
|
+
expect(Author.new.roles).to eq(value)
|
78
87
|
end
|
79
88
|
|
80
89
|
it 'works with multi dimentional array' do
|
81
90
|
value = [['1', '2'], ['3', '4']]
|
82
91
|
expect { connection.add_column(:authors, :tag_ids, :string, array: true, default: value) }.not_to raise_error
|
83
|
-
expect(Author.
|
92
|
+
expect(Author.new.tag_ids).to eq(value)
|
84
93
|
end
|
85
94
|
|
86
95
|
it 'works with change column default value' do
|
87
96
|
value = ['2', '3']
|
88
97
|
connection.add_column(:authors, :tag_ids, :string, array: true)
|
89
98
|
expect { connection.change_column_default(:authors, :tag_ids, { from: nil, to: value }) }.not_to raise_error
|
90
|
-
expect(Author.
|
99
|
+
expect(Author.new.tag_ids).to eq(value)
|
91
100
|
end
|
92
101
|
end
|
93
102
|
|
@@ -344,7 +344,8 @@ RSpec.describe 'BelongsToMany' do
|
|
344
344
|
subject.tags.concat(records)
|
345
345
|
|
346
346
|
entries = Video.all
|
347
|
-
|
347
|
+
arguments = { records: entries, associations: :tags, available_records: Tag.all.to_a }
|
348
|
+
ActiveRecord::Associations::Preloader.new(**arguments).call
|
348
349
|
entries = entries.load
|
349
350
|
|
350
351
|
expect(entries.size).to be_eql(1)
|
data/spec/tests/enum_set_spec.rb
CHANGED
@@ -29,9 +29,10 @@ RSpec.describe 'Enum' do
|
|
29
29
|
subject { table_definition.new(connection, 'articles') }
|
30
30
|
|
31
31
|
it 'can be defined as an array' do
|
32
|
-
subject.enum(:content_status, array: true)
|
32
|
+
subject.enum(:content_status, array: true, enum_type: :content_status)
|
33
33
|
expect(subject['content_status'].name).to be_eql('content_status')
|
34
|
-
expect(subject['content_status'].type).to be_eql(:
|
34
|
+
expect(subject['content_status'].type).to be_eql(:enum)
|
35
|
+
expect(subject['content_status'].options[:enum_type]).to be_eql(:content_status)
|
35
36
|
|
36
37
|
array = subject['content_status'].respond_to?(:options) \
|
37
38
|
? subject['content_status'].options[:array] \
|
@@ -44,14 +45,14 @@ RSpec.describe 'Enum' do
|
|
44
45
|
context 'on schema' do
|
45
46
|
it 'can be used on tables' do
|
46
47
|
dump_io = StringIO.new
|
47
|
-
checker = /t\.enum +"conflicts", +array: true, +
|
48
|
+
checker = /t\.enum +"conflicts", +array: true, +enum_type: "conflicts"/
|
48
49
|
ActiveRecord::SchemaDumper.dump(connection, dump_io)
|
49
50
|
expect(dump_io.string).to match checker
|
50
51
|
end
|
51
52
|
|
52
53
|
xit 'can have a default value as an array of symbols' do
|
53
54
|
dump_io = StringIO.new
|
54
|
-
checker = /t\.enum +"types", +default: \[:A, :B\], +array: true, +
|
55
|
+
checker = /t\.enum +"types", +default: \[:A, :B\], +array: true, +enum_type: "types"/
|
55
56
|
ActiveRecord::SchemaDumper.dump(connection, dump_io)
|
56
57
|
expect(dump_io.string).to match checker
|
57
58
|
end
|
data/spec/tests/enum_spec.rb
CHANGED
@@ -26,12 +26,6 @@ RSpec.describe 'Enum' do
|
|
26
26
|
end
|
27
27
|
|
28
28
|
context 'on migration' do
|
29
|
-
it 'can be created' do
|
30
|
-
connection.create_enum(:status, %i(foo bar))
|
31
|
-
expect(connection.type_exists?(:status)).to be_truthy
|
32
|
-
expect(connection.enum_values(:status)).to be_eql(['foo', 'bar'])
|
33
|
-
end
|
34
|
-
|
35
29
|
it 'can be deleted' do
|
36
30
|
connection.create_enum(:status, %i(foo bar))
|
37
31
|
expect(connection.type_exists?(:status)).to be_truthy
|
@@ -46,16 +40,6 @@ RSpec.describe 'Enum' do
|
|
46
40
|
expect(connection.type_exists?(:status)).to be_truthy
|
47
41
|
end
|
48
42
|
|
49
|
-
it 'can have prefix' do
|
50
|
-
connection.create_enum(:status, %i(foo bar), prefix: true)
|
51
|
-
expect(connection.enum_values(:status)).to be_eql(['status_foo', 'status_bar'])
|
52
|
-
end
|
53
|
-
|
54
|
-
it 'can have suffix' do
|
55
|
-
connection.create_enum(:status, %i(foo bar), suffix: 'tst')
|
56
|
-
expect(connection.enum_values(:status)).to be_eql(['foo_tst', 'bar_tst'])
|
57
|
-
end
|
58
|
-
|
59
43
|
it 'inserts values at the end' do
|
60
44
|
connection.create_enum(:status, %i(foo bar))
|
61
45
|
connection.add_enum_values(:status, %i(baz qux))
|
@@ -85,74 +69,6 @@ RSpec.describe 'Enum' do
|
|
85
69
|
end
|
86
70
|
end
|
87
71
|
|
88
|
-
context 'on table definition' do
|
89
|
-
subject { table_definition.new(connection, 'articles') }
|
90
|
-
|
91
|
-
it 'has the enum method' do
|
92
|
-
expect(subject).to respond_to(:enum)
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'can be used in a single form' do
|
96
|
-
subject.enum('content_status')
|
97
|
-
expect(subject['content_status'].name).to be_eql('content_status')
|
98
|
-
expect(subject['content_status'].type).to be_eql(:content_status)
|
99
|
-
end
|
100
|
-
|
101
|
-
it 'can be used in a multiple form' do
|
102
|
-
subject.enum('foo', 'bar', 'baz', subtype: :content_status)
|
103
|
-
expect(subject['foo'].type).to be_eql(:content_status)
|
104
|
-
expect(subject['bar'].type).to be_eql(:content_status)
|
105
|
-
expect(subject['baz'].type).to be_eql(:content_status)
|
106
|
-
end
|
107
|
-
|
108
|
-
it 'can have custom type' do
|
109
|
-
subject.enum('foo', subtype: :content_status)
|
110
|
-
expect(subject['foo'].name).to be_eql('foo')
|
111
|
-
expect(subject['foo'].type).to be_eql(:content_status)
|
112
|
-
end
|
113
|
-
|
114
|
-
it 'raises StatementInvalid when type isn\'t defined' do
|
115
|
-
subject.enum('foo')
|
116
|
-
creation = connection.send(:schema_creation).accept subject
|
117
|
-
expect{ connection.execute creation }.to raise_error(ActiveRecord::StatementInvalid)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
context 'on schema' do
|
122
|
-
it 'dumps when has it' do
|
123
|
-
dump_io = StringIO.new
|
124
|
-
ActiveRecord::SchemaDumper.dump(connection, dump_io)
|
125
|
-
expect(dump_io.string).to match /create_enum \"content_status\", \[/
|
126
|
-
end
|
127
|
-
|
128
|
-
it 'sorts the enum entries to better consistency' do
|
129
|
-
dump_io = StringIO.new
|
130
|
-
ActiveRecord::SchemaDumper.dump(connection, dump_io)
|
131
|
-
items = dump_io.string.scan(/create_enum "(\w+)"/).flatten
|
132
|
-
expect(items).to be_eql(items.sort)
|
133
|
-
end
|
134
|
-
|
135
|
-
it 'do not dump when has none' do
|
136
|
-
connection.drop_type(:content_status, force: :cascade)
|
137
|
-
|
138
|
-
dump_io = StringIO.new
|
139
|
-
ActiveRecord::SchemaDumper.dump(connection, dump_io)
|
140
|
-
expect(dump_io.string).not_to match /create_enum \"content_status\", \[/
|
141
|
-
end
|
142
|
-
|
143
|
-
it 'can be used on tables too' do
|
144
|
-
dump_io = StringIO.new
|
145
|
-
ActiveRecord::SchemaDumper.dump(connection, dump_io)
|
146
|
-
expect(dump_io.string).to match /t\.enum +"status", +subtype: :content_status/
|
147
|
-
end
|
148
|
-
|
149
|
-
it 'can have a default value as symbol' do
|
150
|
-
dump_io = StringIO.new
|
151
|
-
ActiveRecord::SchemaDumper.dump(connection, dump_io)
|
152
|
-
expect(dump_io.string).to match /t\.enum +"role", +default: :visitor, +subtype: :roles/
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
72
|
context 'on value' do
|
157
73
|
subject { Enum::ContentStatus }
|
158
74
|
let(:values) { %w(created draft published archived) }
|
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:
|
4
|
+
version: 3.0.0
|
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-
|
11
|
+
date: 2022-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '7.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '7.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: pg
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -189,14 +189,15 @@ files:
|
|
189
189
|
- lib/torque/postgresql/arel/select_manager.rb
|
190
190
|
- lib/torque/postgresql/arel/visitors.rb
|
191
191
|
- lib/torque/postgresql/associations.rb
|
192
|
-
- lib/torque/postgresql/associations/association.rb
|
193
192
|
- lib/torque/postgresql/associations/association_scope.rb
|
194
193
|
- lib/torque/postgresql/associations/belongs_to_many_association.rb
|
195
194
|
- lib/torque/postgresql/associations/builder.rb
|
196
195
|
- lib/torque/postgresql/associations/builder/belongs_to_many.rb
|
197
196
|
- lib/torque/postgresql/associations/builder/has_many.rb
|
197
|
+
- lib/torque/postgresql/associations/foreign_association.rb
|
198
198
|
- lib/torque/postgresql/associations/preloader.rb
|
199
199
|
- lib/torque/postgresql/associations/preloader/association.rb
|
200
|
+
- lib/torque/postgresql/associations/preloader/loader_query.rb
|
200
201
|
- lib/torque/postgresql/attributes.rb
|
201
202
|
- lib/torque/postgresql/attributes/builder.rb
|
202
203
|
- lib/torque/postgresql/attributes/builder/enum.rb
|
@@ -232,7 +233,6 @@ files:
|
|
232
233
|
- lib/torque/postgresql/relation/merger.rb
|
233
234
|
- lib/torque/postgresql/schema_cache.rb
|
234
235
|
- lib/torque/postgresql/version.rb
|
235
|
-
- lib/torque/range.rb
|
236
236
|
- spec/en.yml
|
237
237
|
- spec/factories/authors.rb
|
238
238
|
- spec/factories/comments.rb
|
@@ -279,7 +279,6 @@ files:
|
|
279
279
|
- spec/tests/lazy_spec.rb
|
280
280
|
- spec/tests/period_spec.rb
|
281
281
|
- spec/tests/quoting_spec.rb
|
282
|
-
- spec/tests/range_spec.rb
|
283
282
|
- spec/tests/relation_spec.rb
|
284
283
|
- spec/tests/table_inheritance_spec.rb
|
285
284
|
homepage: https://github.com/crashtech/torque-postgresql
|
@@ -294,7 +293,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
294
293
|
requirements:
|
295
294
|
- - ">="
|
296
295
|
- !ruby/object:Gem::Version
|
297
|
-
version:
|
296
|
+
version: 2.7.2
|
298
297
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
299
298
|
requirements:
|
300
299
|
- - ">="
|
@@ -352,6 +351,5 @@ test_files:
|
|
352
351
|
- spec/tests/lazy_spec.rb
|
353
352
|
- spec/tests/period_spec.rb
|
354
353
|
- spec/tests/quoting_spec.rb
|
355
|
-
- spec/tests/range_spec.rb
|
356
354
|
- spec/tests/relation_spec.rb
|
357
355
|
- spec/tests/table_inheritance_spec.rb
|
data/lib/torque/range.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
module Torque
|
2
|
-
module Range
|
3
|
-
def intersection(other)
|
4
|
-
raise ArgumentError, 'value must be a Range' unless other.kind_of?(Range)
|
5
|
-
|
6
|
-
new_min = self.cover?(other.min) ? other.min : other.cover?(min) ? min : nil
|
7
|
-
new_max = self.cover?(other.max) ? other.max : other.cover?(max) ? max : nil
|
8
|
-
|
9
|
-
new_min && new_max ? new_min..new_max : nil
|
10
|
-
end
|
11
|
-
alias_method :&, :intersection
|
12
|
-
|
13
|
-
def union(other)
|
14
|
-
raise ArgumentError, 'value must be a Range' unless other.kind_of?(Range)
|
15
|
-
|
16
|
-
([min, other.min].min)..([max, other.max].max)
|
17
|
-
end
|
18
|
-
alias_method :|, :union
|
19
|
-
end
|
20
|
-
end
|
data/spec/tests/range_spec.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.xdescribe 'Range' do
|
4
|
-
let(:sample) { (5..15) }
|
5
|
-
|
6
|
-
it 'has intersection' do
|
7
|
-
expect { sample.intersection(10) }.to raise_error(ArgumentError, /Range/)
|
8
|
-
|
9
|
-
result = sample & (10..15)
|
10
|
-
expect(result).to be_a(Range)
|
11
|
-
expect(result.min).to be_eql(10)
|
12
|
-
expect(result.max).to be_eql(15)
|
13
|
-
|
14
|
-
result = sample & (15..20)
|
15
|
-
expect(result).to be_a(Range)
|
16
|
-
expect(result.min).to be_eql(15)
|
17
|
-
expect(result.max).to be_eql(15)
|
18
|
-
|
19
|
-
result = sample & (0..10)
|
20
|
-
expect(result).to be_a(Range)
|
21
|
-
expect(result.min).to be_eql(5)
|
22
|
-
expect(result.max).to be_eql(10)
|
23
|
-
|
24
|
-
result = sample & (-10..0)
|
25
|
-
expect(result).to be_nil
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'has union' do
|
29
|
-
expect { sample.union(10) }.to raise_error(ArgumentError, /Range/)
|
30
|
-
|
31
|
-
result = sample | (0..10)
|
32
|
-
expect(result).to be_a(Range)
|
33
|
-
expect(result.min).to be_eql(0)
|
34
|
-
expect(result.max).to be_eql(15)
|
35
|
-
end
|
36
|
-
end
|