composite_primary_keys 9.0.10 → 10.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +5 -5
  2. data/History.rdoc +4 -9
  3. data/README.rdoc +10 -9
  4. data/lib/composite_primary_keys.rb +6 -5
  5. data/lib/composite_primary_keys/arel/sqlserver.rb +2 -1
  6. data/lib/composite_primary_keys/associations/association_scope.rb +4 -4
  7. data/lib/composite_primary_keys/associations/collection_association.rb +1 -1
  8. data/lib/composite_primary_keys/associations/preloader/association.rb +2 -2
  9. data/lib/composite_primary_keys/associations/preloader/belongs_to.rb +2 -2
  10. data/lib/composite_primary_keys/attribute_methods/primary_key.rb +14 -1
  11. data/lib/composite_primary_keys/attribute_methods/write.rb +14 -0
  12. data/lib/composite_primary_keys/attribute_set/builder.rb +22 -0
  13. data/lib/composite_primary_keys/base.rb +6 -5
  14. data/lib/composite_primary_keys/composite_predicates.rb +4 -0
  15. data/lib/composite_primary_keys/connection_adapters/abstract_adapter.rb +10 -10
  16. data/lib/composite_primary_keys/connection_adapters/postgresql/database_statements.rb +26 -0
  17. data/lib/composite_primary_keys/core.rb +9 -12
  18. data/lib/composite_primary_keys/locking/optimistic.rb +7 -7
  19. data/lib/composite_primary_keys/nested_attributes.rb +1 -1
  20. data/lib/composite_primary_keys/relation.rb +1 -6
  21. data/lib/composite_primary_keys/relation/predicate_builder/association_query_handler.rb +33 -0
  22. data/lib/composite_primary_keys/version.rb +2 -2
  23. data/scripts/console.rb +48 -48
  24. data/scripts/txt2html +76 -76
  25. data/scripts/txt2js +65 -65
  26. data/tasks/website.rake +18 -18
  27. data/test/README_tests.rdoc +56 -56
  28. data/test/connections/databases.yml +30 -40
  29. data/test/db_test.rb +52 -52
  30. data/test/fixtures/articles.yml +6 -6
  31. data/test/fixtures/capitol.rb +3 -3
  32. data/test/fixtures/capitols.yml +16 -16
  33. data/test/fixtures/comments.yml +15 -15
  34. data/test/fixtures/department.rb +5 -5
  35. data/test/fixtures/departments.yml +15 -15
  36. data/test/fixtures/dorms.yml +4 -4
  37. data/test/fixtures/group.rb +2 -2
  38. data/test/fixtures/groups.yml +6 -6
  39. data/test/fixtures/hack.rb +4 -4
  40. data/test/fixtures/hacks.yml +2 -2
  41. data/test/fixtures/membership_status.rb +2 -2
  42. data/test/fixtures/product.rb +9 -9
  43. data/test/fixtures/product_tariff.rb +5 -5
  44. data/test/fixtures/products.yml +11 -11
  45. data/test/fixtures/reading.rb +4 -4
  46. data/test/fixtures/readings.yml +10 -10
  47. data/test/fixtures/reference_code_using_composite_key_alias.rb +8 -8
  48. data/test/fixtures/reference_code_using_simple_key_alias.rb +8 -8
  49. data/test/fixtures/reference_codes.yml +28 -28
  50. data/test/fixtures/reference_types.yml +9 -9
  51. data/test/fixtures/restaurant.rb +9 -9
  52. data/test/fixtures/restaurants.yml +14 -14
  53. data/test/fixtures/restaurants_suburbs.yml +10 -10
  54. data/test/fixtures/room.rb +11 -11
  55. data/test/fixtures/room_assignment.rb +13 -13
  56. data/test/fixtures/room_assignments.yml +24 -24
  57. data/test/fixtures/room_attribute.rb +2 -2
  58. data/test/fixtures/room_attribute_assignment.rb +4 -4
  59. data/test/fixtures/room_attribute_assignments.yml +4 -4
  60. data/test/fixtures/room_attributes.yml +2 -2
  61. data/test/fixtures/rooms.yml +12 -12
  62. data/test/fixtures/seat.rb +5 -5
  63. data/test/fixtures/seats.yml +8 -8
  64. data/test/fixtures/street.rb +2 -2
  65. data/test/fixtures/streets.yml +16 -16
  66. data/test/fixtures/student.rb +3 -3
  67. data/test/fixtures/students.yml +15 -15
  68. data/test/fixtures/suburbs.yml +14 -14
  69. data/test/fixtures/tariffs.yml +14 -14
  70. data/test/plugins/pagination.rb +405 -405
  71. data/test/plugins/pagination_helper.rb +135 -135
  72. data/test/setup.rb +50 -50
  73. data/test/test_aliases.rb +18 -18
  74. data/test/test_associations.rb +0 -10
  75. data/test/test_composite_arrays.rb +24 -24
  76. data/test/test_counter_cache.rb +30 -30
  77. data/test/test_dup.rb +37 -37
  78. data/test/test_exists.rb +39 -39
  79. data/test/test_find.rb +9 -3
  80. data/test/test_miscellaneous.rb +32 -32
  81. data/test/test_pagination.rb +35 -35
  82. data/test/test_validations.rb +13 -13
  83. metadata +8 -13
  84. data/lib/composite_primary_keys/autosave_association.rb +0 -32
  85. data/lib/composite_primary_keys/relation/predicate_builder.rb +0 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 133a4025b9fe7ee82617de7c3c34373d8f52d38d5e88c03ab742ebd954bf6064
4
- data.tar.gz: 579e4d9e564e4c9e40f976d0d56b76533296c8f7e5b5ba925d7244141604fb08
2
+ SHA1:
3
+ metadata.gz: d393427145f3047288fffba8fc3434fa41518f4e
4
+ data.tar.gz: f828598d6e09660c798a7735510c5130084b85b9
5
5
  SHA512:
6
- metadata.gz: 334933952b9a84db67746c48c074c38d197215fa607640e134bf7aedd564e122a0c809318fab4529e0ad5bd181081baa792395419b25a4b19149066122cdfdfc
7
- data.tar.gz: 2820381f390429bbdf61b0a04434c0432faa88d2cffdb04c5cd74f9dfc26682893809531b2d4dc14b03620614bec0ce1a69e128624b6a511b5718b19e24c9970
6
+ metadata.gz: fb6c3cfc3c74ddd3eca736945a5e70cebc2a093e704d0407cbe2983670be5282958cffa24507069e623b1099984fceeb02864b55a76d29c3712bcfac91686a58
7
+ data.tar.gz: eeef7b365078357a92b2167f200458bde725b3b3e2032bb17d0799bd19a02e93314e758f89dcf97144d3d39a315cb22fa2120f9848d3496f9f2355190c447dd2
data/History.rdoc CHANGED
@@ -1,14 +1,9 @@
1
- == 9.0.10 (2018-06-24)
2
-
3
- * Fix AR 5.0.7 (Jordan Owens)
4
-
5
- == 9.0.9 (2018-03-06)
6
-
7
- * Fix update statements that incorrectly pass NULL values for the primary key components (Sean Linsley)
8
-
9
- == 9.0.8 (2017-10-11)
1
+ == 10.0.0 (2017-10-08)
10
2
 
3
+ * Support ActiveRecord 5.1.x (Pinak Thakkar, Jordan Owens)
11
4
  * Fix Paper Trail compatibility (Sean Linsley)
5
+ * Fix typo in Readme (Mike Gunderloy)
6
+ * Improved sql server support (Artyom Nikolaev)
12
7
 
13
8
  == 9.0.7 (2017-05-22)
14
9
 
data/README.rdoc CHANGED
@@ -12,7 +12,7 @@ to support composite keys.
12
12
 
13
13
  If you are using Rails add the following to your Gemfile:
14
14
 
15
- gem 'composite_primary_keys', '=x.x.x' (see next section about what verison to use)
15
+ gem 'composite_primary_keys', '=x.x.x' (see next section about what version to use)
16
16
 
17
17
  == Versions
18
18
 
@@ -20,12 +20,13 @@ 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 9.x is designed to work with ActiveRecord 5.0.x
24
- Version 8.x is designed to work with ActiveRecord 4.2.x
25
- Version 7.x is designed to work with ActiveRecord 4.1.x
26
- Version 6.x is designed to work with ActiveRecord 4.0.x
27
- Version 5.x is designed to work with ActiveRecord 3.2.x
28
- Version 4.x is designed to work with ActiveRecord 3.1.x
23
+ Version 10.x is designed to work with ActiveRecord 5.1.x (note this is in progress)
24
+ Version 9.x is designed to work with ActiveRecord 5.0.x
25
+ Version 8.x is designed to work with ActiveRecord 4.2.x
26
+ Version 7.x is designed to work with ActiveRecord 4.1.x
27
+ Version 6.x is designed to work with ActiveRecord 4.0.x
28
+ Version 5.x is designed to work with ActiveRecord 3.2.x
29
+ Version 4.x is designed to work with ActiveRecord 3.1.x
29
30
 
30
31
  Run the following command to list available versions:
31
32
 
@@ -155,8 +156,8 @@ built-in rake task before running tests:
155
156
 
156
157
  rake sqlite:build_database
157
158
 
158
- Note not all tests currently pass on sqlite3. These failures happen when trying to DELETE records where the query
159
- includes a JOIN.
159
+ For sqlite3 to work correctly, you must manually require 'composite_primary_keys/connection_adapters/sqlite3_adapter' after
160
+ loading the CPK gem.
160
161
 
161
162
  === SqlServer
162
163
 
@@ -26,7 +26,7 @@ $:.unshift(File.dirname(__FILE__)) unless
26
26
 
27
27
  unless defined?(ActiveRecord)
28
28
  require 'rubygems'
29
- gem 'activerecord', '~>5.0.0.beta3'
29
+ gem 'activerecord', '~>5.1.0'
30
30
  require 'active_record'
31
31
  end
32
32
 
@@ -38,7 +38,6 @@ require 'active_record/persistence'
38
38
  require 'active_record/relation'
39
39
  require 'active_record/sanitization'
40
40
  require 'active_record/attribute_methods'
41
- require 'active_record/autosave_association'
42
41
 
43
42
  require 'active_record/associations/association'
44
43
  require 'active_record/associations/association_scope'
@@ -51,6 +50,7 @@ require 'active_record/associations/preloader/belongs_to'
51
50
  require 'active_record/associations/singular_association'
52
51
  require 'active_record/associations/collection_association'
53
52
 
53
+ require 'active_record/attribute_set/builder'
54
54
  require 'active_record/attribute_methods/primary_key'
55
55
  require 'active_record/attribute_methods/read'
56
56
  require 'active_record/attribute_methods/write'
@@ -59,12 +59,12 @@ require 'active_record/nested_attributes'
59
59
 
60
60
  require 'active_record/connection_adapters/abstract_adapter'
61
61
  require 'active_record/connection_adapters/abstract_mysql_adapter'
62
+ require 'active_record/connection_adapters/postgresql/database_statements'
62
63
 
63
64
  require 'active_record/relation/batches'
64
65
  require 'active_record/relation/where_clause'
65
66
  require 'active_record/relation/calculations'
66
67
  require 'active_record/relation/finder_methods'
67
- require 'active_record/relation/predicate_builder'
68
68
  require 'active_record/relation/query_methods'
69
69
 
70
70
  # CPK files
@@ -76,8 +76,8 @@ require 'composite_primary_keys/composite_predicates'
76
76
  require 'composite_primary_keys/fixtures'
77
77
  require 'composite_primary_keys/relation'
78
78
  require 'composite_primary_keys/sanitization'
79
+ require 'composite_primary_keys/attribute_set/builder'
79
80
  require 'composite_primary_keys/attribute_methods'
80
- require 'composite_primary_keys/autosave_association'
81
81
  require 'composite_primary_keys/version'
82
82
 
83
83
  require 'composite_primary_keys/associations/association'
@@ -98,12 +98,13 @@ require 'composite_primary_keys/nested_attributes'
98
98
 
99
99
  require 'composite_primary_keys/connection_adapters/abstract_adapter'
100
100
  require 'composite_primary_keys/connection_adapters/abstract_mysql_adapter'
101
+ require 'composite_primary_keys/connection_adapters/postgresql/database_statements'
101
102
 
102
103
  require 'composite_primary_keys/relation/batches'
103
104
  require 'composite_primary_keys/relation/where_clause'
104
105
  require 'composite_primary_keys/relation/calculations'
105
106
  require 'composite_primary_keys/relation/finder_methods'
106
- require 'composite_primary_keys/relation/predicate_builder'
107
+ require 'composite_primary_keys/relation/predicate_builder/association_query_handler'
107
108
  require 'composite_primary_keys/relation/query_methods'
108
109
 
109
110
  require 'composite_primary_keys/composite_relation'
@@ -16,7 +16,8 @@ module Arel
16
16
 
17
17
  def primary_Key_From_Table t
18
18
  return unless t
19
- column_name = schema_cache.primary_keys(t.name) || column_cache(t.name).first.second.try(:name)
19
+ column_name = @connection.schema_cache.primary_keys(t.name) ||
20
+ @connection.schema_cache.columns_hash(t.name).first.try(:second).try(:name)
20
21
 
21
22
  # CPK
22
23
  # column_name ? t[column_name] : nil
@@ -23,8 +23,8 @@ module ActiveRecord
23
23
  binds
24
24
  end
25
25
 
26
- def last_chain_scope(scope, table, reflection, owner, association_klass)
27
- join_keys = reflection.join_keys(association_klass)
26
+ def last_chain_scope(scope, table, reflection, owner)
27
+ join_keys = reflection.join_keys
28
28
  key = join_keys.key
29
29
  foreign_key = join_keys.foreign_key
30
30
 
@@ -46,8 +46,8 @@ module ActiveRecord
46
46
  scope
47
47
  end
48
48
 
49
- def next_chain_scope(scope, table, reflection, association_klass, foreign_table, next_reflection)
50
- join_keys = reflection.join_keys(association_klass)
49
+ def next_chain_scope(scope, table, reflection, foreign_table, next_reflection)
50
+ join_keys = reflection.join_keys
51
51
  key = join_keys.key
52
52
  foreign_key = join_keys.foreign_key
53
53
 
@@ -29,7 +29,7 @@ module CompositePrimaryKeys
29
29
  ids.map! { |i| pk_type.cast(i) }
30
30
  # CPK
31
31
  if reflection.association_primary_key.is_a?(Array)
32
- predicate = Class.new.extend(CompositePrimaryKeys::Predicates).cpk_in_predicate(klass.arel_table, reflection.association_primary_key, ids)
32
+ predicate = CompositePrimaryKeys::Predicates.cpk_in_predicate(klass.arel_table, reflection.association_primary_key, ids)
33
33
  records = klass.where(predicate).index_by do |r|
34
34
  reflection.association_primary_key.map{ |k| r.send(k) }
35
35
  end.values_at(*ids)
@@ -3,9 +3,9 @@ module ActiveRecord
3
3
  class Preloader
4
4
  class Association
5
5
  silence_warnings do
6
- def query_scope(ids)
6
+ def records_for(ids)
7
7
  # CPK
8
- # scope.where(association_key.in(ids))
8
+ # scope.where(association_key_name => ids)
9
9
 
10
10
  if reflection.foreign_key.is_a?(Array)
11
11
  predicate = cpk_in_predicate(table, reflection.foreign_key, ids)
@@ -2,7 +2,7 @@ module ActiveRecord
2
2
  module Associations
3
3
  class Preloader
4
4
  class BelongsTo
5
- def query_scope(ids)
5
+ def records_for(ids)
6
6
  # CPK
7
7
  # scope.where(association_key.in(ids))
8
8
 
@@ -10,7 +10,7 @@ module ActiveRecord
10
10
  predicate = cpk_in_predicate(table, association_key_name, ids)
11
11
  scope.where(predicate)
12
12
  else
13
- scope.where(association_key.in(ids))
13
+ scope.where(association_key_name => ids)
14
14
  end
15
15
  end
16
16
  end
@@ -9,13 +9,26 @@ module ActiveRecord
9
9
  # attribute_was(self.class.primary_key)
10
10
  if self.composite?
11
11
  self.class.primary_keys.map do |key_attr|
12
- attribute_was(key_attr)
12
+ attribute_changed?(key_attr) ? changed_attributes[key_attr] : self.ids_hash[key_attr]
13
13
  end
14
14
  else
15
15
  attribute_was(self.class.primary_key)
16
16
  end
17
17
 
18
18
  end
19
+
20
+ def id_in_database
21
+ sync_with_transaction_state
22
+ # CPK
23
+ # attribute_in_database(self.class.primary_key)
24
+ if self.composite?
25
+ self.class.primary_keys.map do |key_attr|
26
+ attribute_in_database(key_attr)
27
+ end
28
+ else
29
+ attribute_in_database(self.class.primary_key)
30
+ end
31
+ end
19
32
  end
20
33
  end
21
34
  end
@@ -2,6 +2,20 @@ module ActiveRecord
2
2
  module AttributeMethods
3
3
  module Write
4
4
  silence_warnings do
5
+ def write_attribute(attr_name, value)
6
+ name = if self.class.attribute_alias?(attr_name)
7
+ # CPK
8
+ # self.class.attribute_alias(attr_name).to_s
9
+ self.class.attribute_alias(attr_name)
10
+ else
11
+ # CPK
12
+ # attr_name.to_s
13
+ attr_name
14
+ end
15
+
16
+ write_attribute_with_type_cast(name, value, true)
17
+ end
18
+
5
19
  def write_attribute_with_type_cast(attr_name, value, should_type_cast)
6
20
  # CPK
7
21
  if attr_name.kind_of?(Array)
@@ -0,0 +1,22 @@
1
+ module ActiveRecord
2
+ class AttributeSet # :nodoc:
3
+ class Builder # :nodoc:
4
+ silence_warnings do
5
+ def build_from_database(values = {}, additional_types = {})
6
+ # CPK
7
+ # if always_initialized && !values.key?(always_initialized)
8
+ # values[always_initialized] = nil
9
+ # end
10
+ Array(always_initialized).each do |always_initialized_attribute|
11
+ if always_initialized_attribute && !values.key?(always_initialized_attribute)
12
+ values[always_initialized_attribute] = nil
13
+ end
14
+ end
15
+
16
+ attributes = LazyAttributeHash.new(types, values, additional_types)
17
+ AttributeSet.new(attributes)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -47,15 +47,16 @@ module ActiveRecord
47
47
 
48
48
  module CompositeClassMethods
49
49
  def primary_keys
50
- unless defined?(@primary_keys)
51
- reset_primary_keys
52
- end
50
+ @primary_keys = reset_primary_keys unless defined? @primary_keys
53
51
  @primary_keys
54
52
  end
55
53
 
56
54
  # Don't like this method name, but its modeled after how AR does it
57
- def reset_primary_keys
58
- if self != base_class
55
+ def reset_primary_keys #:nodoc:
56
+ if self == base_class
57
+ # CPK
58
+ self.primary_keys = get_primary_key(base_class.name)
59
+ else
59
60
  self.primary_keys = base_class.primary_keys
60
61
  end
61
62
  end
@@ -1,5 +1,9 @@
1
1
  module CompositePrimaryKeys
2
2
  module Predicates
3
+ # Similar to module_function, but does not make instance methods private.
4
+ # https://idiosyncratic-ruby.com/8-self-improvement.html
5
+ extend self
6
+
3
7
  def cpk_and_predicate(predicates)
4
8
  if predicates.length == 1
5
9
  predicates.first
@@ -1,11 +1,11 @@
1
- module ActiveRecord
2
- module ConnectionAdapters
3
- class AbstractAdapter
4
- def quote_column_names(name)
5
- Array(name).map do |col|
6
- quote_column_name(col.to_s)
7
- end.join(CompositePrimaryKeys::ID_SEP)
8
- end
9
- end
10
- end
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class AbstractAdapter
4
+ def quote_column_names(name)
5
+ Array(name).map do |col|
6
+ quote_column_name(col.to_s)
7
+ end.join(CompositePrimaryKeys::ID_SEP)
8
+ end
9
+ end
10
+ end
11
11
  end
@@ -0,0 +1,26 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module PostgreSQL
4
+ module DatabaseStatements
5
+ def sql_for_insert(sql, pk, id_value, sequence_name, binds) # :nodoc:
6
+ if pk.nil?
7
+ # Extract the table from the insert sql. Yuck.
8
+ table_ref = extract_table_ref_from_insert_sql(sql)
9
+ pk = primary_key(table_ref) if table_ref
10
+ end
11
+
12
+ # CPK
13
+ # if pk = suppress_composite_primary_key(pk)
14
+ # sql = "#{sql} RETURNING #{quote_column_name(pk)}"
15
+ #end
16
+ # NOTE pk can be false.
17
+ if pk
18
+ sql = "#{sql} RETURNING #{quote_column_names(pk)}"
19
+ end
20
+
21
+ super
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -27,36 +27,33 @@ module ActiveRecord
27
27
  return super if block_given? ||
28
28
  primary_key.nil? ||
29
29
  scope_attributes? ||
30
- columns_hash.include?(inheritance_column) ||
31
- ids.first.kind_of?(Array)
30
+ columns_hash.include?(inheritance_column)
31
+
32
32
  # CPK
33
33
  return super if self.composite?
34
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
35
+ id = ids.first
36
+
37
+ return super if id.kind_of?(Array) ||
38
+ id.is_a?(ActiveRecord::Base)
43
39
 
44
40
  key = primary_key
45
41
 
46
42
  statement = cached_find_by_statement(key) { |params|
47
43
  where(key => params.bind).limit(1)
48
44
  }
45
+
49
46
  record = statement.execute([id], self, connection).first
50
47
  unless record
51
48
  raise RecordNotFound.new("Couldn't find #{name} with '#{primary_key}'=#{id}",
52
49
  name, primary_key, id)
53
50
  end
54
51
  record
55
- rescue RangeError
52
+ rescue ::RangeError
56
53
  raise RecordNotFound.new("Couldn't find #{name} with an out of range value for '#{primary_key}'",
57
54
  name, primary_key)
58
55
  end
59
56
  end
60
57
  end
61
58
  end
62
- end
59
+ end
@@ -5,7 +5,7 @@ module ActiveRecord
5
5
  private
6
6
 
7
7
  silence_warnings do
8
- def _update_record(attribute_names = self.attribute_names) #:nodoc:
8
+ def _update_record(attribute_names = @attributes.keys) #:nodoc:
9
9
  return super unless locking_enabled?
10
10
  return 0 if attribute_names.empty?
11
11
 
@@ -25,18 +25,18 @@ module ActiveRecord
25
25
  ).where(
26
26
  lock_col => previous_lock_value
27
27
  ).update_all(
28
- attributes_for_update(attribute_names).map do |name|
29
- [name, _read_attribute(name)]
30
- end.to_h
28
+ Hash[attributes_for_update(attribute_names).map do |name|
29
+ [name, _read_attribute(name)]
30
+ end]
31
31
  )
32
32
  else
33
33
  affected_rows = relation.where(
34
34
  self.class.primary_key => id,
35
35
  lock_col => previous_lock_value,
36
36
  ).update_all(
37
- attributes_for_update(attribute_names).map do |name|
38
- [name, _read_attribute(name)]
39
- end.to_h
37
+ Hash[attributes_for_update(attribute_names).map do |name|
38
+ [name, _read_attribute(name)]
39
+ end]
40
40
  )
41
41
  end
42
42