composite_primary_keys 11.1.0 → 11.2.0

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: f55d6d32e63e96e3824998bbf0923818681cff80a944742a6a832908c560830e
4
- data.tar.gz: 34c936d0f6eb9174bfabef659c7abf7774f2ce34251887d0408922251a06e06f
3
+ metadata.gz: 76e658e30475707dc7495c8f5f5647c18ad0a67edc3cc5787a312a1785418524
4
+ data.tar.gz: f824d0c22fb21ec5d7d8311047433a6661cb5c134549ee46460e6c693b0cbe4c
5
5
  SHA512:
6
- metadata.gz: 4edb592bacd34a108d44ca19706ad9012e048a3a81a449b6ee7726f07cf435acc19839599556db7fc24b2971315fc45966e093690285d1a30cd812e29f7ca48f
7
- data.tar.gz: 42a0143eaa30e435beacf9e5be4e77f065af10a0dde691392bfa8599905da38a8f97213b3d67978d5c46ad33592f610674b33d55dd438e22e59f1476c7366219
6
+ metadata.gz: 0721b3f2dcb649fd585baf7facf0747d73edf8929e1f7c2ef9b4522ce3824b23d94cec7caafd810d7ea77e03043ee3cc31abfd6dca16eb012556be147c634fe0
7
+ data.tar.gz: 40282b497748d0a9eda0cc461c38c4dc91714560022fa37e7466e085a65ea2bd53b85f50cd5845560a2ab43e0c24544b76faf493457f9f9f166ce3761b420285
data/History.rdoc CHANGED
@@ -1,3 +1,10 @@
1
+ == 11.2.0 (2019-03-16)
2
+ * When creating new records, honor composite key autoincrementing fields if possible (Antti Pitkänen)
3
+ * Update Association#run to more closely match ActiveRecord (Fabian Mersch)
4
+ * Updates needed due to changes in ActiveRecord (Sammy Larbi)
5
+ * Fix construct_join_attributes method (Brad Slaughter)
6
+ * Fix destroy_all on HABTM (Brad Slaughter)
7
+
1
8
  == 11.1.0 (2018-11-14)
2
9
  * Support ActiveRecord 5.2.1 (S1Artem Tselovalnikov, Caleb Buxton, Charlie Savage)
3
10
  * Fix counter cache (Tomonori Murakami)
@@ -50,21 +50,19 @@ require 'active_record/associations/join_dependency'
50
50
  require 'active_record/associations/preloader/association'
51
51
  require 'active_record/associations/singular_association'
52
52
  require 'active_record/associations/collection_association'
53
+ require 'active_record/associations/through_association'
53
54
 
54
55
  require 'active_record/attribute_methods/primary_key'
55
56
  require 'active_record/attribute_methods/read'
56
57
  require 'active_record/attribute_methods/write'
57
58
  require 'active_record/nested_attributes'
58
59
 
60
+ require 'active_record/connection_adapters/abstract/database_statements'
59
61
  require 'active_record/connection_adapters/abstract_adapter'
60
62
  require 'active_record/connection_adapters/abstract_mysql_adapter'
61
63
  require 'active_record/connection_adapters/postgresql/database_statements'
62
64
 
63
- require 'active_record/relation/batches'
64
65
  require 'active_record/relation/where_clause'
65
- require 'active_record/relation/calculations'
66
- require 'active_record/relation/finder_methods'
67
- require 'active_record/relation/query_methods'
68
66
  require 'active_record/relation/predicate_builder/association_query_value'
69
67
 
70
68
  require 'active_record/validations/uniqueness'
@@ -92,12 +90,14 @@ require 'composite_primary_keys/associations/has_many_through_association'
92
90
  require 'composite_primary_keys/associations/join_dependency'
93
91
  require 'composite_primary_keys/associations/preloader/association'
94
92
  require 'composite_primary_keys/associations/collection_association'
93
+ require 'composite_primary_keys/associations/through_association'
95
94
 
96
95
  require 'composite_primary_keys/attribute_methods/primary_key'
97
96
  require 'composite_primary_keys/attribute_methods/read'
98
97
  require 'composite_primary_keys/attribute_methods/write'
99
98
  require 'composite_primary_keys/nested_attributes'
100
99
 
100
+ require 'composite_primary_keys/connection_adapters/abstract/database_statements'
101
101
  require 'composite_primary_keys/connection_adapters/abstract_adapter'
102
102
  require 'composite_primary_keys/connection_adapters/abstract_mysql_adapter'
103
103
  require 'composite_primary_keys/connection_adapters/postgresql/database_statements'
@@ -1,66 +1,7 @@
1
1
  module ActiveRecord
2
2
  module Associations
3
3
  class HasManyThroughAssociation
4
- def cpk_join_through_predicate(*records)
5
- ensure_mutable
6
4
 
7
- ids = records.map do |record|
8
- source_reflection.association_primary_key(reflection.klass).map do |key|
9
- record.send(key)
10
- end
11
- end
12
-
13
- cpk_in_predicate(through_association.scope.klass.arel_table, source_reflection.foreign_key, ids)
14
- end
15
-
16
- def delete_records(records, method)
17
- ensure_not_nested
18
-
19
- scope = through_association.scope
20
- # CPK
21
- # scope.where! construct_join_attributes(*records)
22
- if source_reflection.klass.composite?
23
- scope.where! cpk_join_through_predicate(*records)
24
- else
25
- scope.where! construct_join_attributes(*records)
26
- end
27
-
28
- case method
29
- when :destroy
30
- if scope.klass.primary_key
31
- count = scope.destroy_all.length
32
- else
33
- scope.to_a.each do |record|
34
- record.run_callbacks :destroy
35
- end
36
-
37
- arel = scope.arel
38
-
39
- stmt = Arel::DeleteManager.new arel.engine
40
- stmt.from scope.klass.arel_table
41
- stmt.wheres = arel.constraints
42
-
43
- count = scope.klass.connection.delete(stmt, 'SQL', scope.bind_values)
44
- end
45
- when :nullify
46
- count = scope.update_all(source_reflection.foreign_key => nil)
47
- else
48
- count = scope.delete_all
49
- end
50
-
51
- delete_through_records(records)
52
-
53
- if source_reflection.options[:counter_cache] && method != :destroy
54
- counter = source_reflection.counter_cache_column
55
- klass.decrement_counter counter, records.map(&:id)
56
- end
57
-
58
- if through_reflection.collection? && update_through_counter?(method)
59
- update_counter(-count, through_reflection)
60
- end
61
-
62
- update_counter(-count)
63
- end
64
5
 
65
6
  def through_records_for(record)
66
7
  # CPK
@@ -43,7 +43,7 @@ module ActiveRecord
43
43
  convert_key(key)
44
44
  end
45
45
  else
46
- record[association_key_name]
46
+ convert_key(record[association_key_name])
47
47
  end
48
48
 
49
49
  owner = owners_by_key[key]
@@ -0,0 +1,24 @@
1
+ module ActiveRecord
2
+ module Associations
3
+ module ThroughAssociation
4
+ alias :original_construct_join_attributes :construct_join_attributes
5
+
6
+ def construct_join_attributes(*records)
7
+ # CPK
8
+ if source_reflection.klass.composite?
9
+ ensure_mutable
10
+
11
+ ids = records.map do |record|
12
+ source_reflection.association_primary_key(reflection.klass).map do |key|
13
+ record.send(key)
14
+ end
15
+ end
16
+
17
+ cpk_in_predicate(through_association.scope.klass.arel_table, source_reflection.foreign_key, ids)
18
+ else
19
+ original_construct_join_attributes(*records)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,17 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module DatabaseStatements
4
+ def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
5
+ sql, binds = to_sql_and_binds(arel, binds)
6
+ value = exec_insert(sql, name, binds, pk, sequence_name)
7
+
8
+ # CPK
9
+ if value && pk.is_a?(Array)
10
+ id_value || value.rows.first
11
+ else
12
+ id_value || last_inserted_id(value)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -56,5 +56,25 @@ module ActiveRecord
56
56
  connection.delete(dm, "#{self} Destroy")
57
57
  end
58
58
  end
59
+
60
+ def _create_record(attribute_names = self.attribute_names)
61
+ attribute_names &= self.class.column_names
62
+ attributes_values = attributes_with_values_for_create(attribute_names)
63
+
64
+ new_id = self.class._insert_record(attributes_values)
65
+
66
+ # CPK
67
+ if self.composite? && self.id.compact.empty?
68
+ self.id = new_id
69
+ else
70
+ self.id ||= new_id if self.class.primary_key
71
+ end
72
+
73
+ @new_record = false
74
+
75
+ yield(self) if block_given?
76
+
77
+ id
78
+ end
59
79
  end
60
80
  end
@@ -7,12 +7,19 @@ module CompositePrimaryKeys
7
7
  return BatchEnumerator.new(of: of, start: start, finish: finish, relation: self)
8
8
  end
9
9
 
10
- if arel.orders.present? || arel.taken.present?
11
- act_on_order_or_limit_ignored(error_on_ignore)
10
+ if arel.orders.present?
11
+ act_on_ignored_order(error_on_ignore)
12
12
  end
13
13
 
14
- relation = relation.reorder(batch_order).limit(of)
14
+ batch_limit = of
15
+ if limit_value
16
+ remaining = limit_value
17
+ batch_limit = remaining if remaining < batch_limit
18
+ end
19
+
20
+ relation = relation.reorder(batch_order).limit(batch_limit)
15
21
  relation = apply_limits(relation, start, finish)
22
+ relation.skip_query_cache! # Retaining the results in the query cache would undermine the point of batching
16
23
  batch_relation = relation
17
24
 
18
25
  loop do
@@ -39,7 +46,20 @@ module CompositePrimaryKeys
39
46
 
40
47
  yield yielded_relation
41
48
 
42
- break if ids.length < of
49
+ break if ids.length < batch_limit
50
+
51
+ if limit_value
52
+ remaining -= ids.length
53
+
54
+ if remaining == 0
55
+ # Saves a useless iteration when the limit is a multiple of the
56
+ # batch size.
57
+ break
58
+ elsif remaining < batch_limit
59
+ relation = relation.limit(remaining)
60
+ end
61
+ end
62
+
43
63
  # CPK
44
64
  # batch_relation = relation.where(arel_attribute(primary_key).gt(primary_key_offset))
45
65
  batch_relation = if composite?
@@ -1,7 +1,7 @@
1
1
  module CompositePrimaryKeys
2
2
  module VERSION
3
3
  MAJOR = 11
4
- MINOR = 1
4
+ MINOR = 2
5
5
  TINY = 0
6
6
  STRING = [MAJOR, MINOR, TINY].join('.')
7
7
  end
@@ -54,8 +54,8 @@ create table product_tariffs (
54
54
  );
55
55
 
56
56
  create table suburbs (
57
- city_id int not null,
58
- suburb_id int not null,
57
+ city_id serial not null,
58
+ suburb_id serial not null,
59
59
  name varchar(50) not null,
60
60
  primary key (city_id, suburb_id)
61
61
  );
@@ -20,8 +20,8 @@ create table reference_types (
20
20
  );
21
21
 
22
22
  create table reference_codes (
23
- reference_type_id int(11),
24
- reference_code int(11) not null,
23
+ reference_type_id int,
24
+ reference_code int not null,
25
25
  code_label varchar(50) default null,
26
26
  abbreviation varchar(50) default null,
27
27
  description varchar(50) default null,
@@ -29,14 +29,14 @@ create table reference_codes (
29
29
  );
30
30
 
31
31
  create table products (
32
- id int(11) not null primary key,
32
+ id int not null primary key,
33
33
  name varchar(50) default null,
34
34
  created_at TIMESTAMP,
35
35
  updated_at TIMESTAMP
36
36
  );
37
37
 
38
38
  create table tariffs (
39
- tariff_id int(11) not null,
39
+ tariff_id int not null,
40
40
  start_date date not null,
41
41
  amount integer(11) default null,
42
42
  created_at TIMESTAMP,
@@ -45,23 +45,23 @@ create table tariffs (
45
45
  );
46
46
 
47
47
  create table product_tariffs (
48
- product_id int(11) not null,
49
- tariff_id int(11) not null,
48
+ product_id int not null,
49
+ tariff_id int not null,
50
50
  tariff_start_date date not null,
51
51
  primary key (product_id, tariff_id, tariff_start_date)
52
52
  );
53
53
 
54
54
  create table suburbs (
55
- city_id int(11) not null,
56
- suburb_id int(11) not null,
55
+ city_id int identity(1,1) not null,
56
+ suburb_id int identity(1,1) not null,
57
57
  name varchar(50) not null,
58
58
  primary key (city_id, suburb_id)
59
59
  );
60
60
 
61
61
  create table streets (
62
62
  id integer not null primary key autoincrement,
63
- city_id int(11) not null,
64
- suburb_id int(11) not null,
63
+ city_id int not null,
64
+ suburb_id int not null,
65
65
  name varchar(50) not null
66
66
  );
67
67
 
@@ -77,9 +77,9 @@ create table articles (
77
77
 
78
78
  create table readings (
79
79
  id integer not null primary key autoincrement,
80
- user_id int(11) not null,
81
- article_id int(11) not null,
82
- rating int(11) not null
80
+ user_id int not null,
81
+ article_id int not null,
82
+ rating int not null
83
83
  );
84
84
 
85
85
  create table groups (
@@ -33,6 +33,11 @@ class TestAssociations < ActiveSupport::TestCase
33
33
  assert_equal(3, products.inject(0) {|sum, product| sum + product.product_tariffs.length})
34
34
  end
35
35
 
36
+ def test_find_includes_2
37
+ products = ProductTariff.where(:tariff_id => 2).order('product_id, tariff_id').includes(:tariff)
38
+ assert_equal(2, products.length)
39
+ end
40
+
36
41
  def test_find_includes_eager_loading
37
42
  product = products(:second_product)
38
43
  product_tarrif = product_tariffs(:second_free)
@@ -59,6 +64,15 @@ class TestAssociations < ActiveSupport::TestCase
59
64
  assert_equal(3, tariffs.inject(0) {|sum, tariff| sum + tariff.product_tariffs.length})
60
65
  end
61
66
 
67
+ def test_find_each_does_not_throw_error
68
+ tariffs = Tariff.includes(:product_tariffs)
69
+ worked = false
70
+ tariffs.first.product_tariffs.order(:tariff_id).find_each do |pt|
71
+ worked = true
72
+ end
73
+ assert worked
74
+ end
75
+
62
76
  def test_association_with_composite_primary_key_can_be_autosaved
63
77
  room = Room.new(dorm_id: 1000, room_id: 1001)
64
78
  room_assignment = RoomAssignment.new(student_id: 1000)
data/test/test_create.rb CHANGED
@@ -48,6 +48,17 @@ class TestCreate < ActiveSupport::TestCase
48
48
  end
49
49
  end
50
50
 
51
+ def test_create_generated_keys
52
+ # Not all databases support columns with multiple identity fields
53
+ if defined?(ActiveRecord::ConnectionAdapters::PostgreSQL) ||
54
+ defined?(ActiveRecord::ConnectionAdapters::SQLite3)
55
+
56
+ suburb = Suburb.create!(:name => 'Capitol Hill')
57
+ refute_nil(suburb.city_id)
58
+ refute_nil(suburb.suburb_id)
59
+ end
60
+ end
61
+
51
62
  def test_create_on_association
52
63
  suburb = Suburb.first
53
64
  suburb.streets.create(:name => "my street")
data/test/test_delete.rb CHANGED
@@ -116,6 +116,19 @@ class TestDelete < ActiveSupport::TestCase
116
116
  end
117
117
  end
118
118
 
119
+ def test_create_destroy_all_has_and_belongs_to_many_on_non_cpk
120
+ records_before = ActiveRecord::Base.connection.execute('select * from employees_groups')
121
+ employee = Employee.create!(department_id: 3, location_id: 2, name: 'Jon')
122
+ employee.groups << Group.create(name: 'test')
123
+ employee.groups.destroy_all
124
+ records_after = ActiveRecord::Base.connection.execute('select * from employees_groups')
125
+ if records_before.respond_to?(:count)
126
+ assert_equal records_before.count, records_after.count
127
+ elsif records_before.respond_to?(:row_count) # OCI8:Cursor for oracle adapter
128
+ assert_equal records_before.row_count, records_after.row_count
129
+ end
130
+ end
131
+
119
132
  def test_delete_not_destroy_on_cpk
120
133
  tariff = Tariff.where(tariff_id: 2).first
121
134
  tariff.delete
data/test/test_preload.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require File.expand_path('../abstract_unit', __FILE__)
2
2
 
3
3
  class TestPreload < ActiveSupport::TestCase
4
- fixtures :comments, :users, :employees, :groups, :hacks
4
+ fixtures :comments, :users, :employees, :groups, :hacks, :readings
5
5
 
6
6
  class UserForPreload < User
7
7
  has_many :comments_with_include_condition, -> { where('person_type = ?', 'User')},
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: 11.1.0
4
+ version: 11.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Charlie Savage
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-14 00:00:00.000000000 Z
11
+ date: 2019-03-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -100,6 +100,7 @@ files:
100
100
  - lib/composite_primary_keys/associations/has_many_through_association.rb
101
101
  - lib/composite_primary_keys/associations/join_dependency.rb
102
102
  - lib/composite_primary_keys/associations/preloader/association.rb
103
+ - lib/composite_primary_keys/associations/through_association.rb
103
104
  - lib/composite_primary_keys/attribute_methods.rb
104
105
  - lib/composite_primary_keys/attribute_methods/primary_key.rb
105
106
  - lib/composite_primary_keys/attribute_methods/read.rb
@@ -109,6 +110,7 @@ files:
109
110
  - lib/composite_primary_keys/composite_arrays.rb
110
111
  - lib/composite_primary_keys/composite_predicates.rb
111
112
  - lib/composite_primary_keys/composite_relation.rb
113
+ - lib/composite_primary_keys/connection_adapters/abstract/database_statements.rb
112
114
  - lib/composite_primary_keys/connection_adapters/abstract_adapter.rb
113
115
  - lib/composite_primary_keys/connection_adapters/abstract_mysql_adapter.rb
114
116
  - lib/composite_primary_keys/connection_adapters/postgresql/database_statements.rb
@@ -270,8 +272,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
270
272
  - !ruby/object:Gem::Version
271
273
  version: '0'
272
274
  requirements: []
273
- rubyforge_project:
274
- rubygems_version: 2.7.6
275
+ rubygems_version: 3.0.2
275
276
  signing_key:
276
277
  specification_version: 4
277
278
  summary: Composite key support for ActiveRecord