composite_primary_keys 12.0.9 → 13.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.rdoc +15 -1
- data/README.rdoc +1 -0
- data/Rakefile +37 -37
- data/lib/composite_primary_keys/active_model/attribute_assignment.rb +19 -19
- data/lib/composite_primary_keys/arel/sqlserver.rb +37 -37
- data/lib/composite_primary_keys/arel/to_sql.rb +18 -18
- data/lib/composite_primary_keys/associations/association.rb +23 -23
- data/lib/composite_primary_keys/associations/association_scope.rb +66 -68
- data/lib/composite_primary_keys/associations/collection_association.rb +31 -31
- data/lib/composite_primary_keys/associations/foreign_association.rb +15 -15
- data/lib/composite_primary_keys/associations/has_many_association.rb +35 -35
- data/lib/composite_primary_keys/associations/{join_dependency.rb → join_association.rb} +137 -103
- data/lib/composite_primary_keys/associations/through_association.rb +25 -25
- data/lib/composite_primary_keys/attribute_methods/primary_key.rb +0 -2
- data/lib/composite_primary_keys/attribute_methods/read.rb +30 -30
- data/lib/composite_primary_keys/attribute_methods/write.rb +35 -35
- data/lib/composite_primary_keys/attribute_methods.rb +21 -9
- data/lib/composite_primary_keys/autosave_association.rb +60 -60
- data/lib/composite_primary_keys/base.rb +141 -141
- data/lib/composite_primary_keys/composite_arrays.rb +86 -86
- data/lib/composite_primary_keys/composite_predicates.rb +2 -1
- data/lib/composite_primary_keys/composite_relation.rb +29 -29
- data/lib/composite_primary_keys/connection_adapters/abstract/database_statements.rb +37 -37
- data/lib/composite_primary_keys/connection_adapters/abstract_adapter.rb +10 -10
- data/lib/composite_primary_keys/connection_adapters/postgresql/database_statements.rb +26 -26
- data/lib/composite_primary_keys/connection_adapters/sqlserver/database_statements.rb +44 -44
- data/lib/composite_primary_keys/core.rb +48 -48
- data/lib/composite_primary_keys/counter_cache.rb +15 -15
- data/lib/composite_primary_keys/fixtures.rb +21 -21
- data/lib/composite_primary_keys/nested_attributes.rb +1 -1
- data/lib/composite_primary_keys/persistence.rb +3 -2
- data/lib/composite_primary_keys/reflection.rb +91 -29
- data/lib/composite_primary_keys/relation/batches.rb +15 -7
- data/lib/composite_primary_keys/relation/calculations.rb +46 -23
- data/lib/composite_primary_keys/relation/finder_methods.rb +235 -235
- data/lib/composite_primary_keys/relation/predicate_builder/association_query_value.rb +39 -20
- data/lib/composite_primary_keys/relation/query_methods.rb +42 -42
- data/lib/composite_primary_keys/relation/where_clause.rb +18 -23
- data/lib/composite_primary_keys/relation.rb +197 -193
- data/lib/composite_primary_keys/sanitization.rb +42 -42
- data/lib/composite_primary_keys/table_metadata.rb +11 -0
- data/lib/composite_primary_keys/transactions.rb +34 -34
- data/lib/composite_primary_keys/validations/uniqueness.rb +31 -31
- data/lib/composite_primary_keys/version.rb +2 -2
- data/lib/composite_primary_keys.rb +4 -2
- data/scripts/console.rb +48 -48
- data/scripts/txt2html +76 -76
- data/scripts/txt2js +65 -65
- data/tasks/databases/mysql.rake +40 -40
- data/tasks/databases/oracle.rake +41 -41
- data/tasks/databases/postgresql.rake +38 -38
- data/tasks/databases/sqlite.rake +25 -25
- data/tasks/databases/sqlserver.rake +43 -43
- data/tasks/website.rake +18 -18
- data/test/README_tests.rdoc +56 -56
- data/test/connections/connection_spec.rb +27 -27
- data/test/connections/databases.ci.yml +22 -22
- data/test/connections/databases.example.yml +40 -40
- data/test/connections/databases.yml +40 -39
- data/test/fixtures/article.rb +10 -10
- data/test/fixtures/articles.yml +7 -7
- data/test/fixtures/capitol.rb +3 -3
- data/test/fixtures/capitols.yml +16 -16
- data/test/fixtures/comment.rb +5 -5
- data/test/fixtures/comments.yml +17 -17
- data/test/fixtures/db_definitions/db2-create-tables.sql +112 -112
- data/test/fixtures/db_definitions/db2-drop-tables.sql +16 -16
- data/test/fixtures/db_definitions/mysql.sql +180 -180
- data/test/fixtures/db_definitions/oracle.drop.sql +41 -41
- data/test/fixtures/db_definitions/oracle.sql +199 -199
- data/test/fixtures/db_definitions/postgresql.sql +182 -182
- data/test/fixtures/db_definitions/sqlite.sql +169 -169
- data/test/fixtures/db_definitions/sqlserver.sql +176 -176
- data/test/fixtures/departments.yml +19 -15
- data/test/fixtures/dorm.rb +2 -2
- data/test/fixtures/dorms.yml +4 -4
- data/test/fixtures/employee.rb +5 -5
- data/test/fixtures/employees.yml +33 -28
- data/test/fixtures/group.rb +2 -2
- data/test/fixtures/groups.yml +6 -6
- data/test/fixtures/membership.rb +2 -0
- data/test/fixtures/membership_status.rb +2 -2
- data/test/fixtures/membership_statuses.yml +16 -16
- data/test/fixtures/memberships.yml +10 -10
- data/test/fixtures/product.rb +9 -9
- data/test/fixtures/product_tariff.rb +5 -5
- data/test/fixtures/product_tariffs.yml +14 -14
- 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.rb +7 -7
- data/test/fixtures/reference_codes.yml +28 -28
- data/test/fixtures/reference_type.rb +12 -12
- 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_suburb.rb +2 -2
- 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/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/suburb.rb +5 -5
- data/test/fixtures/suburbs.yml +14 -14
- data/test/fixtures/tariff.rb +5 -5
- data/test/fixtures/tariffs.yml +14 -14
- data/test/fixtures/topic_sources.yml +3 -3
- data/test/fixtures/topics.yml +8 -8
- data/test/fixtures/user.rb +11 -11
- data/test/fixtures/users.yml +10 -10
- data/test/plugins/pagination.rb +405 -405
- data/test/plugins/pagination_helper.rb +135 -135
- data/test/test_associations.rb +14 -0
- data/test/test_attribute_methods.rb +63 -63
- data/test/test_attributes.rb +75 -60
- data/test/test_calculations.rb +49 -42
- data/test/test_callbacks.rb +99 -99
- data/test/test_composite_arrays.rb +38 -38
- data/test/test_counter_cache.rb +30 -30
- data/test/test_create.rb +218 -206
- data/test/test_delete.rb +188 -179
- data/test/test_dumpable.rb +15 -15
- data/test/test_dup.rb +37 -37
- data/test/test_equal.rb +26 -26
- data/test/test_exists.rb +39 -39
- data/test/test_find.rb +170 -164
- data/test/test_habtm.rb +141 -141
- data/test/test_ids.rb +112 -112
- data/test/test_miscellaneous.rb +32 -32
- data/test/test_nested_attributes.rb +67 -67
- data/test/test_optimistic.rb +18 -18
- data/test/test_pagination.rb +35 -35
- data/test/test_polymorphic.rb +43 -43
- data/test/test_predicates.rb +59 -59
- data/test/test_preload.rb +102 -102
- data/test/test_santiago.rb +23 -23
- data/test/test_touch.rb +23 -23
- data/test/test_tutorial_example.rb +25 -25
- data/test/test_update.rb +102 -96
- data/test/test_validations.rb +13 -13
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eeb7ac69a866392d1d19aec7ae67f99af052e72e5585375c2cb73990f442cc28
|
4
|
+
data.tar.gz: 6552f1e74d6ab9a40aadd66ea78e8d6c489e6d793a47cc52ab2582f60dfbced7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b0bd53df9177d3569e4646124ff2aaf6bacf4d83a78f287a9e954ed388a37ed4872f4024204e34f7402b7989b401586c53636a551d745e5aaf4871927bb66fb
|
7
|
+
data.tar.gz: 8c2eacaaff041c6c4255aed0402f63038d6e0d781665208cbb9b3bdbcc86666087f69822400384f9dfc44215c23be46ddc1c3c69b7ee0008db636d8ff1e0a29c
|
data/History.rdoc
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
== 13.0.2 (2022-01-09)
|
2
|
+
* Fix scoped associations take #2 (Charlie Savage)
|
3
|
+
|
4
|
+
== 13.0.1 (2021-11-14)
|
5
|
+
* Fix invalid sql generation for some cases of scoped associations (Ryan Mulligan)
|
6
|
+
* Fix unintentional connection to database (Kazuhiro Masuda)
|
7
|
+
* Zip values then keys - fixes #548 (Charlie Savage)
|
8
|
+
|
9
|
+
== 13.0.0 (2021-05-09)
|
10
|
+
* Update to ActiveRecord 6.1 (Javier Julio, Charlie Savage, Sammy Larbi)
|
11
|
+
|
12
|
+
== 12.0.10 (2021-05-09)
|
13
|
+
* Support using the #id method on records with primary keys that also have an :id attribute.
|
14
|
+
|
1
15
|
== 12.0.9 (2021-02-22)
|
2
16
|
* Third time is hopefully the charm on MySQL/MariaDB auto increment fix
|
3
17
|
|
@@ -511,7 +525,7 @@ by replacing quoted identifiers with all-caps equivalents on Oracle (Rhett Sutph
|
|
511
525
|
* Update Oracle tests (Rhett Sutphin)
|
512
526
|
|
513
527
|
== 4.1.1 2011-08-31
|
514
|
-
* Support for AR 3.1.1
|
528
|
+
* Support for AR 3.1.1
|
515
529
|
* Make polymorphic belongs_to work in rails 3.1.1 (Tom Hughes)
|
516
530
|
* Eliminate relative paths from the test suite (Rhett Sutphin)
|
517
531
|
* Minor improvements to the CPK test runner w/o relative path changes (Rhett Sutphin)
|
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 13.x is designed to work with ActiveRecord 6.1.x
|
23
24
|
Version 12.x is designed to work with ActiveRecord 6.0.x
|
24
25
|
Version 11.x is designed to work with ActiveRecord 5.2.x
|
25
26
|
Version 10.x is designed to work with ActiveRecord 5.1.x
|
data/Rakefile
CHANGED
@@ -1,37 +1,37 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'rake'
|
3
|
-
require 'rake/clean'
|
4
|
-
require 'rake/testtask'
|
5
|
-
require 'rubygems/package_task'
|
6
|
-
|
7
|
-
# Set global variable so other tasks can access them
|
8
|
-
::PROJECT_ROOT = File.expand_path(".")
|
9
|
-
::GEM_NAME = 'composite_primary_keys'
|
10
|
-
|
11
|
-
require File.join(PROJECT_ROOT, 'lib', 'composite_primary_keys')
|
12
|
-
require File.join(PROJECT_ROOT, 'test', 'connections', 'connection_spec')
|
13
|
-
|
14
|
-
# Read the spec file
|
15
|
-
spec = Gem::Specification.load("#{GEM_NAME}.gemspec")
|
16
|
-
|
17
|
-
# Setup Rake tasks for managing the gem
|
18
|
-
Gem::PackageTask.new(spec).define
|
19
|
-
|
20
|
-
# Now load in other task files
|
21
|
-
Dir.glob('tasks/**/*.rake').each do |rake_file|
|
22
|
-
load File.join(File.dirname(__FILE__), rake_file)
|
23
|
-
end
|
24
|
-
|
25
|
-
# Set up test tasks for each supported connection adapter
|
26
|
-
%w(mysql sqlite oracle oracle_enhanced postgresql ibm_db sqlserver).each do |adapter|
|
27
|
-
namespace adapter do
|
28
|
-
desc "Run tests using the #{adapter} adapter"
|
29
|
-
task "test" do
|
30
|
-
ENV["ADAPTER"] = adapter
|
31
|
-
Rake::TestTask.new("subtest_#{adapter}") do |t|
|
32
|
-
t.libs << "test"
|
33
|
-
end
|
34
|
-
Rake::Task["subtest_#{adapter}"].invoke
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rubygems/package_task'
|
6
|
+
|
7
|
+
# Set global variable so other tasks can access them
|
8
|
+
::PROJECT_ROOT = File.expand_path(".")
|
9
|
+
::GEM_NAME = 'composite_primary_keys'
|
10
|
+
|
11
|
+
require File.join(PROJECT_ROOT, 'lib', 'composite_primary_keys')
|
12
|
+
require File.join(PROJECT_ROOT, 'test', 'connections', 'connection_spec')
|
13
|
+
|
14
|
+
# Read the spec file
|
15
|
+
spec = Gem::Specification.load("#{GEM_NAME}.gemspec")
|
16
|
+
|
17
|
+
# Setup Rake tasks for managing the gem
|
18
|
+
Gem::PackageTask.new(spec).define
|
19
|
+
|
20
|
+
# Now load in other task files
|
21
|
+
Dir.glob('tasks/**/*.rake').each do |rake_file|
|
22
|
+
load File.join(File.dirname(__FILE__), rake_file)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Set up test tasks for each supported connection adapter
|
26
|
+
%w(mysql sqlite oracle oracle_enhanced postgresql ibm_db sqlserver).each do |adapter|
|
27
|
+
namespace adapter do
|
28
|
+
desc "Run tests using the #{adapter} adapter"
|
29
|
+
task "test" do
|
30
|
+
ENV["ADAPTER"] = adapter
|
31
|
+
Rake::TestTask.new("subtest_#{adapter}") do |t|
|
32
|
+
t.libs << "test"
|
33
|
+
end
|
34
|
+
Rake::Task["subtest_#{adapter}"].invoke
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -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,37 +1,37 @@
|
|
1
|
-
module Arel
|
2
|
-
module Visitors
|
3
|
-
class SQLServer < Arel::Visitors::ToSql
|
4
|
-
def make_Fetch_Possible_And_Deterministic o
|
5
|
-
return if o.limit.nil? && o.offset.nil?
|
6
|
-
t = table_From_Statement o
|
7
|
-
pk = primary_Key_From_Table t
|
8
|
-
return unless pk
|
9
|
-
if o.orders.empty?
|
10
|
-
# Prefer deterministic vs a simple `(SELECT NULL)` expr.
|
11
|
-
# CPK
|
12
|
-
#o.orders = [pk.asc]
|
13
|
-
o.orders = pk.map {|a_pk| a_pk.asc}
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def primary_Key_From_Table t
|
18
|
-
return unless t
|
19
|
-
column_name = @connection.schema_cache.primary_keys(t.name) ||
|
20
|
-
@connection.schema_cache.columns_hash(t.name).first.try(:second).try(:name)
|
21
|
-
|
22
|
-
# CPK
|
23
|
-
# column_name ? t[column_name] : nil
|
24
|
-
case column_name
|
25
|
-
when Array
|
26
|
-
column_name.map do |name|
|
27
|
-
t[name]
|
28
|
-
end
|
29
|
-
when NilClass
|
30
|
-
nil
|
31
|
-
else
|
32
|
-
[t[column_name]]
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
1
|
+
module Arel
|
2
|
+
module Visitors
|
3
|
+
class SQLServer < Arel::Visitors::ToSql
|
4
|
+
def make_Fetch_Possible_And_Deterministic o
|
5
|
+
return if o.limit.nil? && o.offset.nil?
|
6
|
+
t = table_From_Statement o
|
7
|
+
pk = primary_Key_From_Table t
|
8
|
+
return unless pk
|
9
|
+
if o.orders.empty?
|
10
|
+
# Prefer deterministic vs a simple `(SELECT NULL)` expr.
|
11
|
+
# CPK
|
12
|
+
#o.orders = [pk.asc]
|
13
|
+
o.orders = pk.map {|a_pk| a_pk.asc}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def primary_Key_From_Table t
|
18
|
+
return unless t
|
19
|
+
column_name = @connection.schema_cache.primary_keys(t.name) ||
|
20
|
+
@connection.schema_cache.columns_hash(t.name).first.try(:second).try(:name)
|
21
|
+
|
22
|
+
# CPK
|
23
|
+
# column_name ? t[column_name] : nil
|
24
|
+
case column_name
|
25
|
+
when Array
|
26
|
+
column_name.map do |name|
|
27
|
+
t[name]
|
28
|
+
end
|
29
|
+
when NilClass
|
30
|
+
nil
|
31
|
+
else
|
32
|
+
[t[column_name]]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -1,18 +1,18 @@
|
|
1
|
-
module Arel
|
2
|
-
module Visitors
|
3
|
-
class ToSql
|
4
|
-
def visit_CompositePrimaryKeys_CompositeKeys o, collector
|
5
|
-
values = o.map do |key|
|
6
|
-
case key
|
7
|
-
when Arel::Attributes::Attribute
|
8
|
-
"#{key.relation.name}.#{key.name}"
|
9
|
-
else
|
10
|
-
key
|
11
|
-
end
|
12
|
-
end
|
13
|
-
collector << "(#{values.join(', ')})"
|
14
|
-
collector
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
1
|
+
module Arel
|
2
|
+
module Visitors
|
3
|
+
class ToSql
|
4
|
+
def visit_CompositePrimaryKeys_CompositeKeys o, collector
|
5
|
+
values = o.map do |key|
|
6
|
+
case key
|
7
|
+
when Arel::Attributes::Attribute
|
8
|
+
"#{key.relation.name}.#{key.name}"
|
9
|
+
else
|
10
|
+
key
|
11
|
+
end
|
12
|
+
end
|
13
|
+
collector << "(#{values.join(', ')})"
|
14
|
+
collector
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -1,23 +1,23 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module Associations
|
3
|
-
class Association
|
4
|
-
def creation_attributes
|
5
|
-
attributes = {}
|
6
|
-
|
7
|
-
if (reflection.has_one? || reflection.collection?) && !options[:through]
|
8
|
-
# CPK
|
9
|
-
# attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key]
|
10
|
-
Array(reflection.foreign_key).zip(Array(reflection.active_record_primary_key)).each do |key1, key2|
|
11
|
-
attributes[key1] = owner[key2]
|
12
|
-
end
|
13
|
-
|
14
|
-
if reflection.options[:as]
|
15
|
-
attributes[reflection.type] = owner.class.base_class.name
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
attributes
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
module Associations
|
3
|
+
class Association
|
4
|
+
def creation_attributes
|
5
|
+
attributes = {}
|
6
|
+
|
7
|
+
if (reflection.has_one? || reflection.collection?) && !options[:through]
|
8
|
+
# CPK
|
9
|
+
# attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key]
|
10
|
+
Array(reflection.foreign_key).zip(Array(reflection.active_record_primary_key)).each do |key1, key2|
|
11
|
+
attributes[key1] = owner[key2]
|
12
|
+
end
|
13
|
+
|
14
|
+
if reflection.options[:as]
|
15
|
+
attributes[reflection.type] = owner.class.base_class.name
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
attributes
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,69 +1,67 @@
|
|
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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
#
|
33
|
-
#
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
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
|
+
key = reflection.join_primary_key
|
27
|
+
foreign_key = reflection.join_foreign_key
|
28
|
+
|
29
|
+
table = reflection.aliased_table
|
30
|
+
|
31
|
+
# CPK
|
32
|
+
# value = transform_value(owner[foreign_key])
|
33
|
+
# scope = apply_scope(scope, table, key, value)
|
34
|
+
Array(key).zip(Array(foreign_key)).each do |a_join_key, a_foreign_key|
|
35
|
+
value = transform_value(owner[a_foreign_key])
|
36
|
+
scope = apply_scope(scope, table, a_join_key, value)
|
37
|
+
end
|
38
|
+
|
39
|
+
if reflection.type
|
40
|
+
polymorphic_type = transform_value(owner.class.polymorphic_name)
|
41
|
+
scope = apply_scope(scope, table, reflection.type, polymorphic_type)
|
42
|
+
end
|
43
|
+
|
44
|
+
scope
|
45
|
+
end
|
46
|
+
|
47
|
+
def next_chain_scope(scope, reflection, next_reflection)
|
48
|
+
key = reflection.join_primary_key
|
49
|
+
foreign_key = reflection.join_foreign_key
|
50
|
+
|
51
|
+
table = reflection.aliased_table
|
52
|
+
foreign_table = next_reflection.aliased_table
|
53
|
+
|
54
|
+
# CPK
|
55
|
+
# constraint = table[key].eq(foreign_table[foreign_key])
|
56
|
+
constraint = cpk_join_predicate(table, key, foreign_table, foreign_key)
|
57
|
+
|
58
|
+
if reflection.type
|
59
|
+
value = transform_value(next_reflection.klass.polymorphic_name)
|
60
|
+
scope = apply_scope(scope, table, reflection.type, value)
|
61
|
+
end
|
62
|
+
|
63
|
+
scope.joins!(join(foreign_table, constraint))
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
69
67
|
end
|
@@ -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,15 +1,15 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ActiveRecord::Associations
|
4
|
-
module ForeignAssociation # :nodoc:
|
5
|
-
def foreign_key_present?
|
6
|
-
if reflection.klass.primary_key
|
7
|
-
# CPK
|
8
|
-
# owner.attribute_present?(reflection.active_record_primary_key)
|
9
|
-
Array(reflection.active_record_primary_key).all? {|key| owner.attribute_present?(key)}
|
10
|
-
else
|
11
|
-
false
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord::Associations
|
4
|
+
module ForeignAssociation # :nodoc:
|
5
|
+
def foreign_key_present?
|
6
|
+
if reflection.klass.primary_key
|
7
|
+
# CPK
|
8
|
+
# owner.attribute_present?(reflection.active_record_primary_key)
|
9
|
+
Array(reflection.active_record_primary_key).all? {|key| owner.attribute_present?(key)}
|
10
|
+
else
|
11
|
+
false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -1,35 +1,35 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module Associations
|
3
|
-
class HasManyAssociation
|
4
|
-
def delete_records(records, method)
|
5
|
-
if method == :destroy
|
6
|
-
records.each(&:destroy!)
|
7
|
-
update_counter(-records.length) unless reflection.inverse_updates_counter_cache?
|
8
|
-
# CPK
|
9
|
-
elsif self.reflection.klass.composite?
|
10
|
-
predicate = cpk_in_predicate(self.scope.table, self.reflection.klass.primary_keys, records.map(&:id))
|
11
|
-
scope = self.scope.where(predicate)
|
12
|
-
update_counter(-delete_count(method, scope))
|
13
|
-
else
|
14
|
-
scope = self.scope.where(reflection.klass.primary_key => records)
|
15
|
-
update_counter(-delete_count(method, scope))
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def delete_count(method, scope)
|
20
|
-
if method == :delete_all
|
21
|
-
scope.delete_all
|
22
|
-
else
|
23
|
-
# CPK
|
24
|
-
# scope.update_all(nullified_owner_attributes)
|
25
|
-
conds = Array(reflection.foreign_key).inject(Hash.new) do |mem, key|
|
26
|
-
mem[key] = nil
|
27
|
-
mem
|
28
|
-
end
|
29
|
-
conds[reflection.type] = nil if reflection.type.present?
|
30
|
-
scope.update_all(conds)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
module Associations
|
3
|
+
class HasManyAssociation
|
4
|
+
def delete_records(records, method)
|
5
|
+
if method == :destroy
|
6
|
+
records.each(&:destroy!)
|
7
|
+
update_counter(-records.length) unless reflection.inverse_updates_counter_cache?
|
8
|
+
# CPK
|
9
|
+
elsif self.reflection.klass.composite?
|
10
|
+
predicate = cpk_in_predicate(self.scope.table, self.reflection.klass.primary_keys, records.map(&:id))
|
11
|
+
scope = self.scope.where(predicate)
|
12
|
+
update_counter(-delete_count(method, scope))
|
13
|
+
else
|
14
|
+
scope = self.scope.where(reflection.klass.primary_key => records)
|
15
|
+
update_counter(-delete_count(method, scope))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def delete_count(method, scope)
|
20
|
+
if method == :delete_all
|
21
|
+
scope.delete_all
|
22
|
+
else
|
23
|
+
# CPK
|
24
|
+
# scope.update_all(nullified_owner_attributes)
|
25
|
+
conds = Array(reflection.foreign_key).inject(Hash.new) do |mem, key|
|
26
|
+
mem[key] = nil
|
27
|
+
mem
|
28
|
+
end
|
29
|
+
conds[reflection.type] = nil if reflection.type.present?
|
30
|
+
scope.update_all(conds)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|