composite_primary_keys 12.0.9 → 12.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/History.rdoc +880 -877
  3. data/README.rdoc +180 -180
  4. data/lib/composite_primary_keys.rb +117 -117
  5. data/lib/composite_primary_keys/active_model/attribute_assignment.rb +19 -19
  6. data/lib/composite_primary_keys/associations/association_scope.rb +68 -68
  7. data/lib/composite_primary_keys/associations/join_dependency.rb +103 -103
  8. data/lib/composite_primary_keys/attribute_methods.rb +9 -9
  9. data/lib/composite_primary_keys/attribute_methods/read.rb +30 -30
  10. data/lib/composite_primary_keys/attribute_methods/write.rb +35 -35
  11. data/lib/composite_primary_keys/base.rb +141 -141
  12. data/lib/composite_primary_keys/connection_adapters/abstract/database_statements.rb +37 -37
  13. data/lib/composite_primary_keys/connection_adapters/sqlserver/database_statements.rb +44 -44
  14. data/lib/composite_primary_keys/core.rb +48 -48
  15. data/lib/composite_primary_keys/persistence.rb +82 -81
  16. data/lib/composite_primary_keys/reflection.rb +29 -29
  17. data/lib/composite_primary_keys/relation.rb +193 -193
  18. data/lib/composite_primary_keys/relation/calculations.rb +81 -81
  19. data/lib/composite_primary_keys/relation/finder_methods.rb +235 -235
  20. data/lib/composite_primary_keys/relation/predicate_builder/association_query_value.rb +20 -20
  21. data/lib/composite_primary_keys/relation/query_methods.rb +42 -42
  22. data/lib/composite_primary_keys/relation/where_clause.rb +23 -23
  23. data/lib/composite_primary_keys/version.rb +8 -8
  24. data/test/abstract_unit.rb +114 -114
  25. data/test/connections/databases.ci.yml +22 -22
  26. data/test/fixtures/db_definitions/db2-create-tables.sql +112 -112
  27. data/test/fixtures/db_definitions/db2-drop-tables.sql +16 -16
  28. data/test/fixtures/db_definitions/mysql.sql +180 -180
  29. data/test/fixtures/db_definitions/oracle.drop.sql +41 -41
  30. data/test/fixtures/db_definitions/oracle.sql +199 -199
  31. data/test/fixtures/db_definitions/postgresql.sql +182 -182
  32. data/test/fixtures/db_definitions/sqlite.sql +169 -169
  33. data/test/fixtures/db_definitions/sqlserver.sql +176 -176
  34. data/test/fixtures/department.rb +16 -16
  35. data/test/fixtures/departments.yml +15 -15
  36. data/test/fixtures/employees.yml +27 -27
  37. data/test/fixtures/restaurants_suburbs.yml +10 -10
  38. data/test/fixtures/streets.yml +16 -16
  39. data/test/fixtures/suburbs.yml +14 -14
  40. data/test/fixtures/user.rb +11 -11
  41. data/test/test_associations.rb +358 -358
  42. data/test/test_attributes.rb +60 -60
  43. data/test/test_calculations.rb +42 -42
  44. data/test/test_create.rb +218 -206
  45. data/test/test_delete.rb +182 -179
  46. data/test/test_exists.rb +39 -39
  47. data/test/test_find.rb +164 -164
  48. data/test/test_ids.rb +112 -112
  49. data/test/test_nested_attributes.rb +67 -67
  50. data/test/test_update.rb +96 -96
  51. metadata +9 -9
@@ -1,19 +1,19 @@
1
- module ActiveModel
2
- module AttributeAssignment
3
- def _assign_attribute(k, v)
4
- # CPK. This is super ugly, but if a table has a composite key where one of the fields is named :id we need
5
- # to handle it as a single value. Otherwise, we would call the id=(value) method which is expecting
6
- # and array of values.
7
- if k == 'id' && self.kind_of?(ActiveRecord::Base) && self.composite? && !self.column_for_attribute(k).null
8
- self._write_attribute(k, v)
9
- else
10
- setter = :"#{k}="
11
- if respond_to?(setter)
12
- public_send(setter, v)
13
- else
14
- raise UnknownAttributeError.new(self, k)
15
- end
16
- end
17
- end
18
- end
19
- end
1
+ module ActiveModel
2
+ module AttributeAssignment
3
+ def _assign_attribute(k, v)
4
+ # CPK. This is super ugly, but if a table has a composite key where one of the fields is named :id we need
5
+ # to handle it as a single value. Otherwise, we would call the id=(value) method which is expecting
6
+ # and array of values.
7
+ if k == 'id' && !v.kind_of?(Array) && self.kind_of?(ActiveRecord::Base) && self.composite? && !self.column_for_attribute(k).null
8
+ self._write_attribute(k, v)
9
+ else
10
+ setter = :"#{k}="
11
+ if respond_to?(setter)
12
+ public_send(setter, v)
13
+ else
14
+ raise UnknownAttributeError.new(self, k)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,69 +1,69 @@
1
- module ActiveRecord
2
- module Associations
3
- class AssociationScope
4
- def self.get_bind_values(owner, chain)
5
- binds = []
6
- last_reflection = chain.last
7
-
8
- # CPK
9
- # binds << last_reflection.join_id_for(owner)
10
- values = last_reflection.join_id_for(owner)
11
- binds += Array(values)
12
-
13
- if last_reflection.type
14
- binds << owner.class.polymorphic_name
15
- end
16
-
17
- chain.each_cons(2).each do |reflection, next_reflection|
18
- if reflection.type
19
- binds << next_reflection.klass.polymorphic_name
20
- end
21
- end
22
- binds
23
- end
24
-
25
- def last_chain_scope(scope, reflection, owner)
26
- join_keys = reflection.join_keys
27
- key = join_keys.key
28
- foreign_key = join_keys.foreign_key
29
-
30
- table = reflection.aliased_table
31
-
32
- # CPK
33
- # value = transform_value(owner[foreign_key])
34
- # scope = apply_scope(scope, table, key, value)
35
- Array(key).zip(Array(foreign_key)).each do |a_join_key, a_foreign_key|
36
- value = transform_value(owner[a_foreign_key])
37
- scope = apply_scope(scope, table, a_join_key, value)
38
- end
39
-
40
- if reflection.type
41
- polymorphic_type = transform_value(owner.class.polymorphic_name)
42
- scope = apply_scope(scope, table, reflection.type, polymorphic_type)
43
- end
44
-
45
- scope
46
- end
47
-
48
- def next_chain_scope(scope, reflection, next_reflection)
49
- join_keys = reflection.join_keys
50
- key = join_keys.key
51
- foreign_key = join_keys.foreign_key
52
-
53
- table = reflection.aliased_table
54
- foreign_table = next_reflection.aliased_table
55
-
56
- # CPK
57
- # constraint = table[key].eq(foreign_table[foreign_key])
58
- constraint = cpk_join_predicate(table, key, foreign_table, foreign_key)
59
-
60
- if reflection.type
61
- value = transform_value(next_reflection.klass.polymorphic_name)
62
- scope = apply_scope(scope, table, reflection.type, value)
63
- end
64
-
65
- scope.joins!(join(foreign_table, constraint))
66
- end
67
- end
68
- end
1
+ module ActiveRecord
2
+ module Associations
3
+ class AssociationScope
4
+ def self.get_bind_values(owner, chain)
5
+ binds = []
6
+ last_reflection = chain.last
7
+
8
+ # CPK
9
+ # binds << last_reflection.join_id_for(owner)
10
+ values = last_reflection.join_id_for(owner)
11
+ binds += Array(values)
12
+
13
+ if last_reflection.type
14
+ binds << owner.class.polymorphic_name
15
+ end
16
+
17
+ chain.each_cons(2).each do |reflection, next_reflection|
18
+ if reflection.type
19
+ binds << next_reflection.klass.polymorphic_name
20
+ end
21
+ end
22
+ binds
23
+ end
24
+
25
+ def last_chain_scope(scope, reflection, owner)
26
+ join_keys = reflection.join_keys
27
+ key = join_keys.key
28
+ foreign_key = join_keys.foreign_key
29
+
30
+ table = reflection.aliased_table
31
+
32
+ # CPK
33
+ # value = transform_value(owner[foreign_key])
34
+ # scope = apply_scope(scope, table, key, value)
35
+ Array(key).zip(Array(foreign_key)).each do |a_join_key, a_foreign_key|
36
+ value = transform_value(owner[a_foreign_key])
37
+ scope = apply_scope(scope, table, a_join_key, value)
38
+ end
39
+
40
+ if reflection.type
41
+ polymorphic_type = transform_value(owner.class.polymorphic_name)
42
+ scope = apply_scope(scope, table, reflection.type, polymorphic_type)
43
+ end
44
+
45
+ scope
46
+ end
47
+
48
+ def next_chain_scope(scope, reflection, next_reflection)
49
+ join_keys = reflection.join_keys
50
+ key = join_keys.key
51
+ foreign_key = join_keys.foreign_key
52
+
53
+ table = reflection.aliased_table
54
+ foreign_table = next_reflection.aliased_table
55
+
56
+ # CPK
57
+ # constraint = table[key].eq(foreign_table[foreign_key])
58
+ constraint = cpk_join_predicate(table, key, foreign_table, foreign_key)
59
+
60
+ if reflection.type
61
+ value = transform_value(next_reflection.klass.polymorphic_name)
62
+ scope = apply_scope(scope, table, reflection.type, value)
63
+ end
64
+
65
+ scope.joins!(join(foreign_table, constraint))
66
+ end
67
+ end
68
+ end
69
69
  end
@@ -1,103 +1,103 @@
1
- module ActiveRecord
2
- module Associations
3
- class JoinDependency
4
- class Aliases # :nodoc:
5
- def column_alias(node, column)
6
- # CPK
7
- #@alias_cache[node][column]
8
- if column.kind_of?(Array)
9
- column.map do |a_column|
10
- @alias_cache[node][a_column]
11
- end
12
- else
13
- @alias_cache[node][column]
14
- end
15
- end
16
- end
17
-
18
- def instantiate(result_set, &block)
19
- primary_key = aliases.column_alias(join_root, join_root.primary_key)
20
-
21
- seen = Hash.new { |i, object_id|
22
- i[object_id] = Hash.new { |j, child_class|
23
- j[child_class] = {}
24
- }
25
- }
26
-
27
- model_cache = Hash.new { |h, klass| h[klass] = {} }
28
- parents = model_cache[join_root]
29
- column_aliases = aliases.column_aliases join_root
30
-
31
- message_bus = ActiveSupport::Notifications.instrumenter
32
-
33
- payload = {
34
- record_count: result_set.length,
35
- class_name: join_root.base_klass.name
36
- }
37
-
38
- message_bus.instrument("instantiation.active_record", payload) do
39
- result_set.each { |row_hash|
40
- # CPK
41
- # parent_key = primary_key ? row_hash[primary_key] : row_hash
42
- # CPK
43
- parent_key = if primary_key.kind_of?(Array)
44
- primary_key.map {|key| row_hash[key]}
45
- else
46
- primary_key ? row_hash[primary_key] : row_hash
47
- end
48
-
49
- parent = parents[parent_key] ||= join_root.instantiate(row_hash, column_aliases, &block)
50
- construct(parent, join_root, row_hash, seen, model_cache)
51
- }
52
- end
53
-
54
- parents.values
55
- end
56
-
57
- def construct(ar_parent, parent, row, seen, model_cache)
58
- return if ar_parent.nil?
59
-
60
- parent.children.each do |node|
61
- if node.reflection.collection?
62
- other = ar_parent.association(node.reflection.name)
63
- other.loaded!
64
- elsif ar_parent.association_cached?(node.reflection.name)
65
- model = ar_parent.association(node.reflection.name).target
66
- construct(model, node, row, seen, model_cache)
67
- next
68
- end
69
-
70
- key = aliases.column_alias(node, node.primary_key)
71
-
72
- # CPK
73
- if key.is_a?(Array)
74
- id = Array(key).map do |column_alias|
75
- row[column_alias]
76
- end
77
- # At least the first value in the key has to be set. Should we require all values to be set?
78
- id = nil if id.first.nil?
79
- else # original
80
- id = row[key]
81
- end
82
-
83
- if id.nil? # duplicating this so it is clear what remained unchanged from the original
84
- nil_association = ar_parent.association(node.reflection.name)
85
- nil_association.loaded!
86
- next
87
- end
88
-
89
- model = seen[ar_parent.object_id][node][id]
90
-
91
- if model
92
- construct(model, node, row, seen, model_cache)
93
- else
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)
98
- end
99
- end
100
- end
101
- end
102
- end
103
- end
1
+ module ActiveRecord
2
+ module Associations
3
+ class JoinDependency
4
+ class Aliases # :nodoc:
5
+ def column_alias(node, column)
6
+ # CPK
7
+ #@alias_cache[node][column]
8
+ if column.kind_of?(Array)
9
+ column.map do |a_column|
10
+ @alias_cache[node][a_column]
11
+ end
12
+ else
13
+ @alias_cache[node][column]
14
+ end
15
+ end
16
+ end
17
+
18
+ def instantiate(result_set, &block)
19
+ primary_key = aliases.column_alias(join_root, join_root.primary_key)
20
+
21
+ seen = Hash.new { |i, object_id|
22
+ i[object_id] = Hash.new { |j, child_class|
23
+ j[child_class] = {}
24
+ }
25
+ }
26
+
27
+ model_cache = Hash.new { |h, klass| h[klass] = {} }
28
+ parents = model_cache[join_root]
29
+ column_aliases = aliases.column_aliases join_root
30
+
31
+ message_bus = ActiveSupport::Notifications.instrumenter
32
+
33
+ payload = {
34
+ record_count: result_set.length,
35
+ class_name: join_root.base_klass.name
36
+ }
37
+
38
+ message_bus.instrument("instantiation.active_record", payload) do
39
+ result_set.each { |row_hash|
40
+ # CPK
41
+ # parent_key = primary_key ? row_hash[primary_key] : row_hash
42
+ # CPK
43
+ parent_key = if primary_key.kind_of?(Array)
44
+ primary_key.map {|key| row_hash[key]}
45
+ else
46
+ primary_key ? row_hash[primary_key] : row_hash
47
+ end
48
+
49
+ parent = parents[parent_key] ||= join_root.instantiate(row_hash, column_aliases, &block)
50
+ construct(parent, join_root, row_hash, seen, model_cache)
51
+ }
52
+ end
53
+
54
+ parents.values
55
+ end
56
+
57
+ def construct(ar_parent, parent, row, seen, model_cache)
58
+ return if ar_parent.nil?
59
+
60
+ parent.children.each do |node|
61
+ if node.reflection.collection?
62
+ other = ar_parent.association(node.reflection.name)
63
+ other.loaded!
64
+ elsif ar_parent.association_cached?(node.reflection.name)
65
+ model = ar_parent.association(node.reflection.name).target
66
+ construct(model, node, row, seen, model_cache)
67
+ next
68
+ end
69
+
70
+ key = aliases.column_alias(node, node.primary_key)
71
+
72
+ # CPK
73
+ if key.is_a?(Array)
74
+ id = Array(key).map do |column_alias|
75
+ row[column_alias]
76
+ end
77
+ # At least the first value in the key has to be set. Should we require all values to be set?
78
+ id = nil if id.first.nil?
79
+ else # original
80
+ id = row[key]
81
+ end
82
+
83
+ if id.nil? # duplicating this so it is clear what remained unchanged from the original
84
+ nil_association = ar_parent.association(node.reflection.name)
85
+ nil_association.loaded!
86
+ next
87
+ end
88
+
89
+ model = seen[ar_parent.object_id][node][id]
90
+
91
+ if model
92
+ construct(model, node, row, seen, model_cache)
93
+ else
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)
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -1,9 +1,9 @@
1
- module ActiveRecord
2
- module AttributeMethods
3
- def has_attribute?(attr_name)
4
- # CPK
5
- # @attributes.key?(attr_name.to_s)
6
- Array(attr_name).all? {|single_attr| @attributes.key?(single_attr.to_s) }
7
- end
8
- end
9
- end
1
+ module ActiveRecord
2
+ module AttributeMethods
3
+ def has_attribute?(attr_name)
4
+ # CPK
5
+ # @attributes.key?(attr_name.to_s)
6
+ Array(attr_name).all? {|single_attr| @attributes.key?(single_attr.to_s) }
7
+ end
8
+ end
9
+ end
@@ -1,30 +1,30 @@
1
- module ActiveRecord
2
- module AttributeMethods
3
- module Read
4
- def read_attribute(attr_name, &block)
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
11
-
12
- primary_key = self.class.primary_key
13
- # CPK
14
- # name = primary_key if name == "id" && primary_key
15
- name = primary_key if name == "id" && primary_key && !composite?
16
- sync_with_transaction_state if name == primary_key
17
- _read_attribute(name, &block)
18
- end
19
-
20
- def _read_attribute(attr_name, &block) # :nodoc
21
- # CPK
22
- if attr_name.kind_of?(Array)
23
- attr_name.map {|name| @attributes.fetch_value(name.to_s, &block)}
24
- else
25
- @attributes.fetch_value(attr_name.to_s, &block)
26
- end
27
- end
28
- end
29
- end
30
- end
1
+ module ActiveRecord
2
+ module AttributeMethods
3
+ module Read
4
+ def read_attribute(attr_name, &block)
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
11
+
12
+ primary_key = self.class.primary_key
13
+ # CPK
14
+ # name = primary_key if name == "id" && primary_key
15
+ name = primary_key if name == "id" && primary_key && !composite?
16
+ sync_with_transaction_state if name == primary_key
17
+ _read_attribute(name, &block)
18
+ end
19
+
20
+ def _read_attribute(attr_name, &block) # :nodoc
21
+ # CPK
22
+ if attr_name.kind_of?(Array)
23
+ attr_name.map {|name| @attributes.fetch_value(name.to_s, &block)}
24
+ else
25
+ @attributes.fetch_value(attr_name.to_s, &block)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end