activerecord 4.0.4 → 4.1.16

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1632 -1797
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +2 -2
  5. data/examples/performance.rb +30 -18
  6. data/examples/simple.rb +4 -4
  7. data/lib/active_record/aggregations.rb +2 -1
  8. data/lib/active_record/association_relation.rb +4 -0
  9. data/lib/active_record/associations/alias_tracker.rb +49 -29
  10. data/lib/active_record/associations/association.rb +9 -17
  11. data/lib/active_record/associations/association_scope.rb +59 -49
  12. data/lib/active_record/associations/belongs_to_association.rb +34 -25
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +6 -1
  14. data/lib/active_record/associations/builder/association.rb +84 -54
  15. data/lib/active_record/associations/builder/belongs_to.rb +90 -58
  16. data/lib/active_record/associations/builder/collection_association.rb +47 -45
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +119 -25
  18. data/lib/active_record/associations/builder/has_many.rb +3 -3
  19. data/lib/active_record/associations/builder/has_one.rb +5 -7
  20. data/lib/active_record/associations/builder/singular_association.rb +6 -7
  21. data/lib/active_record/associations/collection_association.rb +121 -111
  22. data/lib/active_record/associations/collection_proxy.rb +73 -18
  23. data/lib/active_record/associations/has_many_association.rb +14 -11
  24. data/lib/active_record/associations/has_many_through_association.rb +33 -6
  25. data/lib/active_record/associations/has_one_association.rb +1 -1
  26. data/lib/active_record/associations/join_dependency/join_association.rb +46 -104
  27. data/lib/active_record/associations/join_dependency/join_base.rb +6 -8
  28. data/lib/active_record/associations/join_dependency/join_part.rb +18 -37
  29. data/lib/active_record/associations/join_dependency.rb +208 -168
  30. data/lib/active_record/associations/preloader/association.rb +69 -27
  31. data/lib/active_record/associations/preloader/collection_association.rb +2 -2
  32. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  33. data/lib/active_record/associations/preloader/singular_association.rb +3 -3
  34. data/lib/active_record/associations/preloader/through_association.rb +58 -26
  35. data/lib/active_record/associations/preloader.rb +63 -49
  36. data/lib/active_record/associations/singular_association.rb +6 -5
  37. data/lib/active_record/associations/through_association.rb +30 -9
  38. data/lib/active_record/associations.rb +116 -42
  39. data/lib/active_record/attribute_assignment.rb +6 -3
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +2 -1
  41. data/lib/active_record/attribute_methods/dirty.rb +35 -26
  42. data/lib/active_record/attribute_methods/primary_key.rb +8 -1
  43. data/lib/active_record/attribute_methods/read.rb +56 -29
  44. data/lib/active_record/attribute_methods/serialization.rb +44 -12
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +13 -1
  46. data/lib/active_record/attribute_methods/write.rb +59 -26
  47. data/lib/active_record/attribute_methods.rb +82 -43
  48. data/lib/active_record/autosave_association.rb +209 -194
  49. data/lib/active_record/base.rb +6 -2
  50. data/lib/active_record/callbacks.rb +2 -2
  51. data/lib/active_record/coders/json.rb +13 -0
  52. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +5 -10
  53. data/lib/active_record/connection_adapters/abstract/database_statements.rb +14 -24
  54. data/lib/active_record/connection_adapters/abstract/query_cache.rb +13 -13
  55. data/lib/active_record/connection_adapters/abstract/quoting.rb +6 -3
  56. data/lib/active_record/connection_adapters/abstract/savepoints.rb +21 -0
  57. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +90 -0
  58. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +9 -8
  59. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +45 -70
  60. data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -0
  61. data/lib/active_record/connection_adapters/abstract_adapter.rb +28 -96
  62. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +74 -66
  63. data/lib/active_record/connection_adapters/column.rb +1 -35
  64. data/lib/active_record/connection_adapters/connection_specification.rb +231 -43
  65. data/lib/active_record/connection_adapters/mysql2_adapter.rb +10 -5
  66. data/lib/active_record/connection_adapters/mysql_adapter.rb +24 -17
  67. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +22 -15
  68. data/lib/active_record/connection_adapters/postgresql/cast.rb +12 -4
  69. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +18 -44
  70. data/lib/active_record/connection_adapters/postgresql/oid.rb +38 -14
  71. data/lib/active_record/connection_adapters/postgresql/quoting.rb +37 -12
  72. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +20 -11
  73. data/lib/active_record/connection_adapters/postgresql_adapter.rb +98 -52
  74. data/lib/active_record/connection_adapters/schema_cache.rb +8 -29
  75. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +55 -60
  76. data/lib/active_record/connection_handling.rb +39 -5
  77. data/lib/active_record/core.rb +38 -54
  78. data/lib/active_record/counter_cache.rb +9 -10
  79. data/lib/active_record/dynamic_matchers.rb +6 -2
  80. data/lib/active_record/enum.rb +199 -0
  81. data/lib/active_record/errors.rb +22 -5
  82. data/lib/active_record/fixture_set/file.rb +2 -1
  83. data/lib/active_record/fixtures.rb +173 -76
  84. data/lib/active_record/gem_version.rb +15 -0
  85. data/lib/active_record/inheritance.rb +23 -9
  86. data/lib/active_record/integration.rb +54 -1
  87. data/lib/active_record/locking/optimistic.rb +7 -2
  88. data/lib/active_record/locking/pessimistic.rb +1 -1
  89. data/lib/active_record/log_subscriber.rb +6 -13
  90. data/lib/active_record/migration/command_recorder.rb +8 -2
  91. data/lib/active_record/migration.rb +91 -56
  92. data/lib/active_record/model_schema.rb +7 -14
  93. data/lib/active_record/nested_attributes.rb +25 -13
  94. data/lib/active_record/no_touching.rb +52 -0
  95. data/lib/active_record/null_relation.rb +26 -6
  96. data/lib/active_record/persistence.rb +23 -29
  97. data/lib/active_record/querying.rb +15 -12
  98. data/lib/active_record/railtie.rb +12 -61
  99. data/lib/active_record/railties/databases.rake +37 -56
  100. data/lib/active_record/readonly_attributes.rb +0 -6
  101. data/lib/active_record/reflection.rb +230 -79
  102. data/lib/active_record/relation/batches.rb +74 -24
  103. data/lib/active_record/relation/calculations.rb +52 -48
  104. data/lib/active_record/relation/delegation.rb +54 -39
  105. data/lib/active_record/relation/finder_methods.rb +210 -67
  106. data/lib/active_record/relation/merger.rb +15 -12
  107. data/lib/active_record/relation/predicate_builder/array_handler.rb +29 -0
  108. data/lib/active_record/relation/predicate_builder/relation_handler.rb +17 -0
  109. data/lib/active_record/relation/predicate_builder.rb +81 -40
  110. data/lib/active_record/relation/query_methods.rb +185 -108
  111. data/lib/active_record/relation/spawn_methods.rb +8 -5
  112. data/lib/active_record/relation.rb +79 -84
  113. data/lib/active_record/result.rb +45 -6
  114. data/lib/active_record/runtime_registry.rb +5 -0
  115. data/lib/active_record/sanitization.rb +4 -4
  116. data/lib/active_record/schema_dumper.rb +18 -6
  117. data/lib/active_record/schema_migration.rb +31 -18
  118. data/lib/active_record/scoping/default.rb +5 -18
  119. data/lib/active_record/scoping/named.rb +14 -29
  120. data/lib/active_record/scoping.rb +5 -0
  121. data/lib/active_record/store.rb +67 -18
  122. data/lib/active_record/tasks/database_tasks.rb +66 -26
  123. data/lib/active_record/tasks/mysql_database_tasks.rb +16 -10
  124. data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -1
  125. data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
  126. data/lib/active_record/timestamp.rb +6 -6
  127. data/lib/active_record/transactions.rb +10 -12
  128. data/lib/active_record/validations/presence.rb +1 -1
  129. data/lib/active_record/validations/uniqueness.rb +19 -9
  130. data/lib/active_record/version.rb +4 -7
  131. data/lib/active_record.rb +5 -7
  132. data/lib/rails/generators/active_record/migration/migration_generator.rb +4 -0
  133. data/lib/rails/generators/active_record/migration.rb +18 -0
  134. data/lib/rails/generators/active_record/model/model_generator.rb +4 -0
  135. data/lib/rails/generators/active_record.rb +2 -8
  136. metadata +18 -30
  137. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -65
  138. data/lib/active_record/associations/join_helper.rb +0 -45
  139. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
  140. data/lib/active_record/tasks/firebird_database_tasks.rb +0 -56
  141. data/lib/active_record/tasks/oracle_database_tasks.rb +0 -45
  142. data/lib/active_record/tasks/sqlserver_database_tasks.rb +0 -48
  143. data/lib/active_record/test_case.rb +0 -96
@@ -19,7 +19,17 @@ module ActiveRecord
19
19
  #
20
20
  # Person.group(:city).count
21
21
  # # => { 'Rome' => 5, 'Paris' => 3 }
22
+ #
23
+ # If +count+ is used with +select+, it will count the selected columns:
24
+ #
25
+ # Person.select(:age).count
26
+ # # => counts the number of different age values
27
+ #
28
+ # Note: not all valid +select+ expressions are valid +count+ expressions. The specifics differ
29
+ # between databases. In invalid cases, an error from the databsae is thrown.
22
30
  def count(column_name = nil, options = {})
31
+ # TODO: Remove options argument as soon we remove support to
32
+ # activerecord-deprecated_finders.
23
33
  column_name, options = nil, column_name if column_name.is_a?(Hash)
24
34
  calculate(:count, column_name, options)
25
35
  end
@@ -27,8 +37,10 @@ module ActiveRecord
27
37
  # Calculates the average value on a given column. Returns +nil+ if there's
28
38
  # no row. See +calculate+ for examples with options.
29
39
  #
30
- # Person.average('age') # => 35.8
40
+ # Person.average(:age) # => 35.8
31
41
  def average(column_name, options = {})
42
+ # TODO: Remove options argument as soon we remove support to
43
+ # activerecord-deprecated_finders.
32
44
  calculate(:average, column_name, options)
33
45
  end
34
46
 
@@ -36,8 +48,10 @@ module ActiveRecord
36
48
  # with the same data type of the column, or +nil+ if there's no row. See
37
49
  # +calculate+ for examples with options.
38
50
  #
39
- # Person.minimum('age') # => 7
51
+ # Person.minimum(:age) # => 7
40
52
  def minimum(column_name, options = {})
53
+ # TODO: Remove options argument as soon we remove support to
54
+ # activerecord-deprecated_finders.
41
55
  calculate(:minimum, column_name, options)
42
56
  end
43
57
 
@@ -45,8 +59,10 @@ module ActiveRecord
45
59
  # with the same data type of the column, or +nil+ if there's no row. See
46
60
  # +calculate+ for examples with options.
47
61
  #
48
- # Person.maximum('age') # => 93
62
+ # Person.maximum(:age) # => 93
49
63
  def maximum(column_name, options = {})
64
+ # TODO: Remove options argument as soon we remove support to
65
+ # activerecord-deprecated_finders.
50
66
  calculate(:maximum, column_name, options)
51
67
  end
52
68
 
@@ -54,17 +70,9 @@ module ActiveRecord
54
70
  # with the same data type of the column, 0 if there's no row. See
55
71
  # +calculate+ for examples with options.
56
72
  #
57
- # Person.sum('age') # => 4562
73
+ # Person.sum(:age) # => 4562
58
74
  def sum(*args)
59
- if block_given?
60
- ActiveSupport::Deprecation.warn(
61
- "Calling #sum with a block is deprecated and will be removed in Rails 4.1. " \
62
- "If you want to perform sum calculation over the array of elements, use `to_a.sum(&block)`."
63
- )
64
- self.to_a.sum(*args) {|*block_args| yield(*block_args)}
65
- else
66
- calculate(:sum, *args)
67
- end
75
+ calculate(:sum, *args)
68
76
  end
69
77
 
70
78
  # This calculates aggregate values in the given column. Methods for count, sum, average,
@@ -99,19 +107,17 @@ module ActiveRecord
99
107
  #
100
108
  # Person.sum("2 * age")
101
109
  def calculate(operation, column_name, options = {})
102
- relation = with_default_scope
110
+ # TODO: Remove options argument as soon we remove support to
111
+ # activerecord-deprecated_finders.
112
+ if column_name.is_a?(Symbol) && attribute_alias?(column_name)
113
+ column_name = attribute_alias(column_name)
114
+ end
103
115
 
104
- if relation.equal?(self)
105
- if has_include?(column_name)
106
- construct_relation_for_association_calculations.calculate(operation, column_name, options)
107
- else
108
- perform_calculation(operation, column_name, options)
109
- end
116
+ if has_include?(column_name)
117
+ construct_relation_for_association_calculations.calculate(operation, column_name, options)
110
118
  else
111
- relation.calculate(operation, column_name, options)
119
+ perform_calculation(operation, column_name, options)
112
120
  end
113
- rescue ThrowResult
114
- 0
115
121
  end
116
122
 
117
123
  # Use <tt>pluck</tt> as a shortcut to select one or more attributes without
@@ -149,10 +155,10 @@ module ActiveRecord
149
155
  #
150
156
  def pluck(*column_names)
151
157
  column_names.map! do |column_name|
152
- if column_name.is_a?(Symbol) && self.column_names.include?(column_name.to_s)
153
- "#{connection.quote_table_name(table_name)}.#{connection.quote_column_name(column_name)}"
158
+ if column_name.is_a?(Symbol) && attribute_alias?(column_name)
159
+ attribute_alias(column_name)
154
160
  else
155
- column_name
161
+ column_name.to_s
156
162
  end
157
163
  end
158
164
 
@@ -160,22 +166,23 @@ module ActiveRecord
160
166
  construct_relation_for_association_calculations.pluck(*column_names)
161
167
  else
162
168
  relation = spawn
163
- relation.select_values = column_names
169
+ relation.select_values = column_names.map { |cn|
170
+ columns_hash.key?(cn) ? arel_table[cn] : cn
171
+ }
164
172
  result = klass.connection.select_all(relation.arel, nil, bind_values)
165
173
  columns = result.columns.map do |key|
166
174
  klass.column_types.fetch(key) {
167
- result.column_types.fetch(key) {
168
- Class.new { def type_cast(v); v; end }.new
169
- }
175
+ result.column_types.fetch(key) { result.identity_type }
170
176
  }
171
177
  end
172
178
 
173
- result = result.map do |attributes|
174
- values = klass.initialize_attributes(attributes).values
175
-
176
- columns.zip(values).map do |column, value|
177
- column.type_cast(value)
179
+ result = result.rows.map do |values|
180
+ values = result.columns.zip(values).map do |column_name, value|
181
+ single_attr_hash = { column_name => value }
182
+ klass.initialize_attributes(single_attr_hash).values.first
178
183
  end
184
+
185
+ columns.zip(values).map { |column, value| column.type_cast value }
179
186
  end
180
187
  columns.one? ? result.map!(&:first) : result
181
188
  end
@@ -192,30 +199,26 @@ module ActiveRecord
192
199
  private
193
200
 
194
201
  def has_include?(column_name)
195
- eager_loading? || (includes_values.present? && (column_name || references_eager_loaded_tables?))
202
+ eager_loading? || (includes_values.present? && ((column_name && column_name != :all) || references_eager_loaded_tables?))
196
203
  end
197
204
 
198
205
  def perform_calculation(operation, column_name, options = {})
206
+ # TODO: Remove options argument as soon we remove support to
207
+ # activerecord-deprecated_finders.
199
208
  operation = operation.to_s.downcase
200
209
 
201
210
  # If #count is used with #distinct / #uniq it is considered distinct. (eg. relation.distinct.count)
202
211
  distinct = self.distinct_value
203
- if options.has_key?(:distinct)
204
- ActiveSupport::Deprecation.warn "The :distinct option for `Relation#count` is deprecated. " \
205
- "Please use `Relation#distinct` instead. (eg. `relation.distinct.count`)"
206
- distinct = options[:distinct]
207
- end
208
212
 
209
213
  if operation == "count"
210
- column_name ||= (select_for_count || :all)
214
+ column_name ||= select_for_count
211
215
 
212
216
  unless arel.ast.grep(Arel::Nodes::OuterJoin).empty?
213
217
  distinct = true
214
218
  end
215
219
 
216
220
  column_name = primary_key if column_name == :all && distinct
217
-
218
- distinct = nil if column_name =~ /\s*DISTINCT\s+/i
221
+ distinct = nil if column_name =~ /\s*DISTINCT[\s(]+/i
219
222
  end
220
223
 
221
224
  if group_values.any?
@@ -239,7 +242,7 @@ module ActiveRecord
239
242
 
240
243
  def execute_simple_calculation(operation, column_name, distinct) #:nodoc:
241
244
  # Postgresql doesn't like ORDER BY when there are no GROUP BY
242
- relation = reorder(nil)
245
+ relation = unscope(:order)
243
246
 
244
247
  column_alias = column_name
245
248
 
@@ -273,7 +276,7 @@ module ActiveRecord
273
276
  group_attrs = group_values
274
277
 
275
278
  if group_attrs.first.respond_to?(:to_sym)
276
- association = @klass.reflect_on_association(group_attrs.first.to_sym)
279
+ association = @klass._reflect_on_association(group_attrs.first.to_sym)
277
280
  associated = group_attrs.size == 1 && association && association.macro == :belongs_to # only count belongs_to associations
278
281
  group_fields = Array(associated ? association.foreign_key : group_attrs)
279
282
  else
@@ -381,8 +384,9 @@ module ActiveRecord
381
384
  # TODO: refactor to allow non-string `select_values` (eg. Arel nodes).
382
385
  def select_for_count
383
386
  if select_values.present?
384
- select = select_values.join(", ")
385
- select if select !~ /[,*]/
387
+ select_values.join(", ")
388
+ else
389
+ :all
386
390
  end
387
391
  end
388
392
 
@@ -1,8 +1,35 @@
1
- require 'thread'
2
- require 'thread_safe'
1
+ require 'set'
2
+ require 'active_support/concern'
3
+ require 'active_support/deprecation'
3
4
 
4
5
  module ActiveRecord
5
6
  module Delegation # :nodoc:
7
+ module DelegateCache
8
+ def relation_delegate_class(klass) # :nodoc:
9
+ @relation_delegate_cache[klass]
10
+ end
11
+
12
+ def initialize_relation_delegate_cache # :nodoc:
13
+ @relation_delegate_cache = cache = {}
14
+ [
15
+ ActiveRecord::Relation,
16
+ ActiveRecord::Associations::CollectionProxy,
17
+ ActiveRecord::AssociationRelation
18
+ ].each do |klass|
19
+ delegate = Class.new(klass) {
20
+ include ClassSpecificRelation
21
+ }
22
+ const_set klass.name.gsub('::', '_'), delegate
23
+ cache[klass] = delegate
24
+ end
25
+ end
26
+
27
+ def inherited(child_class)
28
+ child_class.initialize_relation_delegate_cache
29
+ super
30
+ end
31
+ end
32
+
6
33
  extend ActiveSupport::Concern
7
34
 
8
35
  # This module creates compiled delegation methods dynamically at runtime, which makes
@@ -10,7 +37,14 @@ module ActiveRecord
10
37
  # may vary depending on the klass of a relation, so we create a subclass of Relation
11
38
  # for each different klass, and the delegations are compiled into that subclass only.
12
39
 
13
- delegate :to_xml, :to_yaml, :length, :collect, :map, :each, :all?, :include?, :to_ary, :to => :to_a
40
+ BLACKLISTED_ARRAY_METHODS = [
41
+ :compact!, :flatten!, :reject!, :reverse!, :rotate!, :map!,
42
+ :shuffle!, :slice!, :sort!, :sort_by!, :delete_if,
43
+ :keep_if, :pop, :shift, :delete_at, :select!
44
+ ].to_set # :nodoc:
45
+
46
+ delegate :to_xml, :to_yaml, :length, :collect, :map, :each, :all?, :include?, :to_ary, :join, to: :to_a
47
+
14
48
  delegate :table_name, :quoted_table_name, :primary_key, :quoted_primary_key,
15
49
  :connection, :columns_hash, :to => :klass
16
50
 
@@ -38,7 +72,7 @@ module ActiveRecord
38
72
  RUBY
39
73
  else
40
74
  define_method method do |*args, &block|
41
- scoping { @klass.send(method, *args, &block) }
75
+ scoping { @klass.public_send(method, *args, &block) }
42
76
  end
43
77
  end
44
78
  end
@@ -57,13 +91,10 @@ module ActiveRecord
57
91
  def method_missing(method, *args, &block)
58
92
  if @klass.respond_to?(method)
59
93
  self.class.delegate_to_scoped_klass(method)
60
- scoping { @klass.send(method, *args, &block) }
61
- elsif Array.method_defined?(method)
62
- self.class.delegate method, :to => :to_a
63
- to_a.send(method, *args, &block)
94
+ scoping { @klass.public_send(method, *args, &block) }
64
95
  elsif arel.respond_to?(method)
65
96
  self.class.delegate method, :to => :arel
66
- arel.send(method, *args, &block)
97
+ arel.public_send(method, *args, &block)
67
98
  else
68
99
  super
69
100
  end
@@ -71,52 +102,36 @@ module ActiveRecord
71
102
  end
72
103
 
73
104
  module ClassMethods # :nodoc:
74
- @@subclasses = ThreadSafe::Cache.new(:initial_capacity => 2)
75
-
76
- def new(klass, *args)
77
- relation = relation_class_for(klass).allocate
78
- relation.__send__(:initialize, klass, *args)
79
- relation
80
- end
81
-
82
- # This doesn't have to be thread-safe. relation_class_for guarantees that this will only be
83
- # called exactly once for a given const name.
84
- def const_missing(name)
85
- const_set(name, Class.new(self) { include ClassSpecificRelation })
105
+ def create(klass, *args)
106
+ relation_class_for(klass).new(klass, *args)
86
107
  end
87
108
 
88
109
  private
89
- # Cache the constants in @@subclasses because looking them up via const_get
90
- # make instantiation significantly slower.
110
+
91
111
  def relation_class_for(klass)
92
- if klass && (klass_name = klass.name)
93
- my_cache = @@subclasses.compute_if_absent(self) { ThreadSafe::Cache.new }
94
- # This hash is keyed by klass.name to avoid memory leaks in development mode
95
- my_cache.compute_if_absent(klass_name) do
96
- # Cache#compute_if_absent guarantees that the block will only executed once for the given klass_name
97
- const_get("#{name.gsub('::', '_')}_#{klass_name.gsub('::', '_')}", false)
98
- end
99
- else
100
- ActiveRecord::Relation
101
- end
112
+ klass.relation_delegate_class(self)
102
113
  end
103
114
  end
104
115
 
105
116
  def respond_to?(method, include_private = false)
106
- super || Array.method_defined?(method) ||
107
- @klass.respond_to?(method, include_private) ||
117
+ super || @klass.respond_to?(method, include_private) ||
118
+ array_delegable?(method) ||
108
119
  arel.respond_to?(method, include_private)
109
120
  end
110
121
 
111
122
  protected
112
123
 
124
+ def array_delegable?(method)
125
+ Array.method_defined?(method) && BLACKLISTED_ARRAY_METHODS.exclude?(method)
126
+ end
127
+
113
128
  def method_missing(method, *args, &block)
114
129
  if @klass.respond_to?(method)
115
- scoping { @klass.send(method, *args, &block) }
116
- elsif Array.method_defined?(method)
117
- to_a.send(method, *args, &block)
130
+ scoping { @klass.public_send(method, *args, &block) }
131
+ elsif array_delegable?(method)
132
+ to_a.public_send(method, *args, &block)
118
133
  elsif arel.respond_to?(method)
119
- arel.send(method, *args, &block)
134
+ arel.public_send(method, *args, &block)
120
135
  else
121
136
  super
122
137
  end