composite_primary_keys 5.0.14 → 6.0.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.
Files changed (35) hide show
  1. checksums.yaml +14 -6
  2. data/History.rdoc +2 -8
  3. data/lib/composite_primary_keys.rb +3 -3
  4. data/lib/composite_primary_keys/associations/association.rb +1 -1
  5. data/lib/composite_primary_keys/associations/association_scope.rb +12 -13
  6. data/lib/composite_primary_keys/associations/has_and_belongs_to_many_association.rb +4 -4
  7. data/lib/composite_primary_keys/associations/has_many_association.rb +2 -2
  8. data/lib/composite_primary_keys/associations/join_dependency.rb +1 -1
  9. data/lib/composite_primary_keys/associations/join_dependency/join_part.rb +3 -3
  10. data/lib/composite_primary_keys/associations/preloader/association.rb +2 -2
  11. data/lib/composite_primary_keys/associations/preloader/belongs_to.rb +1 -1
  12. data/lib/composite_primary_keys/associations/preloader/has_and_belongs_to_many.rb +2 -2
  13. data/lib/composite_primary_keys/attribute_methods/dirty.rb +0 -2
  14. data/lib/composite_primary_keys/attribute_methods/read.rb +3 -3
  15. data/lib/composite_primary_keys/base.rb +3 -27
  16. data/lib/composite_primary_keys/connection_adapters/abstract/connection_specification_changes.rb +2 -2
  17. data/lib/composite_primary_keys/core.rb +28 -0
  18. data/lib/composite_primary_keys/persistence.rb +33 -50
  19. data/lib/composite_primary_keys/relation.rb +5 -5
  20. data/lib/composite_primary_keys/relation/calculations.rb +2 -2
  21. data/lib/composite_primary_keys/relation/query_methods.rb +14 -0
  22. data/lib/composite_primary_keys/version.rb +2 -2
  23. data/test/abstract_unit.rb +0 -1
  24. data/test/connections/databases.yml +10 -1
  25. data/test/debug.log +589 -0
  26. data/test/test_attributes.rb +1 -0
  27. data/test/test_calculations.rb +1 -1
  28. data/test/test_delete.rb +12 -0
  29. data/test/test_dup.rb +3 -2
  30. data/test/test_suite.rb +0 -2
  31. metadata +24 -32
  32. data/lib/composite_primary_keys/counter_cache.rb +0 -22
  33. data/test/fixtures/employees_group.rb +0 -2
  34. data/test/fixtures/employees_groups.yml +0 -15
  35. data/test/test_delete_without_pk.rb +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 6d742f5b3aa47b253ff251f23022e7341a295323
4
- data.tar.gz: 784a15040a16aa863c8a663023597bcbd3ae0ca2
5
- SHA512:
6
- metadata.gz: dc637cd61e831a0b0f9bb7e227d68ca8e4c6d7b9860e1d795824a15b0da908f896b914fadd6070cf789885b3249d15e9dfaae73498c2ae5278d34d86148b09cd
7
- data.tar.gz: 24fb04075dddee84c31aa8a43fcbabf1973384c512837f98dd7912a7472d9bf4c6f85b24a02adf5288c083b83b43a1ab0b54de5bb508880a8caef491ba2863ca
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MTg5ODVmZTc1ZThmM2U1Y2Q1OTllMDM1MGNhMGZiNTk5ZTc0ZWIwMg==
5
+ data.tar.gz: !binary |-
6
+ MDg4MjRkMzllODdmNTIwMjE3YTk4OTlmNDgyYzdlNmIxYmEyNDY2YQ==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ MmYzM2E0YWY5MTY2ZWY0YTc3NGYwMmY0NDIxZjc4ODgzMzFmZmQyOTljNjQ5
10
+ NmNmYTZmNzJmZjkxMzMzMDgxNzU3NTE1MWZlMmU0Mjk4MTlkN2RjNDQ1NzIy
11
+ NTdlZDZjNjI5NTU3MWUxNmM5NTdlZjZiNTk4NzQ0MzNiNWVjNDY=
12
+ data.tar.gz: !binary |-
13
+ YTU3N2Y3YWM3N2I1OGMzNmE5NmI0ZDljNTgwNzRmYzQ2Nzg1YzdhM2E0MWI4
14
+ OGY5NzUzNWUyNzZkOGU2MjgzOTM2MmMzYTAyYTkxYmJjMTM0NzZlNjViMDg2
15
+ NjQ1NGUxNTI2ODFhZjVjYzk2YjNhYzg3OGYxNzMzZjczNjIzZGE=
@@ -1,15 +1,9 @@
1
- == 5.0.14 2013-03-16
2
- * Raise error on destroy when no pk is set (Manuel Kniep)
3
- * Fix bug where object == object returns false for new instances of a CPK model,
4
- even though object.equal?(object) is true (Tyler Rick)
5
- * Instead of the generic message "Number of attr_names and values do not match", give
6
- specifics that would aid in debugging (Tyler Rick)
7
- * Improve equality, ==, implmentation (Joe Goggins)
1
+ == 6.0.0 (2013-08-04)
2
+ * ActiveRecord 4.0 support (Sammy Larbi)
8
3
 
9
4
  == 5.0.13 2013-04-27
10
5
  * Batch query improvements (Jordan Byron)
11
6
  * Support nested attributes (aiasfina and Charlie Savage)
12
- * ActiveRecord 4.0 support in ar_4.0.x branch
13
7
 
14
8
  == 5.0.12 2013-01-21
15
9
  * Fix HasManyAssociation foreign_key_present? method to work with non CPK assocations (Charlie Savage)
@@ -26,7 +26,7 @@ $:.unshift(File.dirname(__FILE__)) unless
26
26
 
27
27
  unless defined?(ActiveRecord)
28
28
  require 'rubygems'
29
- gem 'activerecord', '>= 3.2.9', '~> 3.2.0'
29
+ gem 'activerecord', '4.0.0'
30
30
  require 'active_record'
31
31
  end
32
32
 
@@ -66,12 +66,12 @@ require 'active_record/validations/uniqueness'
66
66
 
67
67
 
68
68
  # CPK files
69
+ require 'composite_primary_keys/persistence'
69
70
  require 'composite_primary_keys/base'
71
+ require 'composite_primary_keys/core'
70
72
  require 'composite_primary_keys/composite_arrays'
71
73
  require 'composite_primary_keys/composite_predicates'
72
- require 'composite_primary_keys/counter_cache'
73
74
  require 'composite_primary_keys/fixtures'
74
- require 'composite_primary_keys/persistence'
75
75
  require 'composite_primary_keys/relation'
76
76
  require 'composite_primary_keys/sanitization'
77
77
  require 'composite_primary_keys/version'
@@ -4,7 +4,7 @@ module ActiveRecord
4
4
  def creation_attributes
5
5
  attributes = {}
6
6
 
7
- if reflection.macro.in?([:has_one, :has_many]) && !options[:through]
7
+ if (reflection.macro == :has_one || reflection.macro == :has_many) && !options[:through]
8
8
  # CPK
9
9
  # attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key]
10
10
  Array(reflection.foreign_key).zip(Array(reflection.active_record_primary_key)).each do |key1, key2|
@@ -25,7 +25,7 @@ module ActiveRecord
25
25
 
26
26
  if reflection.source_macro == :belongs_to
27
27
  if reflection.options[:polymorphic]
28
- key = reflection.association_primary_key(klass)
28
+ key = reflection.association_primary_key(self.klass)
29
29
  else
30
30
  key = reflection.association_primary_key
31
31
  end
@@ -36,8 +36,7 @@ module ActiveRecord
36
36
  foreign_key = reflection.active_record_primary_key
37
37
  end
38
38
 
39
- conditions = self.conditions[i]
40
-
39
+
41
40
  if reflection == chain.last
42
41
  # CPK
43
42
  # scope = scope.where(table[key].eq(owner[foreign_key]))
@@ -47,14 +46,6 @@ module ActiveRecord
47
46
  if reflection.type
48
47
  scope = scope.where(table[reflection.type].eq(owner.class.base_class.name))
49
48
  end
50
-
51
- conditions.each do |condition|
52
- if options[:through] && condition.is_a?(Hash)
53
- condition = { table.name => condition }
54
- end
55
-
56
- scope = scope.where(interpolate(condition))
57
- end
58
49
  else
59
50
  # CPK
60
51
  # constraint = table[key].eq(foreign_table[foreign_key])
@@ -66,10 +57,18 @@ module ActiveRecord
66
57
  end
67
58
 
68
59
  scope = scope.joins(join(foreign_table, constraint))
60
+ end
61
+
62
+ scope_chain[i].each do |scope_chain_item|
63
+ klass = i == 0 ? self.klass : reflection.klass
64
+ item = eval_scope(klass, scope_chain_item)
69
65
 
70
- unless conditions.empty?
71
- scope = scope.where(sanitize(conditions, table))
66
+ if scope_chain_item == self.reflection.scope
67
+ scope.merge! item.except(:where, :includes)
72
68
  end
69
+
70
+ scope.includes! item.includes_values
71
+ scope.where_values += item.where_values
73
72
  end
74
73
  end
75
74
 
@@ -11,7 +11,7 @@ module ActiveRecord
11
11
  end
12
12
 
13
13
  if options[:insert_sql]
14
- owner.connection.insert(interpolate(options[:insert_sql], record))
14
+ owner.class.connection.insert(interpolate(options[:insert_sql], record))
15
15
  else
16
16
  # CPK
17
17
  #stmt = join_table.compile_insert(
@@ -31,7 +31,7 @@ module ActiveRecord
31
31
 
32
32
  stmt = join_table.compile_insert(join_values)
33
33
 
34
- owner.connection.insert stmt.to_sql
34
+ owner.class.connection.insert stmt.to_sql
35
35
  end
36
36
 
37
37
  record
@@ -39,7 +39,7 @@ module ActiveRecord
39
39
 
40
40
  def delete_records(records, method)
41
41
  if sql = options[:delete_sql]
42
- records.each { |record| owner.connection.delete(interpolate(sql, record)) }
42
+ records.each { |record| owner.class.connection.delete(interpolate(sql, record)) }
43
43
  else
44
44
  relation = join_table
45
45
  # CPK
@@ -51,7 +51,7 @@ module ActiveRecord
51
51
  predicate2 = cpk_in_predicate(relation, Array(reflection.association_foreign_key), records.map { |x| x.id }) unless records == :all
52
52
  stmt = relation.where(predicate1.and(predicate2)).compile_delete
53
53
 
54
- owner.connection.delete stmt.to_sql
54
+ owner.class.connection.delete stmt.to_sql
55
55
  end
56
56
  end
57
57
  end
@@ -8,7 +8,7 @@ module ActiveRecord
8
8
  else
9
9
  # CPK
10
10
  # keys = records.map { |r| r[reflection.association_primary_key] }
11
- # scope = scoped.where(reflection.association_primary_key => keys)
11
+ # scope = scope.where(reflection.association_primary_key => keys)
12
12
  table = Arel::Table.new(reflection.table_name)
13
13
  and_conditions = records.map do |record|
14
14
  eq_conditions = Array(reflection.association_primary_key).map do |name|
@@ -22,7 +22,7 @@ module ActiveRecord
22
22
  condition = condition.or(and_condition)
23
23
  end
24
24
 
25
- scope = scoped.where(condition)
25
+ scope = scope.where(condition)
26
26
 
27
27
  if method == :delete_all
28
28
  update_counter(-scope.delete_all)
@@ -18,7 +18,7 @@ module ActiveRecord
18
18
  parent
19
19
  }.uniq
20
20
 
21
- remove_duplicate_results!(active_record, records, @associations)
21
+ remove_duplicate_results!(base_klass, records, @associations)
22
22
  records
23
23
  end
24
24
 
@@ -6,7 +6,7 @@ module ActiveRecord
6
6
  # CPK
7
7
  # "#{aliased_prefix}_r0"
8
8
 
9
- active_record.composite? ?
9
+ base_klass.composite? ?
10
10
  primary_key.inject([]) {|aliased_keys, key| aliased_keys << "#{ aliased_prefix }_r#{aliased_keys.length}"} :
11
11
  "#{ aliased_prefix }_r0"
12
12
  end
@@ -14,7 +14,7 @@ module ActiveRecord
14
14
  def record_id(row)
15
15
  # CPK
16
16
  # row[aliased_primary_key]
17
- active_record.composite? ?
17
+ base_klass.composite? ?
18
18
  aliased_primary_key.map {|key| row[key]}.to_composite_keys :
19
19
  row[aliased_primary_key]
20
20
  end
@@ -25,7 +25,7 @@ module ActiveRecord
25
25
 
26
26
  # CPK
27
27
  #([primary_key] + (column_names - [primary_key])).each_with_index do |column_name, i|
28
- keys = active_record.composite? ? primary_key.map(&:to_s) : [primary_key]
28
+ keys = base_klass.composite? ? primary_key.map(&:to_s) : [primary_key]
29
29
 
30
30
  (keys + (column_names - keys)).each_with_index do |column_name, i|
31
31
  @column_names_with_alias << [column_name, "#{aliased_prefix}_r#{i}"]
@@ -4,9 +4,9 @@ module ActiveRecord
4
4
  class Association
5
5
  def records_for(ids)
6
6
  # CPK
7
- # scoped.where(association_key.in(ids))
7
+ # scope.where(association_key.in(ids))
8
8
  predicate = cpk_in_predicate(table, reflection.foreign_key, ids)
9
- scoped.where(predicate)
9
+ scope.where(predicate)
10
10
  end
11
11
 
12
12
  def associated_records_by_owner
@@ -5,7 +5,7 @@ module ActiveRecord
5
5
  def records_for(ids)
6
6
  # CPK
7
7
  predicate = cpk_in_predicate(table, association_key_name, ids)
8
- scoped.where(predicate)
8
+ scope.where(predicate)
9
9
  end
10
10
  end
11
11
  end
@@ -4,9 +4,9 @@ module ActiveRecord
4
4
  class HasAndBelongsToMany
5
5
  def records_for(ids)
6
6
  # CPK
7
- #scope = super
7
+ # scope = super
8
8
  predicate = cpk_in_predicate(join_table, reflection.foreign_key, ids)
9
- scope = scoped.where(predicate)
9
+ scope = build_scope.where(predicate)
10
10
 
11
11
  klass.connection.select_all(scope.arel.to_sql, 'SQL', scope.bind_values)
12
12
  end
@@ -16,8 +16,6 @@ module ActiveRecord
16
16
  @changed_attributes.delete(attr) unless _field_changed?(attr, old, value)
17
17
  else
18
18
  old = clone_attribute_value(:read_attribute, attr)
19
- # Save Time objects as TimeWithZone if time_zone_aware_attributes == true
20
- old = old.in_time_zone if clone_with_time_zone_conversion_attribute?(attr, old)
21
19
  @changed_attributes[attr] = old if _field_changed?(attr, old, value)
22
20
  end
23
21
  end
@@ -25,12 +25,12 @@ module ActiveRecord
25
25
  end
26
26
  end
27
27
 
28
- def read_attribute(attr_name)
29
- # CPK
28
+ rails_read_attribute = instance_method(:read_attribute)
29
+ define_method(:read_attribute) do |attr_name|
30
30
  if attr_name.kind_of?(Array)
31
31
  attr_name.map {|name| read_attribute(name)}.to_composite_keys
32
32
  else
33
- self.class.type_cast_attribute(attr_name, @attributes, @attributes_cache)
33
+ rails_read_attribute.bind(self).(attr_name)
34
34
  end
35
35
  end
36
36
  end
@@ -3,6 +3,8 @@ module ActiveRecord
3
3
  end
4
4
 
5
5
  class Base
6
+ include CompositePrimaryKeys::ActiveRecord::Persistence
7
+
6
8
  INVALID_FOR_COMPOSITE_KEYS = 'Not appropriate for composite primary keys'
7
9
  NOT_IMPLEMENTED_YET = 'Not implemented for composite primary keys yet'
8
10
 
@@ -57,32 +59,6 @@ module ActiveRecord
57
59
  self.class.composite?
58
60
  end
59
61
 
60
- def initialize_dup(other)
61
- cloned_attributes = other.clone_attributes(:read_attribute_before_type_cast)
62
- self.class.initialize_attributes(cloned_attributes, :serialized => false)
63
- # CPK
64
- # cloned_attributes.delete(self.class.primary_key)
65
- Array(self.class.primary_key).each {|key| cloned_attributes.delete(key.to_s)}
66
-
67
- @attributes = cloned_attributes
68
-
69
- _run_after_initialize_callbacks if respond_to?(:_run_after_initialize_callbacks)
70
-
71
- @changed_attributes = {}
72
- self.class.column_defaults.each do |attr, orig_value|
73
- @changed_attributes[attr] = orig_value if _field_changed?(attr, orig_value, @attributes[attr])
74
- end
75
-
76
- @aggregation_cache = {}
77
- @association_cache = {}
78
- @attributes_cache = {}
79
- @new_record = true
80
-
81
- ensure_proper_type
82
- populate_with_current_scope_attributes
83
- super
84
- end
85
-
86
62
  module CompositeClassMethods
87
63
  def primary_key
88
64
  primary_keys
@@ -137,7 +113,7 @@ module ActiveRecord
137
113
 
138
114
  def ==(comparison_object)
139
115
  return true if equal? comparison_object
140
- ids.is_a?(Array) ? super(comparison_object) && ids.all? {|id| !id.nil?} : super(comparison_object)
116
+ ids.is_a?(Array) ? super(comparison_object) && ids.all? {|id| id.present?} : super(comparison_object)
141
117
  end
142
118
 
143
119
  def can_change_primary_key_values?
@@ -7,7 +7,7 @@ module ActiveRecord
7
7
  end
8
8
 
9
9
  def self.establish_connection(spec = ENV["DATABASE_URL"])
10
- resolver = ConnectionSpecification::Resolver.new spec, configurations
10
+ resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new spec, configurations
11
11
  spec = resolver.spec
12
12
 
13
13
  # CPK
@@ -18,7 +18,7 @@ module ActiveRecord
18
18
  end
19
19
 
20
20
  remove_connection
21
- connection_handler.establish_connection name, spec
21
+ connection_handler.establish_connection self, spec
22
22
  end
23
23
 
24
24
  class << self
@@ -0,0 +1,28 @@
1
+ module ActiveRecord
2
+ module Core
3
+ def initialize_dup(other)
4
+ cloned_attributes = other.clone_attributes(:read_attribute_before_type_cast)
5
+ self.class.initialize_attributes(cloned_attributes, :serialized => false)
6
+ # CPK
7
+ # cloned_attributes.delete(self.class.primary_key)
8
+ Array(self.class.primary_key).each {|key| cloned_attributes.delete(key.to_s)}
9
+ @attributes = cloned_attributes
10
+
11
+ run_callbacks(:initialize) unless _initialize_callbacks.empty?
12
+
13
+ @changed_attributes = {}
14
+ self.class.column_defaults.each do |attr, orig_value|
15
+ @changed_attributes[attr] = orig_value if _field_changed?(attr, orig_value, @attributes[attr])
16
+ end
17
+
18
+ @aggregation_cache = {}
19
+ @association_cache = {}
20
+ @attributes_cache = {}
21
+
22
+ @new_record = true
23
+
24
+ ensure_proper_type
25
+ super
26
+ end
27
+ end
28
+ end
@@ -1,15 +1,9 @@
1
- module ActiveRecord
2
- module Persistence
3
- def destroy
4
- destroy_associations
5
-
6
- if persisted?
7
- IdentityMap.remove(self) if IdentityMap.enabled?
8
- # CPK
9
- #pk = self.class.primary_key
10
- #column = self.class.columns_hash[pk]
11
- #substitute = connection.substitute_at(column, 0)
12
-
1
+ module CompositePrimaryKeys
2
+ module ActiveRecord
3
+ module Persistence
4
+ def relation_for_destroy
5
+ return super unless composite?
6
+
13
7
  where_hash = {}
14
8
  primary_keys = Array(self.class.primary_key)
15
9
 
@@ -17,59 +11,47 @@ module ActiveRecord
17
11
  raise ActiveRecord::CompositeKeyError, "No primary key(s) defined for #{self.class.name}"
18
12
  end
19
13
 
20
- #relation = self.class.unscoped.where(
21
- # self.class.arel_table[pk].eq(substitute))
22
-
23
14
  primary_keys.each do |key|
24
15
  where_hash[key.to_s] = self[key]
25
16
  end
26
17
 
27
- # CPK
28
- #relation.bind_values = [[column, id]]
29
-
30
18
  relation = self.class.unscoped.where(where_hash)
31
- relation.delete_all
32
19
  end
20
+
33
21
 
34
- @destroyed = true
35
- freeze
36
- end
37
-
38
- def touch(name = nil)
39
- attributes = timestamp_attributes_for_update_in_model
40
- attributes << name if name
22
+ def touch(name = nil)
23
+ attributes = timestamp_attributes_for_update_in_model
24
+ attributes << name if name
41
25
 
42
- unless attributes.empty?
43
- current_time = current_time_from_proper_timezone
44
- changes = {}
26
+ unless attributes.empty?
27
+ current_time = current_time_from_proper_timezone
28
+ changes = {}
45
29
 
46
- attributes.each do |column|
47
- column = column.to_s
48
- changes[column] = write_attribute(column, current_time)
49
- end
30
+ attributes.each do |column|
31
+ column = column.to_s
32
+ changes[column] = write_attribute(column, current_time)
33
+ end
50
34
 
51
- changes[self.class.locking_column] = increment_lock if locking_enabled?
35
+ changes[self.class.locking_column] = increment_lock if locking_enabled?
52
36
 
53
- @changed_attributes.except!(*changes.keys)
37
+ @changed_attributes.except!(*changes.keys)
54
38
 
55
- relation = self.class.send(:relation)
56
- arel_table = self.class.arel_table
57
- primary_key = self.class.primary_key
39
+ relation = self.class.send(:relation)
40
+ arel_table = self.class.arel_table
41
+ primary_key = self.class.primary_key
58
42
 
59
- primary_key_predicate = relation.cpk_id_predicate(arel_table, Array(primary_key), Array(id))
43
+ primary_key_predicate = relation.cpk_id_predicate(arel_table, Array(primary_key), Array(id))
60
44
 
61
- self.class.unscoped.where(primary_key_predicate).update_all(changes) == 1
45
+ self.class.unscoped.where(primary_key_predicate).update_all(changes) == 1
46
+ end
62
47
  end
63
- end
64
48
 
65
- def update(attribute_names = @attributes.keys)
66
- klass = self.class
67
- if !self.composite?
68
- attributes_with_values = arel_attributes_values(false, false, attribute_names)
69
- return 0 if attributes_with_values.empty?
70
- stmt = klass.unscoped.where(klass.arel_table[klass.primary_key].eq(id)).arel.compile_update(attributes_with_values)
71
- else
72
- attributes_with_values = arel_attributes_values(can_change_primary_key?, false, attribute_names)
49
+ def update_record(attribute_names = @attributes.keys)
50
+ return super(attribute_names) unless composite?
51
+
52
+ klass = self.class
53
+
54
+ attributes_with_values = arel_attributes_with_values_for_update(attribute_names)
73
55
  return 0 if attributes_with_values.empty?
74
56
 
75
57
  if !can_change_primary_key? and primary_key_changed?
@@ -79,8 +61,9 @@ module ActiveRecord
79
61
  else
80
62
  stmt = klass.unscoped.where(ids_hash).arel.compile_update(attributes_with_values)
81
63
  end
64
+
65
+ klass.connection.update stmt.to_sql
82
66
  end
83
- klass.connection.update stmt.to_sql
84
67
  end
85
68
  end
86
69
  end