composite_primary_keys 5.0.14 → 6.0.0

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