composite_primary_keys 8.1.8 → 9.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/History.rdoc +3 -25
- data/README.rdoc +1 -0
- data/README_DB2.rdoc +33 -33
- data/Rakefile +34 -34
- data/lib/composite_primary_keys.rb +4 -11
- data/lib/composite_primary_keys/associations/association.rb +14 -12
- data/lib/composite_primary_keys/associations/association_scope.rb +27 -54
- data/lib/composite_primary_keys/associations/collection_association.rb +22 -8
- data/lib/composite_primary_keys/associations/has_many_association.rb +16 -54
- data/lib/composite_primary_keys/associations/has_many_through_association.rb +58 -58
- data/lib/composite_primary_keys/associations/join_dependency.rb +74 -56
- data/lib/composite_primary_keys/associations/join_dependency/join_association.rb +13 -11
- data/lib/composite_primary_keys/associations/preloader/association.rb +75 -72
- data/lib/composite_primary_keys/associations/singular_association.rb +8 -12
- data/lib/composite_primary_keys/attribute_methods.rb +6 -4
- data/lib/composite_primary_keys/attribute_methods/primary_key.rb +13 -11
- data/lib/composite_primary_keys/attribute_methods/read.rb +16 -15
- data/lib/composite_primary_keys/attribute_methods/write.rb +21 -19
- data/lib/composite_primary_keys/attribute_set/builder.rb +13 -11
- data/lib/composite_primary_keys/base.rb +5 -69
- data/lib/composite_primary_keys/composite_arrays.rb +8 -51
- data/lib/composite_primary_keys/composite_predicates.rb +7 -16
- data/lib/composite_primary_keys/connection_adapters/abstract_adapter.rb +10 -10
- data/lib/composite_primary_keys/connection_adapters/postgresql_adapter.rb +42 -11
- data/lib/composite_primary_keys/core.rb +46 -45
- data/lib/composite_primary_keys/dirty.rb +19 -19
- data/lib/composite_primary_keys/fixtures.rb +19 -17
- data/lib/composite_primary_keys/locking/optimistic.rb +48 -44
- data/lib/composite_primary_keys/nested_attributes.rb +64 -53
- data/lib/composite_primary_keys/persistence.rb +49 -41
- data/lib/composite_primary_keys/relation.rb +22 -47
- data/lib/composite_primary_keys/relation/batches.rb +33 -30
- data/lib/composite_primary_keys/relation/calculations.rb +3 -7
- data/lib/composite_primary_keys/relation/finder_methods.rb +123 -56
- data/lib/composite_primary_keys/relation/predicate_builder.rb +18 -29
- data/lib/composite_primary_keys/relation/where_clause.rb +33 -0
- data/lib/composite_primary_keys/sanitization.rb +45 -38
- data/lib/composite_primary_keys/validations/uniqueness.rb +37 -37
- data/lib/composite_primary_keys/version.rb +4 -4
- data/scripts/console.rb +48 -48
- data/scripts/txt2html +76 -76
- data/scripts/txt2js +65 -65
- data/tasks/databases/mysql.rake +42 -42
- data/tasks/databases/postgresql.rake +47 -47
- data/tasks/databases/sqlite3.rake +27 -27
- data/tasks/website.rake +18 -18
- data/test/README_tests.rdoc +56 -56
- data/test/abstract_unit.rb +10 -9
- data/test/connections/connection_spec.rb +18 -18
- data/test/connections/databases.yml +9 -39
- data/test/connections/native_ibm_db/connection.rb +18 -18
- data/test/connections/native_mysql/connection.rb +17 -17
- data/test/connections/native_postgresql/connection.rb +12 -12
- data/test/connections/native_sqlite3/connection.rb +9 -9
- data/test/db_test.rb +52 -52
- data/test/fixtures/article.rb +5 -5
- data/test/fixtures/articles.yml +6 -6
- data/test/fixtures/capitol.rb +3 -3
- data/test/fixtures/capitols.yml +16 -16
- data/test/fixtures/comments.yml +15 -15
- data/test/fixtures/db_definitions/mysql.sql +2 -12
- data/test/fixtures/db_definitions/oracle.sql +1 -2
- data/test/fixtures/db_definitions/postgresql.sql +0 -10
- data/test/fixtures/db_definitions/sqlite.sql +0 -9
- data/test/fixtures/db_definitions/sqlserver.sql +1 -2
- data/test/fixtures/department.rb +5 -5
- data/test/fixtures/departments.yml +15 -15
- data/test/fixtures/dorms.yml +4 -4
- data/test/fixtures/employee.rb +1 -2
- data/test/fixtures/employees.yml +19 -23
- data/test/fixtures/group.rb +2 -2
- data/test/fixtures/groups.yml +6 -6
- data/test/fixtures/hack.rb +4 -4
- data/test/fixtures/hacks.yml +2 -2
- data/test/fixtures/membership_status.rb +2 -2
- data/test/fixtures/product.rb +9 -9
- data/test/fixtures/product_tariff.rb +5 -5
- data/test/fixtures/products.yml +11 -11
- data/test/fixtures/reading.rb +4 -4
- data/test/fixtures/readings.yml +10 -10
- data/test/fixtures/reference_code_using_composite_key_alias.rb +8 -8
- data/test/fixtures/reference_code_using_simple_key_alias.rb +8 -8
- data/test/fixtures/reference_codes.yml +28 -28
- data/test/fixtures/reference_type.rb +1 -1
- data/test/fixtures/reference_types.yml +9 -9
- data/test/fixtures/restaurant.rb +9 -9
- data/test/fixtures/restaurants.yml +14 -14
- data/test/fixtures/restaurants_suburbs.yml +10 -10
- data/test/fixtures/room.rb +11 -11
- data/test/fixtures/room_assignment.rb +13 -13
- data/test/fixtures/room_assignments.yml +24 -24
- data/test/fixtures/room_attribute.rb +2 -2
- data/test/fixtures/room_attribute_assignment.rb +4 -4
- data/test/fixtures/room_attribute_assignments.yml +4 -4
- data/test/fixtures/room_attributes.yml +2 -2
- data/test/fixtures/rooms.yml +12 -12
- data/test/fixtures/seat.rb +5 -5
- data/test/fixtures/seats.yml +8 -8
- data/test/fixtures/street.rb +2 -2
- data/test/fixtures/streets.yml +16 -16
- data/test/fixtures/student.rb +3 -3
- data/test/fixtures/students.yml +15 -15
- data/test/fixtures/suburbs.yml +14 -14
- data/test/fixtures/tariff.rb +5 -5
- data/test/fixtures/tariffs.yml +14 -14
- data/test/fixtures/user.rb +0 -1
- data/test/plugins/pagination.rb +405 -405
- data/test/plugins/pagination_helper.rb +135 -135
- data/test/setup.rb +50 -50
- data/test/test_aliases.rb +18 -18
- data/test/test_associations.rb +7 -18
- data/test/test_composite_arrays.rb +24 -38
- data/test/test_counter_cache.rb +30 -30
- data/test/test_create.rb +5 -5
- data/test/test_delete_all.rb +7 -13
- data/test/test_dup.rb +37 -37
- data/test/test_exists.rb +39 -39
- data/test/test_find.rb +16 -12
- data/test/test_habtm.rb +26 -2
- data/test/test_ids.rb +109 -116
- data/test/test_miscellaneous.rb +32 -32
- data/test/test_pagination.rb +35 -35
- data/test/test_polymorphic.rb +0 -7
- data/test/test_predicates.rb +9 -28
- data/test/test_update.rb +3 -5
- data/test/test_validations.rb +13 -13
- metadata +24 -32
- data/lib/composite_primary_keys/arel/visitors/to_sql.rb +0 -36
- data/lib/composite_primary_keys/attribute_methods/dirty.rb +0 -29
- data/lib/composite_primary_keys/autosave_association.rb +0 -67
- data/lib/composite_primary_keys/connection_adapters/abstract_mysql_adapter.rb +0 -23
- data/test/fixtures/pk_called_id.rb +0 -5
- data/test/fixtures/pk_called_ids.yml +0 -11
- data/test/test_find_in_batches.rb +0 -30
- data/test/test_update_all.rb +0 -17
@@ -1,17 +1,48 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module ConnectionAdapters
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
class PostgreSQLAdapter
|
4
|
+
def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
|
5
|
+
unless pk
|
6
|
+
# Extract the table from the insert sql. Yuck.
|
7
|
+
table_ref = extract_table_ref_from_insert_sql(sql)
|
8
|
+
pk = primary_key(table_ref) if table_ref
|
9
|
+
end
|
10
|
+
|
11
|
+
if pk && use_insert_returning?
|
6
12
|
# CPK
|
7
|
-
#
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
# select_value("#{sql} RETURNING #{quote_column_names(pk)}")
|
14
|
+
select_value("#{sql} RETURNING #{quote_column_names(pk)}")
|
15
|
+
elsif pk
|
16
|
+
super
|
17
|
+
last_insert_id_value(sequence_name || default_sequence_name(table_ref, pk))
|
18
|
+
else
|
19
|
+
super
|
20
|
+
end
|
21
|
+
end
|
22
|
+
alias :create :insert
|
23
|
+
|
24
|
+
def sql_for_insert(sql, pk, id_value, sequence_name, binds)
|
25
|
+
unless pk
|
26
|
+
# Extract the table from the insert sql. Yuck.
|
27
|
+
table_ref = extract_table_ref_from_insert_sql(sql)
|
28
|
+
pk = primary_key(table_ref) if table_ref
|
29
|
+
end
|
30
|
+
|
31
|
+
if pk && use_insert_returning?
|
32
|
+
# CPK
|
33
|
+
# sql = "#{sql} RETURNING #{quote_column_names(pk)}"
|
34
|
+
sql = "#{sql} RETURNING #{quote_column_names(pk)}"
|
35
|
+
end
|
36
|
+
|
37
|
+
[sql, binds]
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns a single value if query returns a single element
|
41
|
+
# otherwise returns an array corresponding to the composite keys
|
42
|
+
def last_inserted_id(result)
|
43
|
+
row = result && result.rows.first
|
44
|
+
if Array === row
|
45
|
+
row.size == 1 ? row[0] : row
|
15
46
|
end
|
16
47
|
end
|
17
48
|
end
|
@@ -1,60 +1,61 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module Core
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
silence_warnings do
|
4
|
+
def initialize_dup(other) # :nodoc:
|
5
|
+
@attributes = @attributes.dup
|
6
|
+
# CPK
|
7
|
+
# @attributes.reset(self.class.primary_key)
|
8
|
+
Array(self.class.primary_key).each {|key| @attributes.reset(key)}
|
8
9
|
|
9
|
-
|
10
|
+
run_callbacks(:initialize) unless _initialize_callbacks.empty?
|
10
11
|
|
11
|
-
|
12
|
-
|
12
|
+
@aggregation_cache = {}
|
13
|
+
@association_cache = {}
|
13
14
|
|
14
|
-
|
15
|
-
|
15
|
+
@new_record = true
|
16
|
+
@destroyed = false
|
16
17
|
|
17
|
-
|
18
|
+
super
|
19
|
+
end
|
18
20
|
end
|
19
21
|
|
20
22
|
module ClassMethods
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
s = find_by_statement_cache[key] || find_by_statement_cache.synchronize {
|
47
|
-
find_by_statement_cache[key] ||= StatementCache.create(connection) { |params|
|
23
|
+
silence_warnings do
|
24
|
+
def find(*ids) # :nodoc:
|
25
|
+
# We don't have cache keys for this stuff yet
|
26
|
+
return super unless ids.length == 1
|
27
|
+
return super if block_given? ||
|
28
|
+
primary_key.nil? ||
|
29
|
+
scope_attributes? ||
|
30
|
+
columns_hash.include?(inheritance_column) ||
|
31
|
+
ids.first.kind_of?(Array)
|
32
|
+
# CPK
|
33
|
+
return super if self.composite?
|
34
|
+
|
35
|
+
id = ids.first
|
36
|
+
if ActiveRecord::Base === id
|
37
|
+
id = id.id
|
38
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
39
|
+
You are passing an instance of ActiveRecord::Base to `find`.
|
40
|
+
Please pass the id of the object by calling `.id`
|
41
|
+
MSG
|
42
|
+
end
|
43
|
+
|
44
|
+
key = primary_key
|
45
|
+
|
46
|
+
statement = cached_find_by_statement(key) { |params|
|
48
47
|
where(key => params.bind).limit(1)
|
49
48
|
}
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
49
|
+
record = statement.execute([id], self, connection).first
|
50
|
+
unless record
|
51
|
+
raise RecordNotFound.new("Couldn't find #{name} with '#{primary_key}'=#{id}",
|
52
|
+
name, primary_key, id)
|
53
|
+
end
|
54
|
+
record
|
55
|
+
rescue RangeError
|
56
|
+
raise RecordNotFound.new("Couldn't find #{name} with an out of range value for '#{primary_key}'",
|
57
|
+
name, primary_key)
|
54
58
|
end
|
55
|
-
record
|
56
|
-
rescue RangeError
|
57
|
-
raise RecordNotFound, "Couldn't find #{name} with an out of range value for '#{primary_key}'"
|
58
59
|
end
|
59
60
|
end
|
60
61
|
end
|
@@ -1,19 +1,19 @@
|
|
1
|
-
module ActiveModel
|
2
|
-
module Dirty
|
3
|
-
def can_change_primary_key?
|
4
|
-
true
|
5
|
-
end
|
6
|
-
|
7
|
-
def primary_key_changed?
|
8
|
-
!!changed.detect { |key| ids_hash.keys.include?(key.to_s) }
|
9
|
-
end
|
10
|
-
|
11
|
-
def primary_key_was
|
12
|
-
ids_hash.keys.inject(Hash.new) do |result, attribute_name|
|
13
|
-
result[attribute_name] = attribute_was(attribute_name.to_s)
|
14
|
-
result
|
15
|
-
end
|
16
|
-
end
|
17
|
-
alias_method :ids_hash_was, :primary_key_was
|
18
|
-
end
|
19
|
-
end
|
1
|
+
module ActiveModel
|
2
|
+
module Dirty
|
3
|
+
def can_change_primary_key?
|
4
|
+
true
|
5
|
+
end
|
6
|
+
|
7
|
+
def primary_key_changed?
|
8
|
+
!!changed.detect { |key| ids_hash.keys.include?(key.to_s) }
|
9
|
+
end
|
10
|
+
|
11
|
+
def primary_key_was
|
12
|
+
ids_hash.keys.inject(Hash.new) do |result, attribute_name|
|
13
|
+
result[attribute_name] = attribute_was(attribute_name.to_s)
|
14
|
+
result
|
15
|
+
end
|
16
|
+
end
|
17
|
+
alias_method :ids_hash_was, :primary_key_was
|
18
|
+
end
|
19
|
+
end
|
@@ -1,25 +1,27 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
class Fixture
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
3
|
+
silence_warnings do
|
4
|
+
def find
|
5
|
+
if model_class
|
6
|
+
# CPK
|
7
|
+
# model_class.unscoped do
|
8
|
+
# model_class.find(fixture[model_class.primary_key])
|
9
|
+
# end
|
10
|
+
model_class.unscoped do
|
11
|
+
ids = self.ids(model_class.primary_key)
|
12
|
+
model_class.find(ids)
|
13
|
+
end
|
14
|
+
else
|
15
|
+
raise FixtureClassNotFound, "No class attached to find."
|
12
16
|
end
|
13
|
-
else
|
14
|
-
raise FixtureClassNotFound, "No class attached to find."
|
15
17
|
end
|
16
|
-
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
def ids(key)
|
20
|
+
if key.is_a? Array
|
21
|
+
key.map {|a_key| fixture[a_key.to_s] }
|
22
|
+
else
|
23
|
+
fixture[key]
|
24
|
+
end
|
23
25
|
end
|
24
26
|
end
|
25
27
|
end
|
@@ -1,54 +1,58 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
else
|
30
|
-
affected_rows = relation.where(
|
31
|
-
self.class.primary_key => id,
|
32
|
-
lock_col => previous_lock_value,
|
33
|
-
).update_all(
|
34
|
-
Hash[attributes_for_update(attribute_names).map do |name|
|
1
|
+
module ActiveRecord
|
2
|
+
module Locking
|
3
|
+
module Optimistic
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
silence_warnings do
|
8
|
+
def _update_record(attribute_names = @attributes.keys) #:nodoc:
|
9
|
+
return super unless locking_enabled?
|
10
|
+
return 0 if attribute_names.empty?
|
11
|
+
|
12
|
+
lock_col = self.class.locking_column
|
13
|
+
previous_lock_value = send(lock_col).to_i
|
14
|
+
increment_lock
|
15
|
+
|
16
|
+
attribute_names += [lock_col]
|
17
|
+
attribute_names.uniq!
|
18
|
+
|
19
|
+
begin
|
20
|
+
relation = self.class.unscoped
|
21
|
+
|
22
|
+
if self.composite?
|
23
|
+
affected_rows = relation.where(
|
24
|
+
relation.cpk_id_predicate(relation.table, self.class.primary_key, id_was)
|
25
|
+
).where(
|
26
|
+
lock_col => previous_lock_value
|
27
|
+
).update_all(
|
28
|
+
Hash[attributes_for_update(attribute_names).map do |name|
|
35
29
|
[name, _read_attribute(name)]
|
36
30
|
end]
|
37
|
-
|
38
|
-
|
31
|
+
)
|
32
|
+
else
|
33
|
+
affected_rows = relation.where(
|
34
|
+
self.class.primary_key => id,
|
35
|
+
lock_col => previous_lock_value,
|
36
|
+
).update_all(
|
37
|
+
Hash[attributes_for_update(attribute_names).map do |name|
|
38
|
+
[name, _read_attribute(name)]
|
39
|
+
end]
|
40
|
+
)
|
41
|
+
end
|
39
42
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
+
unless affected_rows == 1
|
44
|
+
raise ActiveRecord::StaleObjectError.new(self, "update")
|
45
|
+
end
|
43
46
|
|
44
|
-
|
47
|
+
affected_rows
|
45
48
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
49
|
+
# If something went wrong, revert the version.
|
50
|
+
rescue Exception
|
51
|
+
send(lock_col + '=', previous_lock_value)
|
52
|
+
raise
|
50
53
|
end
|
51
54
|
end
|
55
|
+
end
|
52
56
|
end
|
53
57
|
end
|
54
58
|
end
|
@@ -8,70 +8,81 @@ module ActiveRecord
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
silence_warnings do
|
12
|
+
def assign_nested_attributes_for_collection_association(association_name, attributes_collection)
|
13
|
+
options = self.nested_attributes_options[association_name]
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
if attributes_collection.respond_to?(:permitted?)
|
16
|
+
attributes_collection = attributes_collection.to_h
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
+
unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array)
|
20
|
+
raise ArgumentError, "Hash or Array expected, got #{attributes_collection.class.name} (#{attributes_collection.inspect})"
|
21
|
+
end
|
19
22
|
|
20
|
-
|
21
|
-
keys = attributes_collection.keys
|
22
|
-
attributes_collection = if keys.include?('id') || keys.include?(:id)
|
23
|
-
[attributes_collection]
|
24
|
-
else
|
25
|
-
attributes_collection.values
|
26
|
-
end
|
27
|
-
end
|
23
|
+
check_record_limit!(options[:limit], attributes_collection)
|
28
24
|
|
29
|
-
|
25
|
+
if attributes_collection.is_a? Hash
|
26
|
+
keys = attributes_collection.keys
|
27
|
+
attributes_collection = if keys.include?('id') || keys.include?(:id)
|
28
|
+
[attributes_collection]
|
29
|
+
else
|
30
|
+
attributes_collection.values
|
31
|
+
end
|
32
|
+
end
|
30
33
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
34
|
+
association = association(association_name)
|
35
|
+
|
36
|
+
existing_records = if association.loaded?
|
37
|
+
association.target
|
38
|
+
# CPK
|
39
|
+
elsif association.reflection.klass.composite?
|
40
|
+
attributes_collection.map do |attribute_collection|
|
41
|
+
attribute_ids = attribute_collection['id'] || attribute_collection[:id]
|
42
|
+
if attribute_ids
|
43
|
+
ids = CompositePrimaryKeys::CompositeKeys.parse(attribute_ids)
|
44
|
+
eq_predicates = Class.new.extend(CompositePrimaryKeys::Predicates).cpk_id_predicate(association.klass.arel_table, association.klass.primary_key, ids)
|
45
|
+
association.scope.where(eq_predicates).to_a
|
46
|
+
else
|
47
|
+
[]
|
41
48
|
end
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
end
|
47
|
-
else
|
48
|
-
attribute_ids = attributes_collection.map {|a| a['id'] || a[:id] }.compact
|
49
|
-
attribute_ids.empty? ? [] : association.scope.where(association.klass.primary_key => attribute_ids)
|
50
|
-
end
|
49
|
+
end.flatten.compact
|
50
|
+
else
|
51
|
+
attribute_ids = attributes_collection.map {|a| a['id'] || a[:id] }.compact
|
52
|
+
attribute_ids.empty? ? [] : association.scope.where(association.klass.primary_key => attribute_ids)
|
53
|
+
end
|
51
54
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
unless reject_new_record?(association_name, attributes)
|
56
|
-
association.build(attributes.except(*UNASSIGNABLE_KEYS))
|
55
|
+
attributes_collection.each do |attributes|
|
56
|
+
if attributes.respond_to?(:permitted?)
|
57
|
+
attributes = attributes.to_h
|
57
58
|
end
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
if target_record
|
66
|
-
existing_record = target_record
|
67
|
-
else
|
68
|
-
association.add_to_target(existing_record, :skip_callbacks)
|
59
|
+
attributes = attributes.with_indifferent_access
|
60
|
+
if attributes['id'].blank?
|
61
|
+
unless reject_new_record?(association_name, attributes)
|
62
|
+
new_record = association.build(attributes.except(*UNASSIGNABLE_KEYS))
|
63
|
+
public_send("#{self.attributes.keys.first}_will_change!") # TODO CPK: Note: Is this a bug in Rails? We need to somehow set the parent model as changed even when changes are only adding new records to an association. This is not the way to do it, but I am not sure how it should be done.
|
64
|
+
new_record
|
69
65
|
end
|
66
|
+
elsif existing_record = cpk_detect_record(attributes['id'], existing_records)
|
67
|
+
unless call_reject_if(association_name, attributes)
|
68
|
+
# Make sure we are operating on the actual object which is in the association's
|
69
|
+
# proxy_target array (either by finding it, or adding it if not found)
|
70
|
+
# Take into account that the proxy_target may have changed due to callbacks
|
71
|
+
target_record = cpk_detect_record(attributes['id'], association.target)
|
70
72
|
|
71
|
-
|
73
|
+
if target_record
|
74
|
+
existing_record = target_record
|
75
|
+
else
|
76
|
+
association.add_to_target(existing_record, :skip_callbacks)
|
77
|
+
end
|
78
|
+
|
79
|
+
result_from_assign = assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
|
80
|
+
public_send("#{self.attributes.keys.first}_will_change!") # TODO CPK: Note: Is this a bug in Rails? We need to somehow set the parent model as changed even when changes are only adding new records to an association. This is not the way to do it, but I am not sure how it should be done.
|
81
|
+
result_from_assign
|
82
|
+
end
|
83
|
+
else
|
84
|
+
raise_nested_attributes_record_not_found!(association_name, attributes['id'])
|
72
85
|
end
|
73
|
-
else
|
74
|
-
raise_nested_attributes_record_not_found!(association_name, attributes['id'])
|
75
86
|
end
|
76
87
|
end
|
77
88
|
end
|