composite_primary_keys 11.3.1 → 12.0.0.rc1
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/History.rdoc +17 -7
- data/README.rdoc +1 -0
- data/lib/composite_primary_keys.rb +1 -6
- data/lib/composite_primary_keys/arel/to_sql.rb +13 -13
- data/lib/composite_primary_keys/associations/association_scope.rb +4 -4
- data/lib/composite_primary_keys/associations/has_many_association.rb +2 -1
- data/lib/composite_primary_keys/associations/has_many_through_association.rb +0 -2
- data/lib/composite_primary_keys/associations/join_dependency.rb +9 -8
- data/lib/composite_primary_keys/associations/preloader/association.rb +28 -36
- data/lib/composite_primary_keys/attribute_methods.rb +2 -2
- data/lib/composite_primary_keys/attribute_methods/read.rb +11 -14
- data/lib/composite_primary_keys/attribute_methods/write.rb +8 -11
- data/lib/composite_primary_keys/base.rb +2 -2
- data/lib/composite_primary_keys/composite_arrays.rb +7 -50
- data/lib/composite_primary_keys/connection_adapters/abstract_adapter.rb +1 -1
- data/lib/composite_primary_keys/connection_adapters/postgresql/database_statements.rb +1 -1
- data/lib/composite_primary_keys/core.rb +10 -14
- data/lib/composite_primary_keys/counter_cache.rb +4 -22
- data/lib/composite_primary_keys/fixtures.rb +5 -10
- data/lib/composite_primary_keys/nested_attributes.rb +6 -6
- data/lib/composite_primary_keys/persistence.rb +8 -8
- data/lib/composite_primary_keys/reflection.rb +3 -3
- data/lib/composite_primary_keys/relation.rb +39 -27
- data/lib/composite_primary_keys/relation/calculations.rb +15 -18
- data/lib/composite_primary_keys/relation/finder_methods.rb +56 -58
- data/lib/composite_primary_keys/relation/query_methods.rb +4 -3
- data/lib/composite_primary_keys/relation/where_clause.rb +2 -2
- data/lib/composite_primary_keys/sanitization.rb +37 -37
- data/lib/composite_primary_keys/validations/uniqueness.rb +2 -2
- data/lib/composite_primary_keys/version.rb +4 -4
- data/tasks/databases/mysql.rake +1 -1
- data/test/abstract_unit.rb +1 -5
- data/test/connections/databases.ci.yml +3 -0
- data/test/db_test.rb +53 -0
- data/test/fixtures/db_definitions/mysql.sql +1 -7
- data/test/fixtures/db_definitions/oracle.drop.sql +1 -3
- data/test/fixtures/db_definitions/oracle.sql +0 -8
- data/test/fixtures/db_definitions/postgresql.sql +0 -6
- data/test/fixtures/db_definitions/sqlite.sql +0 -6
- data/test/fixtures/db_definitions/sqlserver.sql +1 -8
- data/test/test_associations.rb +1 -1
- data/test/test_composite_arrays.rb +0 -14
- data/test/test_create.rb +12 -26
- data/test/test_find.rb +0 -8
- data/test/test_ids.rb +0 -3
- data/test/test_nested_attributes.rb +10 -10
- data/test/test_update.rb +1 -1
- metadata +9 -11
- data/lib/composite_primary_keys/connection_adapters/abstract_mysql_adapter.rb +0 -20
- data/lib/composite_primary_keys/connection_adapters/sqlite3_adapter.rb +0 -23
- data/test/fixtures/cpk_with_default_value.rb +0 -3
- data/test/fixtures/cpk_with_default_values.yml +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 540c65209855565625538300ca62ea930ad91494d7a307dbd4db0419a17e576f
|
4
|
+
data.tar.gz: 9bd63c5ffb21a79abb6f4159ddc0245144406e33f1969801f1d9d3176fdf1e2f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 627e469ec7fe07987605b21f156dc042611af0a31282bc711b078479617c5eebeae770f27ec5de3158f686cb7dd4b175b1729dc0116f46e87894d19dc5482292
|
7
|
+
data.tar.gz: 5038fb2ff8282164c9daf3f5b8123d441c3ea50a126222619f12cdaed9118112a7c2f469b90ffb20b482d5e0a1467e3aabf7b5e14e39208a5972ce3b73717633
|
data/History.rdoc
CHANGED
@@ -1,10 +1,6 @@
|
|
1
|
-
==
|
2
|
-
*
|
3
|
-
*
|
4
|
-
* Fixed incorrect SQL condition for joining by CPK (Sergey Semyonov)
|
5
|
-
* Update travis.yml file (Sergey Semyonov)
|
6
|
-
* Add tests for composite keys with default values (Daniel Wiklund)
|
7
|
-
* Fix create record where one or more of the primary keys has a default value (Daniel Wiklund)
|
1
|
+
== 12.0.0 (?)
|
2
|
+
* Update to ActiveRecord 6.0 (Hiroshi Kajisha, Alexandru Anca, Charlie Savage)
|
3
|
+
* Update travis setup (Olle Jonsson)
|
8
4
|
|
9
5
|
== 11.2.0 (2019-03-16)
|
10
6
|
* When creating new records, honor composite key autoincrementing fields if possible (Antti Pitkänen)
|
@@ -146,6 +142,20 @@
|
|
146
142
|
== 9.0.0.beta1 (2016-04-16)
|
147
143
|
* Rails 5 beta support (Sammy Larbi)
|
148
144
|
|
145
|
+
== 8.1.7 (2019-05-04)
|
146
|
+
|
147
|
+
Fix key not being an array in subquery on has_many :through (Eric Proulx)
|
148
|
+
Convert batches to arrays before continuing loop (Jeremy Mickelson)
|
149
|
+
|
150
|
+
== 8.1.6 (2017-05-20)
|
151
|
+
|
152
|
+
Query cache with bind params (ttw)
|
153
|
+
Fix TestIds#test_set_ids_string. Sqlite's serial and integer are a bit different (Boris Peterbarg)
|
154
|
+
Associations with inverse fix (Boris Peterbarg)
|
155
|
+
Fix save_has_one_association and add a test for it (Boris Peterbarg)
|
156
|
+
Fix save_belongs_to_association override (Boris Peterbarg)
|
157
|
+
Extend approach from #344 to fix autosave for has_one associations as well (Cameron Finucane)
|
158
|
+
|
149
159
|
== 8.1.5 (2017-01-01)
|
150
160
|
|
151
161
|
* Don't nest PK twice when looking up id, fixes #319 (Kerey Roper)
|
data/README.rdoc
CHANGED
@@ -20,6 +20,7 @@ Every major version of ActiveRecord has included numerous internal changes. As
|
|
20
20
|
CPK has to be rewritten for each version of ActiveRecord. To help keep
|
21
21
|
things straight, here is the mapping:
|
22
22
|
|
23
|
+
Version 12.x is designed to work with ActiveRecord 6.0.x
|
23
24
|
Version 11.x is designed to work with ActiveRecord 5.2.x
|
24
25
|
Version 10.x is designed to work with ActiveRecord 5.1.x
|
25
26
|
Version 9.x is designed to work with ActiveRecord 5.0.x
|
@@ -26,7 +26,7 @@ $:.unshift(File.dirname(__FILE__)) unless
|
|
26
26
|
|
27
27
|
unless defined?(ActiveRecord)
|
28
28
|
require 'rubygems'
|
29
|
-
gem 'activerecord', '
|
29
|
+
gem 'activerecord', '6.0.0.rc1'
|
30
30
|
require 'active_record'
|
31
31
|
end
|
32
32
|
|
@@ -59,13 +59,9 @@ require 'active_record/nested_attributes'
|
|
59
59
|
|
60
60
|
require 'active_record/connection_adapters/abstract/database_statements'
|
61
61
|
require 'active_record/connection_adapters/abstract_adapter'
|
62
|
-
require 'active_record/connection_adapters/abstract_mysql_adapter'
|
63
62
|
require 'active_record/connection_adapters/postgresql/database_statements'
|
64
63
|
|
65
64
|
require 'active_record/relation/where_clause'
|
66
|
-
require 'active_record/relation/predicate_builder/association_query_value'
|
67
|
-
|
68
|
-
require 'active_record/validations/uniqueness'
|
69
65
|
|
70
66
|
# CPK files
|
71
67
|
require 'composite_primary_keys/persistence'
|
@@ -99,7 +95,6 @@ require 'composite_primary_keys/nested_attributes'
|
|
99
95
|
|
100
96
|
require 'composite_primary_keys/connection_adapters/abstract/database_statements'
|
101
97
|
require 'composite_primary_keys/connection_adapters/abstract_adapter'
|
102
|
-
require 'composite_primary_keys/connection_adapters/abstract_mysql_adapter'
|
103
98
|
require 'composite_primary_keys/connection_adapters/postgresql/database_statements'
|
104
99
|
require 'composite_primary_keys/connection_adapters/sqlserver/database_statements'
|
105
100
|
|
@@ -1,19 +1,19 @@
|
|
1
1
|
module Arel
|
2
2
|
module Visitors
|
3
3
|
class ToSql
|
4
|
-
def visit_Arel_Nodes_In o, collector
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
4
|
+
# def visit_Arel_Nodes_In o, collector
|
5
|
+
# if Array === o.right && o.right.empty?
|
6
|
+
# collector << '1=0'
|
7
|
+
# else
|
8
|
+
# # CPK
|
9
|
+
# collector << "("
|
10
|
+
# collector = visit o.left, collector
|
11
|
+
# # CPK
|
12
|
+
# collector << ")"
|
13
|
+
# collector << " IN ("
|
14
|
+
# visit(o.right, collector) << ")"
|
15
|
+
# end
|
16
|
+
# end
|
17
17
|
|
18
18
|
def visit_CompositePrimaryKeys_CompositeKeys o, collector
|
19
19
|
values = o.map do |key|
|
@@ -11,12 +11,12 @@ module ActiveRecord
|
|
11
11
|
binds += Array(values)
|
12
12
|
|
13
13
|
if last_reflection.type
|
14
|
-
binds << owner.class.
|
14
|
+
binds << owner.class.polymorphic_name
|
15
15
|
end
|
16
16
|
|
17
17
|
chain.each_cons(2).each do |reflection, next_reflection|
|
18
18
|
if reflection.type
|
19
|
-
binds << next_reflection.klass.
|
19
|
+
binds << next_reflection.klass.polymorphic_name
|
20
20
|
end
|
21
21
|
end
|
22
22
|
binds
|
@@ -38,7 +38,7 @@ module ActiveRecord
|
|
38
38
|
end
|
39
39
|
|
40
40
|
if reflection.type
|
41
|
-
polymorphic_type = transform_value(owner.class.
|
41
|
+
polymorphic_type = transform_value(owner.class.polymorphic_name)
|
42
42
|
scope = apply_scope(scope, table, reflection.type, polymorphic_type)
|
43
43
|
end
|
44
44
|
|
@@ -58,7 +58,7 @@ module ActiveRecord
|
|
58
58
|
constraint = cpk_join_predicate(table, key, foreign_table, foreign_key)
|
59
59
|
|
60
60
|
if reflection.type
|
61
|
-
value = transform_value(next_reflection.klass.
|
61
|
+
value = transform_value(next_reflection.klass.polymorphic_name)
|
62
62
|
scope = apply_scope(scope, table, reflection.type, value)
|
63
63
|
end
|
64
64
|
|
@@ -21,11 +21,12 @@ module ActiveRecord
|
|
21
21
|
scope.delete_all
|
22
22
|
else
|
23
23
|
# CPK
|
24
|
-
# scope.update_all(
|
24
|
+
# scope.update_all(nullified_owner_attributes)
|
25
25
|
conds = Array(reflection.foreign_key).inject(Hash.new) do |mem, key|
|
26
26
|
mem[key] = nil
|
27
27
|
mem
|
28
28
|
end
|
29
|
+
conds[reflection.type] = nil if reflection.type.present?
|
29
30
|
scope.update_all(conds)
|
30
31
|
end
|
31
32
|
end
|
@@ -47,14 +47,14 @@ module ActiveRecord
|
|
47
47
|
end
|
48
48
|
|
49
49
|
parent = parents[parent_key] ||= join_root.instantiate(row_hash, column_aliases, &block)
|
50
|
-
construct(parent, join_root, row_hash,
|
50
|
+
construct(parent, join_root, row_hash, seen, model_cache)
|
51
51
|
}
|
52
52
|
end
|
53
53
|
|
54
54
|
parents.values
|
55
55
|
end
|
56
56
|
|
57
|
-
def construct(ar_parent, parent, row,
|
57
|
+
def construct(ar_parent, parent, row, seen, model_cache)
|
58
58
|
return if ar_parent.nil?
|
59
59
|
|
60
60
|
parent.children.each do |node|
|
@@ -63,7 +63,7 @@ module ActiveRecord
|
|
63
63
|
other.loaded!
|
64
64
|
elsif ar_parent.association_cached?(node.reflection.name)
|
65
65
|
model = ar_parent.association(node.reflection.name).target
|
66
|
-
construct(model, node, row,
|
66
|
+
construct(model, node, row, seen, model_cache)
|
67
67
|
next
|
68
68
|
end
|
69
69
|
|
@@ -86,14 +86,15 @@ module ActiveRecord
|
|
86
86
|
next
|
87
87
|
end
|
88
88
|
|
89
|
-
model = seen[ar_parent.object_id][node
|
89
|
+
model = seen[ar_parent.object_id][node][id]
|
90
90
|
|
91
91
|
if model
|
92
|
-
construct(model, node, row,
|
92
|
+
construct(model, node, row, seen, model_cache)
|
93
93
|
else
|
94
|
-
model = construct_model(ar_parent, node, row, model_cache, id
|
95
|
-
|
96
|
-
|
94
|
+
model = construct_model(ar_parent, node, row, model_cache, id)
|
95
|
+
|
96
|
+
seen[ar_parent.object_id][node][id] = model
|
97
|
+
construct(model, node, row, seen, model_cache)
|
97
98
|
end
|
98
99
|
end
|
99
100
|
end
|
@@ -2,42 +2,39 @@ module ActiveRecord
|
|
2
2
|
module Associations
|
3
3
|
class Preloader
|
4
4
|
class Association
|
5
|
-
def records_for(ids
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
5
|
+
def records_for(ids)
|
6
|
+
records = if association_key_name.is_a?(Array)
|
7
|
+
predicate = cpk_in_predicate(klass.arel_table, association_key_name, ids)
|
8
|
+
scope.where(predicate)
|
9
|
+
else
|
10
|
+
scope.where(association_key_name => ids)
|
11
|
+
end
|
12
|
+
records.load do |record|
|
13
|
+
# Processing only the first owner
|
14
|
+
# because the record is modified but not an owner
|
15
|
+
owner = owners_by_key[convert_key(record[association_key_name])].first
|
16
|
+
association = owner.association(reflection.name)
|
17
|
+
association.set_inverse_instance(record)
|
14
18
|
end
|
15
19
|
end
|
16
20
|
|
17
21
|
def owners_by_key
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
convert_key(owner[key_name])
|
25
|
-
end
|
26
|
-
else
|
27
|
-
convert_key(owner[owner_key_name])
|
22
|
+
@owners_by_key ||= owners.each_with_object({}) do |owner, result|
|
23
|
+
# CPK
|
24
|
+
# key = convert_key(owner[owner_key_name])
|
25
|
+
key = if owner_key_name.is_a?(Array)
|
26
|
+
Array(owner_key_name).map do |key_name|
|
27
|
+
convert_key(owner[key_name])
|
28
28
|
end
|
29
|
-
|
30
|
-
|
31
|
-
|
29
|
+
else
|
30
|
+
convert_key(owner[owner_key_name])
|
31
|
+
end
|
32
|
+
(result[key] ||= []) << owner if key
|
32
33
|
end
|
33
|
-
@owners_by_key
|
34
34
|
end
|
35
35
|
|
36
|
-
def
|
37
|
-
|
38
|
-
# CPK
|
39
|
-
#owner = owners_by_key[convert_key(record[association_key_name])]
|
40
|
-
|
36
|
+
def records_by_owner
|
37
|
+
@records_by_owner ||= preloaded_records.each_with_object({}) do |record, result|
|
41
38
|
key = if association_key_name.is_a?(Array)
|
42
39
|
Array(record[association_key_name]).map do |key|
|
43
40
|
convert_key(key)
|
@@ -45,14 +42,9 @@ module ActiveRecord
|
|
45
42
|
else
|
46
43
|
convert_key(record[association_key_name])
|
47
44
|
end
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
association.set_inverse_instance(record)
|
52
|
-
end
|
53
|
-
|
54
|
-
owners.each do |owner|
|
55
|
-
associate_records_to_owner(owner, records[convert_key(owner[owner_key_name])] || [])
|
45
|
+
owners_by_key[key].each do |owner|
|
46
|
+
(result[owner] ||= []) << record
|
47
|
+
end
|
56
48
|
end
|
57
49
|
end
|
58
50
|
end
|
@@ -2,8 +2,8 @@ module ActiveRecord
|
|
2
2
|
module AttributeMethods
|
3
3
|
def has_attribute?(attr_name)
|
4
4
|
# CPK
|
5
|
-
#
|
6
|
-
Array(attr_name).all?{|single_attr|
|
5
|
+
# attributes.key?(attr_name)
|
6
|
+
Array(attr_name).all? {|single_attr| attributes.key?(single_attr) }
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
@@ -2,30 +2,27 @@ module ActiveRecord
|
|
2
2
|
module AttributeMethods
|
3
3
|
module Read
|
4
4
|
def read_attribute(attr_name, &block)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
# attr_name.to_s
|
12
|
-
attr_name
|
13
|
-
end
|
5
|
+
# CPK
|
6
|
+
# name = attr_name.to_s
|
7
|
+
name = attr_name
|
8
|
+
if self.class.attribute_alias?(name)
|
9
|
+
name = self.class.attribute_alias(name)
|
10
|
+
end
|
14
11
|
|
15
12
|
primary_key = self.class.primary_key
|
16
13
|
# CPK
|
17
|
-
# name = primary_key if name == "id"
|
18
|
-
name = primary_key if name == "id"
|
14
|
+
# name = primary_key if name == "id" && primary_key
|
15
|
+
name = primary_key if name == "id" && primary_key && !composite?
|
19
16
|
sync_with_transaction_state if name == primary_key
|
20
17
|
_read_attribute(name, &block)
|
21
18
|
end
|
22
19
|
|
23
|
-
def _read_attribute(attr_name)
|
20
|
+
def _read_attribute(attr_name, &block) # :nodoc
|
24
21
|
# CPK
|
25
22
|
if attr_name.kind_of?(Array)
|
26
|
-
attr_name.map {|name| @attributes.fetch_value(name.to_s)}
|
23
|
+
attr_name.map {|name| @attributes.fetch_value(name.to_s, &block)}
|
27
24
|
else
|
28
|
-
@attributes.fetch_value(attr_name.to_s)
|
25
|
+
@attributes.fetch_value(attr_name.to_s, &block)
|
29
26
|
end
|
30
27
|
end
|
31
28
|
end
|
@@ -2,20 +2,17 @@ module ActiveRecord
|
|
2
2
|
module AttributeMethods
|
3
3
|
module Write
|
4
4
|
def write_attribute(attr_name, value)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
# attr_name.to_s
|
12
|
-
attr_name
|
13
|
-
end
|
5
|
+
# CPK
|
6
|
+
#name = attr_name.to_s
|
7
|
+
name = attr_name
|
8
|
+
if self.class.attribute_alias?(name)
|
9
|
+
name = self.class.attribute_alias(name)
|
10
|
+
end
|
14
11
|
|
15
12
|
primary_key = self.class.primary_key
|
16
13
|
# CPK
|
17
|
-
# name = primary_key if name == "id"
|
18
|
-
name = primary_key if name == "id"
|
14
|
+
# name = primary_key if name == "id" && primary_key
|
15
|
+
name = primary_key if name == "id" && primary_key && !composite?
|
19
16
|
sync_with_transaction_state if name == primary_key
|
20
17
|
_write_attribute(name, value)
|
21
18
|
end
|
@@ -52,7 +52,7 @@ module ActiveRecord
|
|
52
52
|
end
|
53
53
|
|
54
54
|
# Don't like this method name, but its modeled after how AR does it
|
55
|
-
|
55
|
+
def reset_primary_keys #:nodoc:
|
56
56
|
if self == base_class
|
57
57
|
# CPK
|
58
58
|
self.primary_keys = get_primary_key(base_class.name)
|
@@ -123,7 +123,7 @@ module ActiveRecord
|
|
123
123
|
end
|
124
124
|
|
125
125
|
def to_param
|
126
|
-
persisted? ? to_key.
|
126
|
+
persisted? ? to_key.join(CompositePrimaryKeys::ID_SEP) : nil
|
127
127
|
end
|
128
128
|
end
|
129
129
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module CompositePrimaryKeys
|
2
2
|
ID_SEP = ','
|
3
3
|
ID_SET_SEP = ';'
|
4
|
-
ESCAPE_CHAR = '^'
|
5
4
|
|
6
5
|
module ArrayExtension
|
7
6
|
def to_composite_keys
|
@@ -9,27 +8,12 @@ module CompositePrimaryKeys
|
|
9
8
|
end
|
10
9
|
end
|
11
10
|
|
12
|
-
|
13
|
-
# representation (just by arrays).
|
14
|
-
#
|
15
|
-
# `ids` is Array that may contain:
|
16
|
-
# 1. A CPK represented by an array or a string.
|
17
|
-
# 2. An array of CPKs represented by arrays or strings.
|
18
|
-
#
|
19
|
-
# There is an issue. Let `ids` contain an array with several strings. We can't distinguish case 1
|
20
|
-
# from case 2 there in general. E.g. the item can be an array containing appropriate number of strings,
|
21
|
-
# and each string can contain appropriate number of commas. We consider case 2 to win there.
|
22
|
-
def self.normalize(ids, cpk_size)
|
11
|
+
def self.normalize(ids)
|
23
12
|
ids.map do |id|
|
24
|
-
if
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
# An array of CPKs - case 2
|
29
|
-
normalize(id, cpk_size)
|
30
|
-
elsif id.is_a?(String)
|
31
|
-
# CPK as a string - case 1
|
32
|
-
CompositeKeys.parse(id)
|
13
|
+
if id.is_a?(Array)
|
14
|
+
normalize(id)
|
15
|
+
elsif id.is_a?(String) && id.index(ID_SEP)
|
16
|
+
id.split(ID_SEP)
|
33
17
|
else
|
34
18
|
id
|
35
19
|
end
|
@@ -43,7 +27,7 @@ module CompositePrimaryKeys
|
|
43
27
|
when Array
|
44
28
|
value.to_composite_keys
|
45
29
|
when String
|
46
|
-
value.split(ID_SEP)
|
30
|
+
self.new(value.split(ID_SEP))
|
47
31
|
else
|
48
32
|
raise(ArgumentError, "Unsupported type: #{value}")
|
49
33
|
end
|
@@ -59,36 +43,9 @@ module CompositePrimaryKeys
|
|
59
43
|
|
60
44
|
def to_s
|
61
45
|
# Doing this makes it easier to parse Base#[](attr_name)
|
62
|
-
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
module Utils
|
67
|
-
class << self
|
68
|
-
def escape_string_key(key)
|
69
|
-
key.gsub(Regexp.union(ESCAPE_CHAR, ID_SEP)) do |unsafe|
|
70
|
-
"#{ESCAPE_CHAR}#{unsafe.ord.to_s(16).upcase}"
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def unescape_string_key(key)
|
75
|
-
key.gsub(/#{Regexp.escape(ESCAPE_CHAR)}[0-9a-fA-F]{2}/) do |escaped|
|
76
|
-
char = escaped.slice(1, 2).hex.chr
|
77
|
-
(char == ESCAPE_CHAR || char == ID_SEP) ? char : escaped
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def cpk_as_array?(value, pk_size)
|
82
|
-
# We don't permit Array to be an element of CPK.
|
83
|
-
value.is_a?(Array) && value.size == pk_size && value.none? { |item| item.is_a?(Array) }
|
84
|
-
end
|
85
|
-
|
86
|
-
def cpk_as_string?(value, pk_size)
|
87
|
-
value.is_a?(String) && value.count(ID_SEP) == pk_size - 1
|
88
|
-
end
|
46
|
+
join(ID_SEP)
|
89
47
|
end
|
90
48
|
end
|
91
|
-
private_constant :Utils
|
92
49
|
end
|
93
50
|
|
94
51
|
Array.send(:include, CompositePrimaryKeys::ArrayExtension)
|