torque-postgresql 1.1.5 → 2.0.3

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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/lib/torque/postgresql.rb +0 -2
  3. data/lib/torque/postgresql/adapter.rb +0 -1
  4. data/lib/torque/postgresql/adapter/database_statements.rb +4 -15
  5. data/lib/torque/postgresql/adapter/schema_creation.rb +13 -23
  6. data/lib/torque/postgresql/adapter/schema_definitions.rb +7 -21
  7. data/lib/torque/postgresql/adapter/schema_dumper.rb +74 -11
  8. data/lib/torque/postgresql/adapter/schema_statements.rb +2 -12
  9. data/lib/torque/postgresql/associations.rb +0 -3
  10. data/lib/torque/postgresql/associations/association_scope.rb +18 -60
  11. data/lib/torque/postgresql/associations/belongs_to_many_association.rb +16 -11
  12. data/lib/torque/postgresql/associations/preloader.rb +0 -24
  13. data/lib/torque/postgresql/associations/preloader/association.rb +13 -9
  14. data/lib/torque/postgresql/autosave_association.rb +4 -4
  15. data/lib/torque/postgresql/auxiliary_statement.rb +1 -13
  16. data/lib/torque/postgresql/coder.rb +1 -2
  17. data/lib/torque/postgresql/config.rb +0 -4
  18. data/lib/torque/postgresql/inheritance.rb +13 -17
  19. data/lib/torque/postgresql/reflection/abstract_reflection.rb +19 -25
  20. data/lib/torque/postgresql/reflection/belongs_to_many_reflection.rb +16 -4
  21. data/lib/torque/postgresql/relation.rb +11 -16
  22. data/lib/torque/postgresql/relation/auxiliary_statement.rb +2 -8
  23. data/lib/torque/postgresql/relation/distinct_on.rb +1 -1
  24. data/lib/torque/postgresql/version.rb +1 -1
  25. data/spec/en.yml +19 -0
  26. data/spec/factories/authors.rb +6 -0
  27. data/spec/factories/comments.rb +13 -0
  28. data/spec/factories/posts.rb +6 -0
  29. data/spec/factories/tags.rb +5 -0
  30. data/spec/factories/texts.rb +5 -0
  31. data/spec/factories/users.rb +6 -0
  32. data/spec/factories/videos.rb +5 -0
  33. data/spec/mocks/cache_query.rb +16 -0
  34. data/spec/mocks/create_table.rb +35 -0
  35. data/spec/models/activity.rb +3 -0
  36. data/spec/models/activity_book.rb +4 -0
  37. data/spec/models/activity_post.rb +7 -0
  38. data/spec/models/activity_post/sample.rb +4 -0
  39. data/spec/models/author.rb +4 -0
  40. data/spec/models/author_journalist.rb +4 -0
  41. data/spec/models/comment.rb +3 -0
  42. data/spec/models/course.rb +2 -0
  43. data/spec/models/geometry.rb +2 -0
  44. data/spec/models/guest_comment.rb +4 -0
  45. data/spec/models/post.rb +6 -0
  46. data/spec/models/tag.rb +2 -0
  47. data/spec/models/text.rb +2 -0
  48. data/spec/models/time_keeper.rb +2 -0
  49. data/spec/models/user.rb +8 -0
  50. data/spec/models/video.rb +2 -0
  51. data/spec/schema.rb +141 -0
  52. data/spec/spec_helper.rb +59 -0
  53. data/spec/tests/arel_spec.rb +72 -0
  54. data/spec/tests/auxiliary_statement_spec.rb +593 -0
  55. data/spec/tests/belongs_to_many_spec.rb +246 -0
  56. data/spec/tests/coder_spec.rb +367 -0
  57. data/spec/tests/collector_spec.rb +59 -0
  58. data/spec/tests/distinct_on_spec.rb +65 -0
  59. data/spec/tests/enum_set_spec.rb +306 -0
  60. data/spec/tests/enum_spec.rb +628 -0
  61. data/spec/tests/geometric_builder_spec.rb +221 -0
  62. data/spec/tests/has_many_spec.rb +400 -0
  63. data/spec/tests/interval_spec.rb +167 -0
  64. data/spec/tests/lazy_spec.rb +24 -0
  65. data/spec/tests/period_spec.rb +954 -0
  66. data/spec/tests/quoting_spec.rb +24 -0
  67. data/spec/tests/range_spec.rb +36 -0
  68. data/spec/tests/relation_spec.rb +57 -0
  69. data/spec/tests/table_inheritance_spec.rb +416 -0
  70. metadata +102 -14
  71. data/lib/torque/postgresql/associations/join_dependency/join_association.rb +0 -15
  72. data/lib/torque/postgresql/schema_dumper.rb +0 -88
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 91a42a9a04ba195e57f4b87af2931a6ecf82e9d58a4acec84b95350404ee4977
4
- data.tar.gz: e4fce1b312a40bf6e98a1f8bee8351795a45a5afddf25ce0f7765cd6c01d89ec
3
+ metadata.gz: 9e426686cf04fcf990d84b945abe3b3435168237f1ff24c6f23ac3b4941bbc4e
4
+ data.tar.gz: 2f936f5676f80804e4766bc9bf64b81d70ddbd08e9409b373b0d59d7d20e8bf1
5
5
  SHA512:
6
- metadata.gz: 56a370889f5ffbb09a2c414bd1a9c4311d4d415675fd8ac7f00a09ffb4b2aa4b70998b475f6ab494ad06f0e0b9783ddea599268f04d0c5d3184b9e1d0d644d44
7
- data.tar.gz: 7341f28b3805af398868be6a4095c9dcf4b9e7d6be28a0ce4e2af0340004490e2e75b9eb6e7e63f9d6ac0bba1caf5fdb7154cd5b8d7928c6c093f748cda96d71
6
+ metadata.gz: 373d085090e02e76eb2523f7c2d5a32434c002f712cf892aa38f81bc9935a51f2426054c97bb5df534c47e23fd1800d84b670b9443266908e2f076f20928e7a2
7
+ data.tar.gz: f0441cc66de2ed015d0b8dbb13ae88dc4074a54c8477fc7a31fc1d51e2bfd7cb57ab0e3de529dcbd4feb3fa72dd1fc8894738868e8bfa36ad9490badc3d1c990
@@ -6,7 +6,6 @@ require 'active_support'
6
6
 
7
7
  require 'active_support/core_ext/date/acts_like'
8
8
  require 'active_support/core_ext/time/zones'
9
- require 'active_support/core_ext/hash/compact'
10
9
  require 'active_record/connection_adapters/postgresql_adapter'
11
10
 
12
11
  require 'torque/postgresql/config'
@@ -28,6 +27,5 @@ require 'torque/postgresql/migration'
28
27
  require 'torque/postgresql/relation'
29
28
  require 'torque/postgresql/reflection'
30
29
  require 'torque/postgresql/schema_cache'
31
- require 'torque/postgresql/schema_dumper'
32
30
 
33
31
  require 'torque/postgresql/railtie' if defined?(Rails)
@@ -10,7 +10,6 @@ module Torque
10
10
  module PostgreSQL
11
11
  module Adapter
12
12
  include Quoting
13
- include ColumnDumper unless Torque::PostgreSQL::AR521
14
13
  include DatabaseStatements
15
14
  include SchemaStatements
16
15
 
@@ -43,16 +43,9 @@ module Torque
43
43
  end
44
44
 
45
45
  # :nodoc:
46
- if Torque::PostgreSQL::AR521
47
- def load_additional_types(oids = nil)
48
- super
49
- torque_load_additional_types(oids)
50
- end
51
- else
52
- def load_additional_types(type_map, oids = nil)
53
- super
54
- torque_load_additional_types(oids)
55
- end
46
+ def load_additional_types(oids = nil)
47
+ super
48
+ torque_load_additional_types(oids)
56
49
  end
57
50
 
58
51
  # Add the composite types to be loaded too.
@@ -80,11 +73,7 @@ module Torque
80
73
  SQL
81
74
 
82
75
  execute_and_clear(query, 'SCHEMA', []) do |records|
83
- records.each do |row|
84
- case row['typtype']
85
- when 'e' then OID::Enum.create(row, type_map)
86
- end
87
- end
76
+ records.each { |row| OID::Enum.create(row, type_map) }
88
77
  end
89
78
  end
90
79
 
@@ -5,10 +5,11 @@ module Torque
5
5
 
6
6
  # Redefine original table creation command to ensure PostgreSQL standard
7
7
  def visit_TableDefinition(o)
8
- create_sql = "CREATE#{' TEMPORARY' if o.temporary}"
9
- create_sql << " TABLE #{quote_table_name(o.name)}"
8
+ create_sql = +"CREATE#{table_modifier_in_create(o)} TABLE "
9
+ create_sql << "IF NOT EXISTS " if o.if_not_exists
10
+ create_sql << "#{quote_table_name(o.name)} "
10
11
 
11
- statements = o.columns.map{ |c| accept c }
12
+ statements = o.columns.map { |c| accept c }
12
13
  statements << accept(o.primary_keys) if o.primary_keys
13
14
 
14
15
  if supports_indexes_in_create?
@@ -17,36 +18,25 @@ module Torque
17
18
  end)
18
19
  end
19
20
 
20
- if supports_foreign_keys_in_create?
21
+ if supports_foreign_keys?
21
22
  statements.concat(o.foreign_keys.map do |to_table, options|
22
23
  foreign_key_in_create(o.name, to_table, options)
23
24
  end)
24
25
  end
25
26
 
26
- if o.as
27
- create_sql << " AS #{@conn.to_sql(o.as)}"
28
- else
29
- create_sql << " (#{statements.join(', ')})"
30
- add_table_options!(create_sql, table_options(o))
27
+ create_sql << "(#{statements.join(', ')})" \
28
+ if statements.present? || o.inherits.present?
31
29
 
32
- if o.inherits.present?
33
- tables = o.inherits.map(&method(:quote_table_name))
34
- create_sql << " INHERITS ( #{tables.join(' , ')} )"
35
- end
30
+ add_table_options!(create_sql, table_options(o))
31
+
32
+ if o.inherits.present?
33
+ tables = o.inherits.map(&method(:quote_table_name))
34
+ create_sql << " INHERITS ( #{tables.join(' , ')} )"
36
35
  end
37
36
 
37
+ create_sql << " AS #{to_sql(o.as)}" if o.as
38
38
  create_sql
39
39
  end
40
-
41
- # Keep rails 5.0 and 5.1 compatibility
42
- def supports_foreign_keys_in_create?
43
- if defined?(super)
44
- super
45
- else
46
- supports_foreign_keys?
47
- end
48
- end
49
-
50
40
  end
51
41
 
52
42
  ActiveRecord::ConnectionAdapters::PostgreSQL::SchemaCreation.prepend SchemaCreation
@@ -7,17 +7,15 @@ module Torque
7
7
  # dates to be stored without having to store a seconds-based integer
8
8
  # or any sort of other approach
9
9
  def interval(*args, **options)
10
- args.each { |name| column(name, :interval, options) }
10
+ args.each { |name| column(name, :interval, **options) }
11
11
  end
12
12
 
13
13
  # Creates a column with an enum type, needing to specify the subtype,
14
14
  # which is basically the name of the type defined prior creating the
15
15
  # column
16
16
  def enum(*args, **options)
17
- args.each do |name|
18
- type = options.fetch(:subtype, name)
19
- column(name, type, options)
20
- end
17
+ subtype = options.delete(:subtype)
18
+ args.each { |name| column(name, (subtype || name), **options) }
21
19
  end
22
20
 
23
21
  # Creates a column with an enum array type, needing to specify the
@@ -34,23 +32,11 @@ module Torque
34
32
 
35
33
  attr_reader :inherits
36
34
 
37
- def initialize(name, *_, **options)
38
- old_args = []
39
- old_args << options.delete(:temporary) || false
40
- old_args << options.delete(:options)
41
- old_args << options.delete(:as)
42
- comment = options.delete(:comment)
35
+ def initialize(*args, **options)
36
+ super
43
37
 
44
- super(name, *old_args, comment: comment)
45
-
46
- if options.key?(:inherits)
47
- @inherits = Array[options.delete(:inherits)].flatten.compact
48
- @inherited_id = !(options.key?(:primary_key) || options.key?(:id))
49
- end
50
- end
51
-
52
- def inherited_id?
53
- @inherited_id
38
+ @inherits = Array.wrap(options.delete(:inherits)).flatten.compact \
39
+ if options.key?(:inherits)
54
40
  end
55
41
  end
56
42
 
@@ -1,22 +1,23 @@
1
1
  module Torque
2
2
  module PostgreSQL
3
3
  module Adapter
4
- module ColumnDumper
4
+ module SchemaDumper
5
+ def dump(stream) # :nodoc:
6
+ @connection.dump_mode!
7
+ super
5
8
 
6
- # Adds +:subtype+ as a valid migration key
7
- unless Torque::PostgreSQL::AR521
8
- def migration_keys
9
- super + [:subtype]
10
- end
9
+ @connection.dump_mode!
10
+ stream
11
+ end
12
+
13
+ def extensions(stream) # :nodoc:
14
+ super
15
+ user_defined_types(stream)
11
16
  end
12
17
 
13
18
  # Translate +:enum_set+ into +:enum+
14
19
  def schema_type(column)
15
- if column.type == :enum_set
16
- :enum
17
- else
18
- super
19
- end
20
+ column.type == :enum_set ? :enum : super
20
21
  end
21
22
 
22
23
  # Adds +:subtype+ option to the default set
@@ -36,7 +37,69 @@ module Torque
36
37
  column.sql_type.to_sym.inspect if column.type == :enum || column.type == :enum_set
37
38
  end
38
39
 
40
+ def tables(stream) # :nodoc:
41
+ inherited_tables = @connection.inherited_tables
42
+ sorted_tables = @connection.data_sources.sort - @connection.views
43
+
44
+ stream.puts " # These are the common tables managed"
45
+ (sorted_tables - inherited_tables.keys).each do |table_name|
46
+ table(table_name, stream) unless ignored?(table_name)
47
+ end
48
+
49
+ if inherited_tables.present?
50
+ stream.puts " # These are tables that has inheritance"
51
+ inherited_tables.each do |table_name, inherits|
52
+ next if ignored?(table_name)
53
+
54
+ sub_stream = StringIO.new
55
+ table(table_name, sub_stream)
56
+
57
+ # Add the inherits setting
58
+ sub_stream.rewind
59
+ inherits.map!(&:to_sym)
60
+ inherits = inherits.first if inherits.size === 1
61
+ inherits = ", inherits: #{inherits.inspect} do |t|"
62
+ table_dump = sub_stream.read.gsub(/ do \|t\|$/, inherits)
63
+
64
+ # Ensure bodyless definitions
65
+ table_dump.gsub!(/do \|t\|\n end/, '')
66
+ stream.print table_dump
67
+ end
68
+ end
69
+
70
+ # Dump foreign keys at the end to make sure all dependent tables exist.
71
+ if @connection.supports_foreign_keys?
72
+ sorted_tables.each do |tbl|
73
+ foreign_keys(tbl, stream) unless ignored?(tbl)
74
+ end
75
+ end
76
+
77
+ # Scenic integration
78
+ views(stream) if defined?(::Scenic)
79
+ end
80
+
81
+ # Dump user defined types like enum
82
+ def user_defined_types(stream)
83
+ types = @connection.user_defined_types('e')
84
+ return unless types.any?
85
+
86
+ stream.puts " # These are user-defined types used on this database"
87
+ types.sort_by(&:first).each { |(name, type)| send(type.to_sym, name, stream) }
88
+ stream.puts
89
+ rescue => e
90
+ stream.puts "# Could not dump user-defined types because of following #{e.class}"
91
+ stream.puts "# #{e.message}"
92
+ stream.puts
93
+ end
94
+
95
+ # Dump enum custom type
96
+ def enum(name, stream)
97
+ values = @connection.enum_values(name).map { |v| "\"#{v}\"" }
98
+ stream.puts " create_enum \"#{name}\", [#{values.join(', ')}], force: :cascade"
99
+ end
39
100
  end
101
+
102
+ ActiveRecord::ConnectionAdapters::PostgreSQL::SchemaDumper.prepend SchemaDumper
40
103
  end
41
104
  end
42
105
  end
@@ -73,24 +73,14 @@ module Torque
73
73
 
74
74
  # Rewrite the method that creates tables to easily accept extra options
75
75
  def create_table(table_name, **options, &block)
76
- td = create_table_definition(table_name, **options)
77
- options[:id] = false if td.inherited_id?
78
- options[:temporary] = td
76
+ options[:id] = false if options[:inherits].present? &&
77
+ options[:primary_key].blank? && options[:id].blank?
79
78
 
80
79
  super table_name, **options, &block
81
80
  end
82
81
 
83
82
  private
84
83
 
85
- # This waits for the second call to really return the table definition
86
- def create_table_definition(*args, **options) # :nodoc:
87
- if !args.second.kind_of?(TableDefinition)
88
- TableDefinition.new(*args, **options)
89
- else
90
- args.second
91
- end
92
- end
93
-
94
84
  def quote_enum_values(name, values, options)
95
85
  prefix = options[:prefix]
96
86
  prefix = name if prefix === true
@@ -3,6 +3,3 @@ require_relative 'associations/association_scope'
3
3
  require_relative 'associations/belongs_to_many_association'
4
4
  require_relative 'associations/builder'
5
5
  require_relative 'associations/preloader'
6
-
7
- require_relative 'associations/join_dependency/join_association' \
8
- unless Torque::PostgreSQL::AR521
@@ -14,63 +14,40 @@ module Torque
14
14
  # When the relation is connected through an array, intercept the
15
15
  # condition builder and uses an overlap condition building it on
16
16
  # +build_id_constraint+
17
- def last_chain_scope(scope, *args)
18
- # 5.0 table, reflection, owner, association_klass
19
- # 5.1 table, reflection, owner
20
- # 5.2 reflection, owner
21
-
22
- reflection = args.size.eql?(2) ? args[0] : args[1]
17
+ def last_chain_scope(scope, reflection, owner)
23
18
  return super unless reflection.connected_through_array?
24
19
 
25
- table = args[0] if args.size > 2
26
- keys = args.size.eql?(4) ? reflection.join_keys(args[3]) : reflection.join_keys
27
- owner = args.size.eql?(2) ? args[1] : args[2]
28
-
20
+ keys = reflection.join_keys
29
21
  value = transform_value(owner[keys.foreign_key])
30
- constraint, binds = build_id_constraint(reflection, keys, value, table, true)
22
+ constraint = build_id_constraint(reflection, keys, value, true)
31
23
 
32
- if Torque::PostgreSQL::AR521
33
- scope.where!(constraint)
34
- else
35
- klass = ::ActiveRecord::Relation::WhereClause
36
- scope.where_clause += klass.new([constraint], binds)
37
- scope
38
- end
24
+ scope.where!(constraint)
39
25
  end
40
26
 
41
27
  # When the relation is connected through an array, intercept the
42
28
  # condition builder and uses an overlap condition building it on
43
29
  # +build_id_constraint+
44
- def next_chain_scope(scope, *args)
45
- # 5.0 table, reflection, association_klass, foreign_table, next_reflection
46
- # 5.1 table, reflection, foreign_table, next_reflection
47
- # 5.2 reflection, next_reflection
48
-
49
- reflection = args.size.eql?(2) ? args[0] : args[1]
30
+ def next_chain_scope(scope, reflection, next_reflection)
50
31
  return super unless reflection.connected_through_array?
51
32
 
52
- table = args[0] if args.size > 2
53
- next_reflection = args[-1]
54
-
55
- foreign_table = args[-2] if args.size.eql?(5)
56
- foreign_table ||= next_reflection.aliased_table
57
-
58
- keys = args.size.eql?(5) ? reflection.join_keys(args[2]) : reflection.join_keys
33
+ keys = reflection.join_keys
34
+ foreign_table = next_reflection.aliased_table
59
35
 
60
36
  value = foreign_table[keys.foreign_key]
61
- constraint, *_ = build_id_constraint(reflection, keys, value, table)
37
+ constraint = build_id_constraint(reflection, keys, value)
62
38
 
63
39
  scope.joins!(join(foreign_table, constraint))
64
40
  end
65
41
 
66
42
  # Trigger the same method on the relation which will build the
67
43
  # constraint condition using array logics
68
- def build_id_constraint(reflection, keys, value, table = nil, bind_param = false)
69
- table ||= reflection.aliased_table
70
- value, binds = build_binds_for_constraint(reflection, value, keys.foreign_key) \
71
- if bind_param
44
+ def build_id_constraint(reflection, keys, value, bind_param = false)
45
+ table = reflection.aliased_table
46
+ value = Array.wrap(value).map do |value|
47
+ build_bind_param_for_constraint(reflection, value, keys.foreign_key)
48
+ end if bind_param
72
49
 
73
- [reflection.build_id_constraint(table[keys.key], value), binds]
50
+ reflection.build_id_constraint(table[keys.key], value)
74
51
  end
75
52
 
76
53
  # For array-like values, it needs to call the method as many times as
@@ -83,30 +60,11 @@ module Torque
83
60
  end
84
61
  end
85
62
 
86
- # When binds are necessary for a constraint, instantiate them
87
- if Torque::PostgreSQL::AR521
88
- def build_binds_for_constraint(reflection, values, foreign_key)
89
- result = Array.wrap(values).map do |value|
90
- ::Arel::Nodes::BindParam.new(::ActiveRecord::Relation::QueryAttribute.new(
91
- foreign_key, value, reflection.klass.attribute_types[foreign_key],
92
- ))
93
- end
94
-
95
- [result, nil]
96
- end
97
- else
98
- def build_binds_for_constraint(reflection, values, foreign_key)
99
- type = reflection.klass.attribute_types[foreign_key]
100
- parts = Array.wrap(values).map do |value|
101
- bind = ::Arel::Nodes::BindParam.new
102
- value = ::ActiveRecord::Relation::QueryAttribute.new(foreign_key, value, type)
103
- [bind, value]
104
- end.to_h
105
-
106
- [parts.keys, parts.values]
107
- end
63
+ def build_bind_param_for_constraint(reflection, value, foreign_key)
64
+ ::Arel::Nodes::BindParam.new(::ActiveRecord::Relation::QueryAttribute.new(
65
+ foreign_key, value, reflection.klass.attribute_types[foreign_key],
66
+ ))
108
67
  end
109
-
110
68
  end
111
69
 
112
70
  ::ActiveRecord::Associations::AssociationScope.singleton_class.prepend(AssociationScope::ClassMethods)
@@ -28,20 +28,21 @@ module Torque
28
28
  end
29
29
 
30
30
  def ids_reader
31
- owner[reflection.active_record_primary_key]
31
+ owner[source_attr]
32
32
  end
33
33
 
34
34
  def ids_writer(new_ids)
35
- column = reflection.active_record_primary_key
36
- owner.update_column(column, owner[column] = new_ids.presence)
35
+ column = source_attr
36
+ command = owner.persisted? ? :update_column : :write_attribute
37
+ owner.public_send(command, column, new_ids.presence)
37
38
  @association_scope = nil
38
39
  end
39
40
 
40
41
  def insert_record(record, *)
41
42
  super
42
43
 
43
- attribute = (ids_reader || owner[reflection.active_record_primary_key] = [])
44
- attribute.push(record[klass_fk])
44
+ attribute = (ids_reader || owner[source_attr] = [])
45
+ attribute.push(record[klass_attr])
45
46
  record
46
47
  end
47
48
 
@@ -50,8 +51,8 @@ module Torque
50
51
  end
51
52
 
52
53
  def include?(record)
53
- list = owner[reflection.active_record_primary_key]
54
- ids_reader && ids_reader.include?(record[klass_fk])
54
+ list = owner[source_attr]
55
+ ids_reader && ids_reader.include?(record[klass_attr])
55
56
  end
56
57
 
57
58
  private
@@ -65,7 +66,7 @@ module Torque
65
66
  # When the idea is to nulligy the association, then just set the owner
66
67
  # +primary_key+ as empty
67
68
  def delete_count(method, scope, ids = nil)
68
- ids ||= scope.pluck(klass_fk)
69
+ ids ||= scope.pluck(klass_attr)
69
70
  scope.delete_all if method == :delete_all
70
71
  remove_stash_records(ids)
71
72
  end
@@ -76,13 +77,13 @@ module Torque
76
77
 
77
78
  # Deletes the records according to the <tt>:dependent</tt> option.
78
79
  def delete_records(records, method)
79
- ids = Array.wrap(records).each_with_object(klass_fk).map(&:[])
80
+ ids = Array.wrap(records).each_with_object(klass_attr).map(&:[])
80
81
 
81
82
  if method == :destroy
82
83
  records.each(&:destroy!)
83
84
  remove_stash_records(ids)
84
85
  else
85
- scope = self.scope.where(klass_fk => records)
86
+ scope = self.scope.where(klass_attr => records)
86
87
  delete_count(method, scope, ids)
87
88
  end
88
89
  end
@@ -98,10 +99,14 @@ module Torque
98
99
  ids_writer(ids_reader - Array.wrap(ids))
99
100
  end
100
101
 
101
- def klass_fk
102
+ def source_attr
102
103
  reflection.foreign_key
103
104
  end
104
105
 
106
+ def klass_attr
107
+ reflection.active_record_primary_key
108
+ end
109
+
105
110
  def difference(a, b)
106
111
  a - b
107
112
  end