composite_primary_keys 13.0.3 → 13.0.4

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: e585b24e33313e3e28cb2930a551379cdd08acee51021a3291f2a31ba63000e6
4
- data.tar.gz: f6cd7efcbce731128f39a732cf90623c3b06ce5669c71b79cede3b7cb3f2ec8a
3
+ metadata.gz: 875a5dc3886b5b887bbcb77bdcb0bfa40ad377e5084fd1bcdf3a71b5c226dbc3
4
+ data.tar.gz: 9cad15004b91f80917564f623855836217c2ce8e745eb5e6fc47464f10c7cf0c
5
5
  SHA512:
6
- metadata.gz: ceea9d28fa8d5f910158f1c8ac69ca1d56bca8ab095cab681db4f749f0cae1dc0d9a3ff24009b4a0ffd7afb3f1cb452487e24bacddf48144a280a7e61d459028
7
- data.tar.gz: b5ccaaad9807d0a6f82a03be277fea073cc6cfe5dbeb235fbef42ecfd6ca0f321b08367f78e8c8a493614071119399df84c207e3a3cda434f75a9a190980cb5b
6
+ metadata.gz: f771c6c4266eb770f685c7fc0960c344c10b7666a24240c59b456afa2c4c52c058e530e8e3d1ddfb4575468eb5eaf30a77b141216820eb028d774fc9f9593326
7
+ data.tar.gz: 33d2e087cdfc10ea336038a5ffabdb5dd878133ba11ed874ee2d6bd7cf5e572f9acf8b3a996bf04b402c161ffe49d2237ae7284266b58e6eed98b53a890ca7e5
data/History.rdoc CHANGED
@@ -1,3 +1,6 @@
1
+ == 13.0.4
2
+ * Fix previously_new_record? not being set to true after create
3
+
1
4
  == 13.0.3 (2022-01-09)
2
5
  * Remove override on ActiveRecord::Base#to_param. That method has moved to Integration
3
6
  so no longer works. #541. (Charlie Savage)
@@ -1,32 +1,32 @@
1
- module CompositePrimaryKeys
2
- module CollectionAssociation
3
- def ids_writer(ids)
4
- primary_key = reflection.association_primary_key
5
- pk_type = klass.type_for_attribute(primary_key)
6
- ids = Array(ids).reject(&:blank?)
7
- ids.map! { |i| pk_type.cast(i) }
8
-
9
- # CPK-
10
- if primary_key.is_a?(Array)
11
- predicate = CompositePrimaryKeys::Predicates.cpk_in_predicate(klass.arel_table, reflection.association_primary_key, ids)
12
- records = klass.where(predicate).index_by do |r|
13
- reflection.association_primary_key.map{ |k| r.send(k) }
14
- end.values_at(*ids)
15
- else
16
- records = klass.where(primary_key => ids).index_by do |r|
17
- r.public_send(primary_key)
18
- end.values_at(*ids).compact
19
- end
20
-
21
- if records.size != ids.size
22
- found_ids = records.map { |record| record.public_send(primary_key) }
23
- not_found_ids = ids - found_ids
24
- klass.all.raise_record_not_found_exception!(ids, records.size, ids.size, primary_key, not_found_ids)
25
- else
26
- replace(records)
27
- end
28
- end
29
- end
30
- end
31
-
1
+ module CompositePrimaryKeys
2
+ module CollectionAssociation
3
+ def ids_writer(ids)
4
+ primary_key = reflection.association_primary_key
5
+ pk_type = klass.type_for_attribute(primary_key)
6
+ ids = Array(ids).reject(&:blank?)
7
+ ids.map! { |i| pk_type.cast(i) }
8
+
9
+ # CPK-
10
+ if primary_key.is_a?(Array)
11
+ predicate = CompositePrimaryKeys::Predicates.cpk_in_predicate(klass.arel_table, reflection.association_primary_key, ids)
12
+ records = klass.where(predicate).index_by do |r|
13
+ reflection.association_primary_key.map{ |k| r.send(k) }
14
+ end.values_at(*ids)
15
+ else
16
+ records = klass.where(primary_key => ids).index_by do |r|
17
+ r.public_send(primary_key)
18
+ end.values_at(*ids).compact
19
+ end
20
+
21
+ if records.size != ids.size
22
+ found_ids = records.map { |record| record.public_send(primary_key) }
23
+ not_found_ids = ids - found_ids
24
+ klass.all.raise_record_not_found_exception!(ids, records.size, ids.size, primary_key, not_found_ids)
25
+ else
26
+ replace(records)
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
32
  ActiveRecord::Associations::CollectionAssociation.prepend CompositePrimaryKeys::CollectionAssociation
@@ -1,60 +1,60 @@
1
- module ActiveRecord
2
- module AutosaveAssociation
3
- def save_has_one_association(reflection)
4
- association = association_instance_get(reflection.name)
5
- record = association && association.load_target
6
-
7
- if record && !record.destroyed?
8
- autosave = reflection.options[:autosave]
9
-
10
- if autosave && record.marked_for_destruction?
11
- record.destroy
12
- elsif autosave != false
13
- # CPK
14
- #key = reflection.options[:primary_key] ? send(reflection.options[:primary_key]) : id
15
- key = reflection.options[:primary_key] ? self[reflection.options[:primary_key]] : id
16
-
17
- if (autosave && record.changed_for_autosave?) || new_record? || record_changed?(reflection, record, key)
18
- unless reflection.through_reflection
19
- record[reflection.foreign_key] = key
20
- if inverse_reflection = reflection.inverse_of
21
- record.association(inverse_reflection.name).loaded!
22
- end
23
- end
24
-
25
- saved = record.save(validate: !autosave)
26
- raise ActiveRecord::Rollback if !saved && autosave
27
- saved
28
- end
29
- end
30
- end
31
- end
32
-
33
- def save_belongs_to_association(reflection)
34
- association = association_instance_get(reflection.name)
35
- return unless association && association.loaded? && !association.stale_target?
36
-
37
- record = association.load_target
38
- if record && !record.destroyed?
39
- autosave = reflection.options[:autosave]
40
-
41
- if autosave && record.marked_for_destruction?
42
- self[reflection.foreign_key] = nil
43
- record.destroy
44
- elsif autosave != false
45
- saved = record.save(validate: !autosave) if record.new_record? || (autosave && record.changed_for_autosave?)
46
-
47
- if association.updated?
48
- # CPK
49
- # association_id = record.send(reflection.options[:primary_key] || :id)
50
- association_id = reflection.options[:primary_key] ? record[reflection.options[:primary_key]] : record.id
51
- self[reflection.foreign_key] = association_id
52
- association.loaded!
53
- end
54
-
55
- saved if autosave
56
- end
57
- end
58
- end
59
- end
60
- end
1
+ module ActiveRecord
2
+ module AutosaveAssociation
3
+ def save_has_one_association(reflection)
4
+ association = association_instance_get(reflection.name)
5
+ record = association && association.load_target
6
+
7
+ if record && !record.destroyed?
8
+ autosave = reflection.options[:autosave]
9
+
10
+ if autosave && record.marked_for_destruction?
11
+ record.destroy
12
+ elsif autosave != false
13
+ # CPK
14
+ #key = reflection.options[:primary_key] ? send(reflection.options[:primary_key]) : id
15
+ key = reflection.options[:primary_key] ? self[reflection.options[:primary_key]] : id
16
+
17
+ if (autosave && record.changed_for_autosave?) || new_record? || record_changed?(reflection, record, key)
18
+ unless reflection.through_reflection
19
+ record[reflection.foreign_key] = key
20
+ if inverse_reflection = reflection.inverse_of
21
+ record.association(inverse_reflection.name).loaded!
22
+ end
23
+ end
24
+
25
+ saved = record.save(validate: !autosave)
26
+ raise ActiveRecord::Rollback if !saved && autosave
27
+ saved
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ def save_belongs_to_association(reflection)
34
+ association = association_instance_get(reflection.name)
35
+ return unless association && association.loaded? && !association.stale_target?
36
+
37
+ record = association.load_target
38
+ if record && !record.destroyed?
39
+ autosave = reflection.options[:autosave]
40
+
41
+ if autosave && record.marked_for_destruction?
42
+ self[reflection.foreign_key] = nil
43
+ record.destroy
44
+ elsif autosave != false
45
+ saved = record.save(validate: !autosave) if record.new_record? || (autosave && record.changed_for_autosave?)
46
+
47
+ if association.updated?
48
+ # CPK
49
+ # association_id = record.send(reflection.options[:primary_key] || :id)
50
+ association_id = reflection.options[:primary_key] ? record[reflection.options[:primary_key]] : record.id
51
+ self[reflection.foreign_key] = association_id
52
+ association.loaded!
53
+ end
54
+
55
+ saved if autosave
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -1,86 +1,86 @@
1
- module CompositePrimaryKeys
2
- ID_SEP = ','
3
- ID_SET_SEP = ';'
4
- ESCAPE_CHAR = '^'
5
-
6
- module ArrayExtension
7
- def to_composite_keys
8
- CompositeKeys.new(self)
9
- end
10
- end
11
-
12
- # Convert mixed representation of CPKs (by strings or arrays) to normalized
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 serveral 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)
23
- ids.map do |id|
24
- if Utils.cpk_as_array?(id, cpk_size) && id.any? { |item| !Utils.cpk_as_string?(item, cpk_size) }
25
- # CPK as an array - case 1
26
- id
27
- elsif id.is_a?(Array)
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)
33
- else
34
- id
35
- end
36
- end
37
- end
38
-
39
- class CompositeKeys < Array
40
-
41
- def self.parse(value)
42
- case value
43
- when Array
44
- value.to_composite_keys
45
- when String
46
- value.split(ID_SEP).map { |key| Utils.unescape_string_key(key) }.to_composite_keys
47
- else
48
- raise(ArgumentError, "Unsupported type: #{value}")
49
- end
50
- end
51
-
52
- def to_s
53
- # Doing this makes it easier to parse Base#[](attr_name)
54
- map { |key| Utils.escape_string_key(key.to_s) }.join(ID_SEP)
55
- end
56
- end
57
-
58
- module Utils
59
- class << self
60
- def escape_string_key(key)
61
- key.gsub(Regexp.union(ESCAPE_CHAR, ID_SEP)) do |unsafe|
62
- "#{ESCAPE_CHAR}#{unsafe.ord.to_s(16).upcase}"
63
- end
64
- end
65
-
66
- def unescape_string_key(key)
67
- key.gsub(/#{Regexp.escape(ESCAPE_CHAR)}[0-9a-fA-F]{2}/) do |escaped|
68
- char = escaped.slice(1, 2).hex.chr
69
- (char == ESCAPE_CHAR || char == ID_SEP) ? char : escaped
70
- end
71
- end
72
-
73
- def cpk_as_array?(value, pk_size)
74
- # We don't permit Array to be an element of CPK.
75
- value.is_a?(Array) && value.size == pk_size && value.none? { |item| item.is_a?(Array) }
76
- end
77
-
78
- def cpk_as_string?(value, pk_size)
79
- value.is_a?(String) && value.count(ID_SEP) == pk_size - 1
80
- end
81
- end
82
- end
83
- private_constant :Utils
84
- end
85
-
86
- Array.send(:include, CompositePrimaryKeys::ArrayExtension)
1
+ module CompositePrimaryKeys
2
+ ID_SEP = ','
3
+ ID_SET_SEP = ';'
4
+ ESCAPE_CHAR = '^'
5
+
6
+ module ArrayExtension
7
+ def to_composite_keys
8
+ CompositeKeys.new(self)
9
+ end
10
+ end
11
+
12
+ # Convert mixed representation of CPKs (by strings or arrays) to normalized
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 serveral 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)
23
+ ids.map do |id|
24
+ if Utils.cpk_as_array?(id, cpk_size) && id.any? { |item| !Utils.cpk_as_string?(item, cpk_size) }
25
+ # CPK as an array - case 1
26
+ id
27
+ elsif id.is_a?(Array)
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)
33
+ else
34
+ id
35
+ end
36
+ end
37
+ end
38
+
39
+ class CompositeKeys < Array
40
+
41
+ def self.parse(value)
42
+ case value
43
+ when Array
44
+ value.to_composite_keys
45
+ when String
46
+ value.split(ID_SEP).map { |key| Utils.unescape_string_key(key) }.to_composite_keys
47
+ else
48
+ raise(ArgumentError, "Unsupported type: #{value}")
49
+ end
50
+ end
51
+
52
+ def to_s
53
+ # Doing this makes it easier to parse Base#[](attr_name)
54
+ map { |key| Utils.escape_string_key(key.to_s) }.join(ID_SEP)
55
+ end
56
+ end
57
+
58
+ module Utils
59
+ class << self
60
+ def escape_string_key(key)
61
+ key.gsub(Regexp.union(ESCAPE_CHAR, ID_SEP)) do |unsafe|
62
+ "#{ESCAPE_CHAR}#{unsafe.ord.to_s(16).upcase}"
63
+ end
64
+ end
65
+
66
+ def unescape_string_key(key)
67
+ key.gsub(/#{Regexp.escape(ESCAPE_CHAR)}[0-9a-fA-F]{2}/) do |escaped|
68
+ char = escaped.slice(1, 2).hex.chr
69
+ (char == ESCAPE_CHAR || char == ID_SEP) ? char : escaped
70
+ end
71
+ end
72
+
73
+ def cpk_as_array?(value, pk_size)
74
+ # We don't permit Array to be an element of CPK.
75
+ value.is_a?(Array) && value.size == pk_size && value.none? { |item| item.is_a?(Array) }
76
+ end
77
+
78
+ def cpk_as_string?(value, pk_size)
79
+ value.is_a?(String) && value.count(ID_SEP) == pk_size - 1
80
+ end
81
+ end
82
+ end
83
+ private_constant :Utils
84
+ end
85
+
86
+ Array.send(:include, CompositePrimaryKeys::ArrayExtension)
@@ -73,6 +73,7 @@ module ActiveRecord
73
73
  end
74
74
 
75
75
  @new_record = false
76
+ @previously_new_record = true
76
77
 
77
78
  yield(self) if block_given?
78
79
 
@@ -1,32 +1,32 @@
1
- module ActiveRecord
2
- module Validations
3
- class UniquenessValidator
4
- def validate_each(record, attribute, value)
5
- finder_class = find_finder_class_for(record)
6
- value = map_enum_attribute(finder_class, attribute, value)
7
-
8
- relation = build_relation(finder_class, attribute, value)
9
- if record.persisted?
10
- # CPK
11
- if finder_class.primary_key.is_a?(Array)
12
- predicate = finder_class.cpk_id_predicate(finder_class.arel_table, finder_class.primary_key, record.id_in_database || record.id)
13
- relation = relation.where.not(predicate)
14
- elsif finder_class.primary_key
15
- relation = relation.where.not(finder_class.primary_key => record.id_in_database)
16
- else
17
- raise UnknownPrimaryKey.new(finder_class, "Can not validate uniqueness for persisted record without primary key.")
18
- end
19
- end
20
- relation = scope_relation(record, relation)
21
- relation = relation.merge(options[:conditions]) if options[:conditions]
22
-
23
- if relation.exists?
24
- error_options = options.except(:case_sensitive, :scope, :conditions)
25
- error_options[:value] = value
26
-
27
- record.errors.add(attribute, :taken, **error_options)
28
- end
29
- end
30
- end
31
- end
1
+ module ActiveRecord
2
+ module Validations
3
+ class UniquenessValidator
4
+ def validate_each(record, attribute, value)
5
+ finder_class = find_finder_class_for(record)
6
+ value = map_enum_attribute(finder_class, attribute, value)
7
+
8
+ relation = build_relation(finder_class, attribute, value)
9
+ if record.persisted?
10
+ # CPK
11
+ if finder_class.primary_key.is_a?(Array)
12
+ predicate = finder_class.cpk_id_predicate(finder_class.arel_table, finder_class.primary_key, record.id_in_database || record.id)
13
+ relation = relation.where.not(predicate)
14
+ elsif finder_class.primary_key
15
+ relation = relation.where.not(finder_class.primary_key => record.id_in_database)
16
+ else
17
+ raise UnknownPrimaryKey.new(finder_class, "Can not validate uniqueness for persisted record without primary key.")
18
+ end
19
+ end
20
+ relation = scope_relation(record, relation)
21
+ relation = relation.merge(options[:conditions]) if options[:conditions]
22
+
23
+ if relation.exists?
24
+ error_options = options.except(:case_sensitive, :scope, :conditions)
25
+ error_options[:value] = value
26
+
27
+ record.errors.add(attribute, :taken, **error_options)
28
+ end
29
+ end
30
+ end
31
+ end
32
32
  end
@@ -2,7 +2,7 @@ module CompositePrimaryKeys
2
2
  module VERSION
3
3
  MAJOR = 13
4
4
  MINOR = 0
5
- TINY = 3
5
+ TINY = 4
6
6
  STRING = [MAJOR, MINOR, TINY].join('.')
7
7
  end
8
8
  end
@@ -1,14 +1,14 @@
1
- class RoomAssignment < ActiveRecord::Base
2
- self.primary_keys = :student_id, :dorm_id, :room_id
3
- belongs_to :student
4
- belongs_to :room, :foreign_key => [:dorm_id, :room_id], :primary_key => [:dorm_id, :room_id]
5
- validates_uniqueness_of :student_id
6
-
7
- before_destroy do |record|
8
- puts record
9
- end
10
-
11
- after_destroy do |record|
12
- puts record
13
- end
1
+ class RoomAssignment < ActiveRecord::Base
2
+ self.primary_keys = :student_id, :dorm_id, :room_id
3
+ belongs_to :student
4
+ belongs_to :room, :foreign_key => [:dorm_id, :room_id], :primary_key => [:dorm_id, :room_id]
5
+ validates_uniqueness_of :student_id
6
+
7
+ before_destroy do |record|
8
+ puts record
9
+ end
10
+
11
+ after_destroy do |record|
12
+ puts record
13
+ end
14
14
  end
@@ -1,38 +1,38 @@
1
- require File.expand_path('../abstract_unit', __FILE__)
2
-
3
- class CompositeArraysTest < ActiveSupport::TestCase
4
-
5
- def test_new_primary_keys
6
- keys = CompositePrimaryKeys::CompositeKeys.new
7
- assert_not_nil keys
8
- assert_equal '', keys.to_s
9
- assert_equal '', "#{keys}"
10
- end
11
-
12
- def test_initialize_primary_keys
13
- keys = CompositePrimaryKeys::CompositeKeys.new([1,2,3])
14
- assert_not_nil keys
15
- assert_equal '1,2,3', keys.to_s
16
- assert_equal '1,2,3', "#{keys}"
17
- end
18
-
19
- def test_to_composite_keys
20
- keys = [1,2,3].to_composite_keys
21
- assert_equal CompositePrimaryKeys::CompositeKeys, keys.class
22
- assert_equal '1,2,3', keys.to_s
23
- end
24
-
25
- def test_parse
26
- assert_equal ['1', '2'], CompositePrimaryKeys::CompositeKeys.parse('1,2')
27
- assert_equal ['The USA', '^Washington, D.C.'],
28
- CompositePrimaryKeys::CompositeKeys.parse('The USA,^5EWashington^2C D.C.')
29
- assert_equal ['The USA', '^Washington, D.C.'],
30
- CompositePrimaryKeys::CompositeKeys.parse(['The USA', '^Washington, D.C.'])
31
- end
32
-
33
- def test_to_s
34
- assert_equal '1,2', CompositePrimaryKeys::CompositeKeys.new([1, 2]).to_s
35
- assert_equal 'The USA,^5EWashington^2C D.C.',
36
- CompositePrimaryKeys::CompositeKeys.new(['The USA', '^Washington, D.C.']).to_s
37
- end
38
- end
1
+ require File.expand_path('../abstract_unit', __FILE__)
2
+
3
+ class CompositeArraysTest < ActiveSupport::TestCase
4
+
5
+ def test_new_primary_keys
6
+ keys = CompositePrimaryKeys::CompositeKeys.new
7
+ assert_not_nil keys
8
+ assert_equal '', keys.to_s
9
+ assert_equal '', "#{keys}"
10
+ end
11
+
12
+ def test_initialize_primary_keys
13
+ keys = CompositePrimaryKeys::CompositeKeys.new([1,2,3])
14
+ assert_not_nil keys
15
+ assert_equal '1,2,3', keys.to_s
16
+ assert_equal '1,2,3', "#{keys}"
17
+ end
18
+
19
+ def test_to_composite_keys
20
+ keys = [1,2,3].to_composite_keys
21
+ assert_equal CompositePrimaryKeys::CompositeKeys, keys.class
22
+ assert_equal '1,2,3', keys.to_s
23
+ end
24
+
25
+ def test_parse
26
+ assert_equal ['1', '2'], CompositePrimaryKeys::CompositeKeys.parse('1,2')
27
+ assert_equal ['The USA', '^Washington, D.C.'],
28
+ CompositePrimaryKeys::CompositeKeys.parse('The USA,^5EWashington^2C D.C.')
29
+ assert_equal ['The USA', '^Washington, D.C.'],
30
+ CompositePrimaryKeys::CompositeKeys.parse(['The USA', '^Washington, D.C.'])
31
+ end
32
+
33
+ def test_to_s
34
+ assert_equal '1,2', CompositePrimaryKeys::CompositeKeys.new([1, 2]).to_s
35
+ assert_equal 'The USA,^5EWashington^2C D.C.',
36
+ CompositePrimaryKeys::CompositeKeys.new(['The USA', '^Washington, D.C.']).to_s
37
+ end
38
+ end
data/test/test_create.rb CHANGED
@@ -1,218 +1,219 @@
1
- require File.expand_path('../abstract_unit', __FILE__)
2
-
3
- class TestCreate < ActiveSupport::TestCase
4
- fixtures :articles, :students, :dorms, :rooms, :room_assignments, :reference_types, :reference_codes, :streets, :suburbs
5
-
6
- CLASSES = {
7
- :single => {
8
- :class => ReferenceType,
9
- :primary_keys => :reference_type_id,
10
- :create => {:reference_type_id => 10, :type_label => 'NEW_TYPE', :abbreviation => 'New Type'}
11
- },
12
- :dual => {
13
- :class => ReferenceCode,
14
- :primary_keys => [:reference_type_id, :reference_code],
15
- :create => {:reference_type_id => 1, :reference_code => 20, :code_label => 'NEW_CODE', :abbreviation => 'New Code'}
16
- }
17
- }
18
-
19
- def setup
20
- self.class.classes = CLASSES
21
- end
22
-
23
- def test_setup
24
- testing_with do
25
- assert_not_nil @klass_info[:create]
26
- end
27
- end
28
-
29
- def test_create
30
- testing_with do
31
- assert new_obj = @klass.create(@klass_info[:create])
32
- assert !new_obj.new_record?
33
- assert new_obj.id
34
- end
35
- end
36
-
37
- def test_create_no_id
38
- testing_with do
39
- begin
40
- @obj = @klass.create(@klass_info[:create].except(@klass.primary_key))
41
- @successful = !composite?
42
- rescue ActiveRecord::CompositeKeyError
43
- @successful = false
44
- rescue
45
- flunk "Incorrect exception raised: #{$!}, #{$!.class}"
46
- end
47
- assert_equal composite?, !@successful, "Create should have failed for composites; #{@obj.inspect}"
48
- end
49
- end
50
-
51
- def test_create_with_array
52
- date = Date.new(2027, 01, 27)
53
- tariff = Tariff.create!(id: [10, date], amount: 27)
54
- refute_nil(tariff)
55
- assert_equal([10, date], tariff.id)
56
- assert_equal(date, tariff.start_date)
57
- assert_equal(27, tariff.amount)
58
- end
59
-
60
- def test_create_with_partial_serial
61
- attributes = {:location_id => 100}
62
-
63
- # SQLite does not support an autoincrementing field in a composite key
64
- if Department.connection.class.name == "ActiveRecord::ConnectionAdapters::SQLite3Adapter"
65
- attributes[:id] = 200
66
- end
67
-
68
- department = Department.new(attributes)
69
- assert_nil(department.attributes[:id])
70
-
71
- department.save!
72
- refute_nil(department.attributes["id"])
73
- assert_equal(100, department.location_id)
74
- end
75
-
76
- def test_create_with_id
77
- department = Department.create!(id: [2, 3])
78
- assert_equal([2, 3], department.id)
79
- assert_equal(2, department.attributes["id"])
80
- assert_equal(3, department.attributes["location_id"])
81
-
82
- department.reload
83
- assert_equal([2, 3], department.id)
84
- assert_equal(2, department.attributes["id"])
85
- assert_equal(3, department.attributes["location_id"])
86
- end
87
-
88
- def test_create_on_association
89
- suburb = Suburb.first
90
- suburb.streets.create(:name => "my street")
91
- street = Street.find_by_name('my street')
92
- assert_equal(suburb.city_id, street.city_id)
93
- assert_equal(suburb.suburb_id, street.suburb_id)
94
- end
95
-
96
- def test_create_on_association_when_belongs_to_is_single_key
97
- rt = ReferenceType.first
98
- rt.reference_codes.create(:reference_code => 4321, :code_label => 'foo', :abbreviation => 'bar')
99
- rc = ReferenceCode.find_by_reference_code(4321)
100
- assert_equal(rc.reference_type_id, rt.reference_type_id)
101
- end
102
-
103
- def test_new_habtm
104
- restaurant = Restaurant.new(:franchise_id => 101,
105
- :store_id => 201,
106
- :name => "My Store")
107
-
108
- restaurant.suburbs << Suburb.new(:city_id => 24,
109
- :suburb_id => 25,
110
- :name => "My Suburb")
111
-
112
- restaurant.save!
113
-
114
- # Test restaurant
115
- assert_equal(101, restaurant.franchise_id)
116
- assert_equal(201, restaurant.store_id)
117
- assert_equal("My Store", restaurant.name)
118
- assert_equal(1, restaurant.suburbs.length)
119
-
120
- # Test suburbs
121
- suburb = restaurant.suburbs[0]
122
- assert_equal(24, suburb.city_id)
123
- assert_equal(25, suburb.suburb_id)
124
- assert_equal("My Suburb", suburb.name)
125
- end
126
-
127
- def test_create_habtm
128
- restaurant = Restaurant.create(:franchise_id => 100,
129
- :store_id => 200,
130
- :name => "My Store")
131
-
132
- restaurant.suburbs.create(:city_id => 24,
133
- :suburb_id => 25,
134
- :name => "My Suburb")
135
-
136
- # Test restaurant
137
- assert_equal(100, restaurant.franchise_id)
138
- assert_equal(200, restaurant.store_id)
139
- assert_equal("My Store", restaurant.name)
140
-
141
- assert_equal(1, restaurant.suburbs.reload.length)
142
-
143
- # Test suburbs
144
- suburb = restaurant.suburbs[0]
145
- assert_equal(24, suburb.city_id)
146
- assert_equal(25, suburb.suburb_id)
147
- assert_equal("My Suburb", suburb.name)
148
- end
149
-
150
- def test_has_many_ids_1
151
- dorm = dorms(:toyon)
152
- room = Room.new(:dorm_id => dorm.id, :room_id => 5)
153
- room.save!
154
-
155
- student1 = students(:kelly)
156
-
157
- RoomAssignment.delete_all
158
-
159
- assignment1 = RoomAssignment.new(:student_id => student1.id, :dorm_id => room.dorm_id, :room_id => room.room_id)
160
- assignment1.save!
161
-
162
- room.room_assignment_ids = [[assignment1.student_id, assignment1.dorm_id, assignment1.room_id]]
163
- room.save!
164
-
165
- assert_equal(1, room.room_assignments.length)
166
- assert_equal(assignment1, room.room_assignments.first)
167
- end
168
-
169
- def test_has_many_ids_2
170
- dorm = dorms(:toyon)
171
- room = Room.new(:dorm_id => dorm.id, :room_id => 5)
172
- room.save!
173
-
174
- student1 = students(:kelly)
175
- student2 = students(:jordan)
176
-
177
- RoomAssignment.delete_all
178
-
179
- assignment1 = RoomAssignment.new(:student_id => student1.id, :dorm_id => room.dorm_id, :room_id => room.room_id)
180
- assignment1.save!
181
-
182
- assignment2 = RoomAssignment.new(:student_id => student2.id, :dorm_id => room.dorm_id, :room_id => room.room_id)
183
- assignment2.save!
184
-
185
- room.room_assignment_ids = [[assignment1.student_id, assignment1.dorm_id, assignment1.room_id],
186
- [assignment2.student_id, assignment2.dorm_id, assignment2.room_id]]
187
- room.save!
188
-
189
- assert_equal(2, room.room_assignments.length)
190
- assert_equal(assignment1, room.room_assignments[0])
191
- assert_equal(assignment2, room.room_assignments[1])
192
- end
193
-
194
- def test_find_or_create_by
195
- suburb = Suburb.find_by(:city_id => 3, :suburb_id => 1)
196
- assert_nil(suburb)
197
-
198
- suburb = Suburb.find_or_create_by!(:name => 'New Suburb', :city_id => 3, :suburb_id => 1)
199
- refute_nil(suburb)
200
- end
201
-
202
- def test_cache
203
- Suburb.cache do
204
- # Suburb does not exist
205
- suburb = Suburb.find_by(:city_id => 10, :suburb_id => 10)
206
- assert_nil(suburb)
207
-
208
- # Create it
209
- suburb = Suburb.create!(:name => 'New Suburb', :city_id => 10, :suburb_id => 10)
210
-
211
- # Should be able to find it
212
- suburb = Suburb.find_by(:city_id => 10)
213
- refute_nil(suburb)
214
- refute_nil(suburb.city_id)
215
- refute_nil(suburb.suburb_id)
216
- end
217
- end
218
- end
1
+ require File.expand_path('../abstract_unit', __FILE__)
2
+
3
+ class TestCreate < ActiveSupport::TestCase
4
+ fixtures :articles, :students, :dorms, :rooms, :room_assignments, :reference_types, :reference_codes, :streets, :suburbs
5
+
6
+ CLASSES = {
7
+ :single => {
8
+ :class => ReferenceType,
9
+ :primary_keys => :reference_type_id,
10
+ :create => {:reference_type_id => 10, :type_label => 'NEW_TYPE', :abbreviation => 'New Type'}
11
+ },
12
+ :dual => {
13
+ :class => ReferenceCode,
14
+ :primary_keys => [:reference_type_id, :reference_code],
15
+ :create => {:reference_type_id => 1, :reference_code => 20, :code_label => 'NEW_CODE', :abbreviation => 'New Code'}
16
+ }
17
+ }
18
+
19
+ def setup
20
+ self.class.classes = CLASSES
21
+ end
22
+
23
+ def test_setup
24
+ testing_with do
25
+ assert_not_nil @klass_info[:create]
26
+ end
27
+ end
28
+
29
+ def test_create
30
+ testing_with do
31
+ assert new_obj = @klass.create(@klass_info[:create])
32
+ assert !new_obj.new_record?
33
+ assert new_obj.id
34
+ assert new_obj.previously_new_record?
35
+ end
36
+ end
37
+
38
+ def test_create_no_id
39
+ testing_with do
40
+ begin
41
+ @obj = @klass.create(@klass_info[:create].except(@klass.primary_key))
42
+ @successful = !composite?
43
+ rescue ActiveRecord::CompositeKeyError
44
+ @successful = false
45
+ rescue
46
+ flunk "Incorrect exception raised: #{$!}, #{$!.class}"
47
+ end
48
+ assert_equal composite?, !@successful, "Create should have failed for composites; #{@obj.inspect}"
49
+ end
50
+ end
51
+
52
+ def test_create_with_array
53
+ date = Date.new(2027, 01, 27)
54
+ tariff = Tariff.create!(id: [10, date], amount: 27)
55
+ refute_nil(tariff)
56
+ assert_equal([10, date], tariff.id)
57
+ assert_equal(date, tariff.start_date)
58
+ assert_equal(27, tariff.amount)
59
+ end
60
+
61
+ def test_create_with_partial_serial
62
+ attributes = {:location_id => 100}
63
+
64
+ # SQLite does not support an autoincrementing field in a composite key
65
+ if Department.connection.class.name == "ActiveRecord::ConnectionAdapters::SQLite3Adapter"
66
+ attributes[:id] = 200
67
+ end
68
+
69
+ department = Department.new(attributes)
70
+ assert_nil(department.attributes[:id])
71
+
72
+ department.save!
73
+ refute_nil(department.attributes["id"])
74
+ assert_equal(100, department.location_id)
75
+ end
76
+
77
+ def test_create_with_id
78
+ department = Department.create!(id: [2, 3])
79
+ assert_equal([2, 3], department.id)
80
+ assert_equal(2, department.attributes["id"])
81
+ assert_equal(3, department.attributes["location_id"])
82
+
83
+ department.reload
84
+ assert_equal([2, 3], department.id)
85
+ assert_equal(2, department.attributes["id"])
86
+ assert_equal(3, department.attributes["location_id"])
87
+ end
88
+
89
+ def test_create_on_association
90
+ suburb = Suburb.first
91
+ suburb.streets.create(:name => "my street")
92
+ street = Street.find_by_name('my street')
93
+ assert_equal(suburb.city_id, street.city_id)
94
+ assert_equal(suburb.suburb_id, street.suburb_id)
95
+ end
96
+
97
+ def test_create_on_association_when_belongs_to_is_single_key
98
+ rt = ReferenceType.first
99
+ rt.reference_codes.create(:reference_code => 4321, :code_label => 'foo', :abbreviation => 'bar')
100
+ rc = ReferenceCode.find_by_reference_code(4321)
101
+ assert_equal(rc.reference_type_id, rt.reference_type_id)
102
+ end
103
+
104
+ def test_new_habtm
105
+ restaurant = Restaurant.new(:franchise_id => 101,
106
+ :store_id => 201,
107
+ :name => "My Store")
108
+
109
+ restaurant.suburbs << Suburb.new(:city_id => 24,
110
+ :suburb_id => 25,
111
+ :name => "My Suburb")
112
+
113
+ restaurant.save!
114
+
115
+ # Test restaurant
116
+ assert_equal(101, restaurant.franchise_id)
117
+ assert_equal(201, restaurant.store_id)
118
+ assert_equal("My Store", restaurant.name)
119
+ assert_equal(1, restaurant.suburbs.length)
120
+
121
+ # Test suburbs
122
+ suburb = restaurant.suburbs[0]
123
+ assert_equal(24, suburb.city_id)
124
+ assert_equal(25, suburb.suburb_id)
125
+ assert_equal("My Suburb", suburb.name)
126
+ end
127
+
128
+ def test_create_habtm
129
+ restaurant = Restaurant.create(:franchise_id => 100,
130
+ :store_id => 200,
131
+ :name => "My Store")
132
+
133
+ restaurant.suburbs.create(:city_id => 24,
134
+ :suburb_id => 25,
135
+ :name => "My Suburb")
136
+
137
+ # Test restaurant
138
+ assert_equal(100, restaurant.franchise_id)
139
+ assert_equal(200, restaurant.store_id)
140
+ assert_equal("My Store", restaurant.name)
141
+
142
+ assert_equal(1, restaurant.suburbs.reload.length)
143
+
144
+ # Test suburbs
145
+ suburb = restaurant.suburbs[0]
146
+ assert_equal(24, suburb.city_id)
147
+ assert_equal(25, suburb.suburb_id)
148
+ assert_equal("My Suburb", suburb.name)
149
+ end
150
+
151
+ def test_has_many_ids_1
152
+ dorm = dorms(:toyon)
153
+ room = Room.new(:dorm_id => dorm.id, :room_id => 5)
154
+ room.save!
155
+
156
+ student1 = students(:kelly)
157
+
158
+ RoomAssignment.delete_all
159
+
160
+ assignment1 = RoomAssignment.new(:student_id => student1.id, :dorm_id => room.dorm_id, :room_id => room.room_id)
161
+ assignment1.save!
162
+
163
+ room.room_assignment_ids = [[assignment1.student_id, assignment1.dorm_id, assignment1.room_id]]
164
+ room.save!
165
+
166
+ assert_equal(1, room.room_assignments.length)
167
+ assert_equal(assignment1, room.room_assignments.first)
168
+ end
169
+
170
+ def test_has_many_ids_2
171
+ dorm = dorms(:toyon)
172
+ room = Room.new(:dorm_id => dorm.id, :room_id => 5)
173
+ room.save!
174
+
175
+ student1 = students(:kelly)
176
+ student2 = students(:jordan)
177
+
178
+ RoomAssignment.delete_all
179
+
180
+ assignment1 = RoomAssignment.new(:student_id => student1.id, :dorm_id => room.dorm_id, :room_id => room.room_id)
181
+ assignment1.save!
182
+
183
+ assignment2 = RoomAssignment.new(:student_id => student2.id, :dorm_id => room.dorm_id, :room_id => room.room_id)
184
+ assignment2.save!
185
+
186
+ room.room_assignment_ids = [[assignment1.student_id, assignment1.dorm_id, assignment1.room_id],
187
+ [assignment2.student_id, assignment2.dorm_id, assignment2.room_id]]
188
+ room.save!
189
+
190
+ assert_equal(2, room.room_assignments.length)
191
+ assert_equal(assignment1, room.room_assignments[0])
192
+ assert_equal(assignment2, room.room_assignments[1])
193
+ end
194
+
195
+ def test_find_or_create_by
196
+ suburb = Suburb.find_by(:city_id => 3, :suburb_id => 1)
197
+ assert_nil(suburb)
198
+
199
+ suburb = Suburb.find_or_create_by!(:name => 'New Suburb', :city_id => 3, :suburb_id => 1)
200
+ refute_nil(suburb)
201
+ end
202
+
203
+ def test_cache
204
+ Suburb.cache do
205
+ # Suburb does not exist
206
+ suburb = Suburb.find_by(:city_id => 10, :suburb_id => 10)
207
+ assert_nil(suburb)
208
+
209
+ # Create it
210
+ suburb = Suburb.create!(:name => 'New Suburb', :city_id => 10, :suburb_id => 10)
211
+
212
+ # Should be able to find it
213
+ suburb = Suburb.find_by(:city_id => 10)
214
+ refute_nil(suburb)
215
+ refute_nil(suburb.city_id)
216
+ refute_nil(suburb.suburb_id)
217
+ end
218
+ end
219
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: composite_primary_keys
3
3
  version: !ruby/object:Gem::Version
4
- version: 13.0.3
4
+ version: 13.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Charlie Savage
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-09 00:00:00.000000000 Z
11
+ date: 2022-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -216,7 +216,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
216
216
  - !ruby/object:Gem::Version
217
217
  version: '0'
218
218
  requirements: []
219
- rubygems_version: 3.3.4
219
+ rubygems_version: 3.3.14
220
220
  signing_key:
221
221
  specification_version: 4
222
222
  summary: Composite key support for ActiveRecord