composite_primary_keys 11.1.0 → 11.2.0

Sign up to get free protection for your applications and to get access to all the features.
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