aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/relation
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/relation')
-rw-r--r--activerecord/lib/active_record/relation/batches.rb2
-rw-r--r--activerecord/lib/active_record/relation/batches/batch_enumerator.rb2
-rw-r--r--activerecord/lib/active_record/relation/calculations.rb22
-rw-r--r--activerecord/lib/active_record/relation/delegation.rb13
-rw-r--r--activerecord/lib/active_record/relation/finder_methods.rb240
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder.rb4
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder/array_handler.rb2
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder/association_query_handler.rb5
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder/base_handler.rb2
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder/class_handler.rb27
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb2
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb40
-rw-r--r--activerecord/lib/active_record/relation/spawn_methods.rb2
-rw-r--r--activerecord/lib/active_record/relation/where_clause.rb2
-rw-r--r--activerecord/lib/active_record/relation/where_clause_factory.rb48
15 files changed, 202 insertions, 211 deletions
diff --git a/activerecord/lib/active_record/relation/batches.rb b/activerecord/lib/active_record/relation/batches.rb
index 4b2987ac6d..76031515fd 100644
--- a/activerecord/lib/active_record/relation/batches.rb
+++ b/activerecord/lib/active_record/relation/batches.rb
@@ -260,7 +260,7 @@ module ActiveRecord
end
def act_on_ignored_order(error_on_ignore)
- raise_error = (error_on_ignore.nil? ? self.klass.error_on_ignored_order : error_on_ignore)
+ raise_error = (error_on_ignore.nil? ? klass.error_on_ignored_order : error_on_ignore)
if raise_error
raise ArgumentError.new(ORDER_IGNORE_MESSAGE)
diff --git a/activerecord/lib/active_record/relation/batches/batch_enumerator.rb b/activerecord/lib/active_record/relation/batches/batch_enumerator.rb
index 333b3a63cf..3555779ec2 100644
--- a/activerecord/lib/active_record/relation/batches/batch_enumerator.rb
+++ b/activerecord/lib/active_record/relation/batches/batch_enumerator.rb
@@ -7,7 +7,7 @@ module ActiveRecord
@of = of
@relation = relation
@start = start
- @finish = finish
+ @finish = finish
end
# Looping through a collection of records from the database (using the
diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb
index a887be8a20..35c670f1a1 100644
--- a/activerecord/lib/active_record/relation/calculations.rb
+++ b/activerecord/lib/active_record/relation/calculations.rb
@@ -112,10 +112,6 @@ module ActiveRecord
# ...
# end
def calculate(operation, column_name)
- if column_name.is_a?(Symbol) && attribute_alias?(column_name)
- column_name = attribute_alias(column_name)
- end
-
if has_include?(column_name)
relation = construct_relation_for_association_calculations
relation = relation.distinct if operation.to_s.downcase == "count"
@@ -197,7 +193,7 @@ module ActiveRecord
# If #count is used with #distinct (i.e. `relation.distinct.count`) it is
# considered distinct.
- distinct = self.distinct_value
+ distinct = distinct_value
if operation == "count"
column_name ||= select_for_count
@@ -215,8 +211,8 @@ module ActiveRecord
def aggregate_column(column_name)
return column_name if Arel::Expressions === column_name
- if @klass.column_names.include?(column_name.to_s)
- Arel::Attribute.new(@klass.unscoped.table, column_name)
+ if @klass.has_attribute?(column_name.to_s) || @klass.attribute_alias?(column_name.to_s)
+ @klass.arel_attribute(column_name)
else
Arel.sql(column_name == :all ? "*" : column_name.to_s)
end
@@ -227,17 +223,17 @@ module ActiveRecord
end
def execute_simple_calculation(operation, column_name, distinct) #:nodoc:
- # PostgreSQL doesn't like ORDER BY when there are no GROUP BY
- relation = unscope(:order)
-
column_alias = column_name
- if operation == "count" && (relation.limit_value || relation.offset_value)
+ if operation == "count" && (limit_value || offset_value)
# Shortcut when limit is zero.
- return 0 if relation.limit_value == 0
+ return 0 if limit_value == 0
- query_builder = build_count_subquery(relation, column_name, distinct)
+ query_builder = build_count_subquery(spawn, column_name, distinct)
else
+ # PostgreSQL doesn't like ORDER BY when there are no GROUP BY
+ relation = unscope(:order)
+
column = aggregate_column(column_name)
select_value = operation_over_aggregate_column(column, operation, distinct)
diff --git a/activerecord/lib/active_record/relation/delegation.rb b/activerecord/lib/active_record/relation/delegation.rb
index d16de4b06c..d3ba724507 100644
--- a/activerecord/lib/active_record/relation/delegation.rb
+++ b/activerecord/lib/active_record/relation/delegation.rb
@@ -1,6 +1,3 @@
-require "active_support/concern"
-require "active_support/core_ext/regexp"
-
module ActiveRecord
module Delegation # :nodoc:
module DelegateCache # :nodoc:
@@ -18,7 +15,10 @@ module ActiveRecord
delegate = Class.new(klass) {
include ClassSpecificRelation
}
- const_set klass.name.gsub("::".freeze, "_".freeze), delegate
+ mangled_name = klass.name.gsub("::".freeze, "_".freeze)
+ const_set mangled_name, delegate
+ private_constant mangled_name
+
cache[klass] = delegate
end
end
@@ -38,6 +38,7 @@ module ActiveRecord
delegate :to_xml, :encode_with, :length, :collect, :map, :each, :all?, :include?, :to_ary, :join,
:[], :&, :|, :+, :-, :sample, :reverse, :compact, :in_groups, :in_groups_of,
+ :to_sentence, :to_formatted_s,
:shuffle, :split, :index, to: :records
delegate :table_name, :quoted_table_name, :primary_key, :quoted_primary_key,
@@ -81,7 +82,7 @@ module ActiveRecord
end
end
- protected
+ private
def method_missing(method, *args, &block)
if @klass.respond_to?(method)
@@ -113,7 +114,7 @@ module ActiveRecord
arel.respond_to?(method, include_private)
end
- protected
+ private
def method_missing(method, *args, &block)
if @klass.respond_to?(method)
diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb
index 5e580ac865..4548944fe6 100644
--- a/activerecord/lib/active_record/relation/finder_methods.rb
+++ b/activerecord/lib/active_record/relation/finder_methods.rb
@@ -17,8 +17,8 @@ module ActiveRecord
# Person.where("administrator = 1").order("created_on DESC").find(1)
#
# NOTE: The returned records may not be in the same order as the ids you
- # provide since database rows are unordered. You'd need to provide an explicit QueryMethods#order
- # option if you want the results are sorted.
+ # provide since database rows are unordered. You will need to provide an explicit QueryMethods#order
+ # option if you want the results to be sorted.
#
# ==== Find with lock
#
@@ -76,7 +76,7 @@ module ActiveRecord
# Post.find_by "published_at < ?", 2.weeks.ago
def find_by(arg, *args)
where(arg, *args).take
- rescue RangeError
+ rescue ::RangeError
nil
end
@@ -84,7 +84,7 @@ module ActiveRecord
# an ActiveRecord::RecordNotFound error.
def find_by!(arg, *args)
where(arg, *args).take!
- rescue RangeError
+ rescue ::RangeError
raise RecordNotFound.new("Couldn't find #{@klass.name} with an out of range value",
@klass.name)
end
@@ -152,14 +152,6 @@ module ActiveRecord
result = result.reverse_order!
limit ? result.reverse : result.first
- rescue ActiveRecord::IrreversibleOrderError
- ActiveSupport::Deprecation.warn(<<-WARNING.squish)
- Finding a last element by loading the relation when SQL ORDER
- can not be reversed is deprecated.
- Rails 5.1 will raise ActiveRecord::IrreversibleOrderError in this case.
- Please call `to_a.last` if you still want to load the relation.
- WARNING
- find_last(limit)
end
# Same as #last but raises ActiveRecord::RecordNotFound if no record
@@ -309,8 +301,7 @@ module ActiveRecord
# Person.exists?
def exists?(conditions = :none)
if Base === conditions
- conditions = conditions.id
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
+ raise ArgumentError, <<-MSG.squish
You are passing an instance of ActiveRecord::Base to `exists?`.
Please pass the id of the object by calling `.id`.
MSG
@@ -321,7 +312,7 @@ module ActiveRecord
relation = apply_join_dependency(self, construct_join_dependency(eager_loading: false))
return false if ActiveRecord::NullRelation === relation
- relation = relation.except(:select, :order).select(ONE_AS_ONE).limit(1)
+ relation = relation.except(:select, :distinct).select(ONE_AS_ONE).limit(1)
case conditions
when Array, Hash
@@ -333,7 +324,7 @@ module ActiveRecord
end
connection.select_value(relation, "#{name} Exists", relation.bound_attributes) ? true : false
- rescue RangeError
+ rescue ::RangeError
false
end
@@ -345,7 +336,7 @@ module ActiveRecord
# of results obtained should be provided in the +result_size+ argument and
# the expected number of results should be provided in the +expected_size+
# argument.
- def raise_record_not_found_exception!(ids = nil, result_size = nil, expected_size = nil) # :nodoc:
+ def raise_record_not_found_exception!(ids = nil, result_size = nil, expected_size = nil, key = primary_key) # :nodoc:
conditions = arel.where_sql(@klass.arel_engine)
conditions = " [#{conditions}]" if conditions
name = @klass.name
@@ -353,15 +344,15 @@ module ActiveRecord
if ids.nil?
error = "Couldn't find #{name}"
error << " with#{conditions}" if conditions
- raise RecordNotFound, error
+ raise RecordNotFound.new(error, name)
elsif Array(ids).size == 1
- error = "Couldn't find #{name} with '#{primary_key}'=#{ids}#{conditions}"
- raise RecordNotFound.new(error, name, primary_key, ids)
+ error = "Couldn't find #{name} with '#{key}'=#{ids}#{conditions}"
+ raise RecordNotFound.new(error, name, key, ids)
else
- error = "Couldn't find all #{name.pluralize} with '#{primary_key}': "
+ error = "Couldn't find all #{name.pluralize} with '#{key}': "
error << "(#{ids.join(", ")})#{conditions} (found #{result_size} results, but was looking for #{expected_size})"
- raise RecordNotFound, error
+ raise RecordNotFound.new(error, name, primary_key, ids)
end
end
@@ -439,143 +430,140 @@ module ActiveRecord
reflections.none?(&:collection?)
end
- protected
+ private
- def find_with_ids(*ids)
- raise UnknownPrimaryKey.new(@klass) if primary_key.nil?
+ def find_with_ids(*ids)
+ raise UnknownPrimaryKey.new(@klass) if primary_key.nil?
- expects_array = ids.first.kind_of?(Array)
- return ids.first if expects_array && ids.first.empty?
+ expects_array = ids.first.kind_of?(Array)
+ return ids.first if expects_array && ids.first.empty?
- ids = ids.flatten.compact.uniq
+ ids = ids.flatten.compact.uniq
- case ids.size
- when 0
- raise RecordNotFound, "Couldn't find #{@klass.name} without an ID"
- when 1
- result = find_one(ids.first)
- expects_array ? [ result ] : result
- else
- find_some(ids)
+ case ids.size
+ when 0
+ raise RecordNotFound, "Couldn't find #{@klass.name} without an ID"
+ when 1
+ result = find_one(ids.first)
+ expects_array ? [ result ] : result
+ else
+ find_some(ids)
+ end
+ rescue ::RangeError
+ raise RecordNotFound, "Couldn't find #{@klass.name} with an out of range ID"
end
- rescue RangeError
- raise RecordNotFound, "Couldn't find #{@klass.name} with an out of range ID"
- end
- def find_one(id)
- if ActiveRecord::Base === id
- id = id.id
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
- You are passing an instance of ActiveRecord::Base to `find`.
- Please pass the id of the object by calling `.id`.
- MSG
- end
+ def find_one(id)
+ if ActiveRecord::Base === id
+ raise ArgumentError, <<-MSG.squish
+ You are passing an instance of ActiveRecord::Base to `find`.
+ Please pass the id of the object by calling `.id`.
+ MSG
+ end
- relation = where(primary_key => id)
- record = relation.take
+ relation = where(primary_key => id)
+ record = relation.take
- raise_record_not_found_exception!(id, 0, 1) unless record
+ raise_record_not_found_exception!(id, 0, 1) unless record
- record
- end
+ record
+ end
- def find_some(ids)
- return find_some_ordered(ids) unless order_values.present?
+ def find_some(ids)
+ return find_some_ordered(ids) unless order_values.present?
- result = where(primary_key => ids).to_a
+ result = where(primary_key => ids).to_a
- expected_size =
- if limit_value && ids.size > limit_value
- limit_value
- else
- ids.size
- end
+ expected_size =
+ if limit_value && ids.size > limit_value
+ limit_value
+ else
+ ids.size
+ end
- # 11 ids with limit 3, offset 9 should give 2 results.
- if offset_value && (ids.size - offset_value < expected_size)
- expected_size = ids.size - offset_value
- end
+ # 11 ids with limit 3, offset 9 should give 2 results.
+ if offset_value && (ids.size - offset_value < expected_size)
+ expected_size = ids.size - offset_value
+ end
- if result.size == expected_size
- result
- else
- raise_record_not_found_exception!(ids, result.size, expected_size)
+ if result.size == expected_size
+ result
+ else
+ raise_record_not_found_exception!(ids, result.size, expected_size)
+ end
end
- end
- def find_some_ordered(ids)
- ids = ids.slice(offset_value || 0, limit_value || ids.size) || []
+ def find_some_ordered(ids)
+ ids = ids.slice(offset_value || 0, limit_value || ids.size) || []
- result = except(:limit, :offset).where(primary_key => ids).records
+ result = except(:limit, :offset).where(primary_key => ids).records
- if result.size == ids.size
- pk_type = @klass.type_for_attribute(primary_key)
+ if result.size == ids.size
+ pk_type = @klass.type_for_attribute(primary_key)
- records_by_id = result.index_by(&:id)
- ids.map { |id| records_by_id.fetch(pk_type.cast(id)) }
- else
- raise_record_not_found_exception!(ids, result.size, ids.size)
+ records_by_id = result.index_by(&:id)
+ ids.map { |id| records_by_id.fetch(pk_type.cast(id)) }
+ else
+ raise_record_not_found_exception!(ids, result.size, ids.size)
+ end
end
- end
- def find_take
- if loaded?
- records.first
- else
- @take ||= limit(1).records.first
+ def find_take
+ if loaded?
+ records.first
+ else
+ @take ||= limit(1).records.first
+ end
end
- end
- def find_take_with_limit(limit)
- if loaded?
- records.take(limit)
- else
- limit(limit).to_a
+ def find_take_with_limit(limit)
+ if loaded?
+ records.take(limit)
+ else
+ limit(limit).to_a
+ end
end
- end
- def find_nth(index)
- @offsets[offset_index + index] ||= find_nth_with_limit(index, 1).first
- end
+ def find_nth(index)
+ @offsets[offset_index + index] ||= find_nth_with_limit(index, 1).first
+ end
- def find_nth_with_limit(index, limit)
- if loaded?
- records[index, limit] || []
- else
- relation = if order_values.empty? && primary_key
- order(arel_attribute(primary_key).asc)
+ def find_nth_with_limit(index, limit)
+ if loaded?
+ records[index, limit] || []
else
- self
+ relation = if order_values.empty? && primary_key
+ order(arel_attribute(primary_key).asc)
+ else
+ self
+ end
+
+ relation = relation.offset(offset_index + index) unless index.zero?
+ relation.limit(limit).to_a
end
-
- relation = relation.offset(offset_index + index) unless index.zero?
- relation.limit(limit).to_a
end
- end
- def find_nth_from_last(index)
- if loaded?
- records[-index]
- else
- relation = if order_values.empty? && primary_key
- order(arel_attribute(primary_key).asc)
+ def find_nth_from_last(index)
+ if loaded?
+ records[-index]
else
- self
+ relation = if order_values.empty? && primary_key
+ order(arel_attribute(primary_key).asc)
+ else
+ self
+ end
+
+ relation.to_a[-index]
+ # TODO: can be made more performant on large result sets by
+ # for instance, last(index)[-index] (which would require
+ # refactoring the last(n) finder method to make test suite pass),
+ # or by using a combination of reverse_order, limit, and offset,
+ # e.g., reverse_order.offset(index-1).first
end
-
- relation.to_a[-index]
- # TODO: can be made more performant on large result sets by
- # for instance, last(index)[-index] (which would require
- # refactoring the last(n) finder method to make test suite pass),
- # or by using a combination of reverse_order, limit, and offset,
- # e.g., reverse_order.offset(index-1).first
end
- end
-
- private
- def find_last(limit)
- limit ? records.last(limit) : records.last
- end
+ def find_last(limit)
+ limit ? records.last(limit) : records.last
+ end
end
end
diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb
index 780a1ee422..18ae10a652 100644
--- a/activerecord/lib/active_record/relation/predicate_builder.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder.rb
@@ -4,7 +4,6 @@ module ActiveRecord
require "active_record/relation/predicate_builder/association_query_handler"
require "active_record/relation/predicate_builder/base_handler"
require "active_record/relation/predicate_builder/basic_object_handler"
- require "active_record/relation/predicate_builder/class_handler"
require "active_record/relation/predicate_builder/polymorphic_array_handler"
require "active_record/relation/predicate_builder/range_handler"
require "active_record/relation/predicate_builder/relation_handler"
@@ -16,7 +15,6 @@ module ActiveRecord
@handlers = []
register_handler(BasicObject, BasicObjectHandler.new)
- register_handler(Class, ClassHandler.new(self))
register_handler(Base, BaseHandler.new(self))
register_handler(Range, RangeHandler.new)
register_handler(RangeHandler::RangeWithBinds, RangeHandler.new)
@@ -66,6 +64,8 @@ module ActiveRecord
handler_for(value).call(attribute, value)
end
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
+ # Workaround for Ruby 2.2 "private attribute?" warning.
protected
attr_reader :table
diff --git a/activerecord/lib/active_record/relation/predicate_builder/array_handler.rb b/activerecord/lib/active_record/relation/predicate_builder/array_handler.rb
index 6400caba06..88b6c37d43 100644
--- a/activerecord/lib/active_record/relation/predicate_builder/array_handler.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder/array_handler.rb
@@ -29,6 +29,8 @@ module ActiveRecord
array_predicates.inject { |composite, predicate| composite.or(predicate) }
end
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
+ # Workaround for Ruby 2.2 "private attribute?" warning.
protected
attr_reader :predicate_builder
diff --git a/activerecord/lib/active_record/relation/predicate_builder/association_query_handler.rb b/activerecord/lib/active_record/relation/predicate_builder/association_query_handler.rb
index 7e20cb2c63..29860ec677 100644
--- a/activerecord/lib/active_record/relation/predicate_builder/association_query_handler.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder/association_query_handler.rb
@@ -28,6 +28,8 @@ module ActiveRecord
predicate_builder.build_from_hash(queries)
end
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
+ # Workaround for Ruby 2.2 "private attribute?" warning.
protected
attr_reader :predicate_builder
@@ -68,9 +70,6 @@ module ActiveRecord
case value
when Relation
value.klass.base_class
- when Array
- val = value.compact.first
- val.class.base_class if val.is_a?(Base)
when Base
value.class.base_class
end
diff --git a/activerecord/lib/active_record/relation/predicate_builder/base_handler.rb b/activerecord/lib/active_record/relation/predicate_builder/base_handler.rb
index 65c5159704..3bb1037885 100644
--- a/activerecord/lib/active_record/relation/predicate_builder/base_handler.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder/base_handler.rb
@@ -9,6 +9,8 @@ module ActiveRecord
predicate_builder.build(attribute, value.id)
end
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
+ # Workaround for Ruby 2.2 "private attribute?" warning.
protected
attr_reader :predicate_builder
diff --git a/activerecord/lib/active_record/relation/predicate_builder/class_handler.rb b/activerecord/lib/active_record/relation/predicate_builder/class_handler.rb
deleted file mode 100644
index 0a6574fcf1..0000000000
--- a/activerecord/lib/active_record/relation/predicate_builder/class_handler.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-module ActiveRecord
- class PredicateBuilder
- class ClassHandler # :nodoc:
- def initialize(predicate_builder)
- @predicate_builder = predicate_builder
- end
-
- def call(attribute, value)
- print_deprecation_warning
- predicate_builder.build(attribute, value.name)
- end
-
- protected
-
- attr_reader :predicate_builder
-
- private
-
- def print_deprecation_warning
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
- Passing a class as a value in an Active Record query is deprecated and
- will be removed. Pass a string instead.
- MSG
- end
- end
- end
-end
diff --git a/activerecord/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb b/activerecord/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb
index 0c7f92b3d0..335124c952 100644
--- a/activerecord/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb
@@ -21,6 +21,8 @@ module ActiveRecord
end
end
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
+ # Workaround for Ruby 2.2 "private attribute?" warning.
protected
attr_reader :predicate_builder
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 9fbbe32e7f..4ee413c805 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -3,8 +3,6 @@ require "active_record/relation/query_attribute"
require "active_record/relation/where_clause"
require "active_record/relation/where_clause_factory"
require "active_model/forbidden_attributes_protection"
-require "active_support/core_ext/string/filters"
-require "active_support/core_ext/regexp"
module ActiveRecord
module QueryMethods
@@ -77,7 +75,7 @@ module ActiveRecord
end
def bound_attributes
- if limit_value && !string_containing_comma?(limit_value)
+ if limit_value
limit_bind = Attribute.with_cast_value(
"LIMIT".freeze,
connection.sanitize_limit(limit_value),
@@ -242,7 +240,14 @@ module ActiveRecord
# Model.select(:field).first.other_field
# # => ActiveModel::MissingAttributeError: missing attribute: other_field
def select(*fields)
- return super if block_given?
+ if block_given?
+ if fields.any?
+ raise ArgumentError, "`select' with block doesn't take arguments."
+ end
+
+ return super()
+ end
+
raise ArgumentError, "Call this with at least one field" if fields.empty?
spawn._select!(*fields)
end
@@ -651,7 +656,7 @@ module ActiveRecord
end
self.where_clause = self.where_clause.or(other.where_clause)
- self.having_clause = self.having_clause.or(other.having_clause)
+ self.having_clause = having_clause.or(other.having_clause)
self
end
@@ -682,13 +687,6 @@ module ActiveRecord
end
def limit!(value) # :nodoc:
- if string_containing_comma?(value)
- # Remove `string_containing_comma?` when removing this deprecation
- ActiveSupport::Deprecation.warn(<<-WARNING.squish)
- Passing a string to limit in the form "1,2" is deprecated and will be
- removed in Rails 5.1. Please call `offset` explicitly instead.
- WARNING
- end
self.limit_value = value
self
end
@@ -755,7 +753,7 @@ module ActiveRecord
# end
#
def none
- where("1=0").extending!(NullRelation)
+ spawn.none!
end
def none! # :nodoc:
@@ -840,16 +838,12 @@ module ActiveRecord
def distinct(value = true)
spawn.distinct!(value)
end
- alias uniq distinct
- deprecate uniq: :distinct
# Like #distinct, but modifies relation in place.
def distinct!(value = true) # :nodoc:
self.distinct_value = value
self
end
- alias uniq! distinct!
- deprecate uniq!: :distinct!
# Used to extend a scope with additional methods, either through
# a module or through a block provided.
@@ -950,13 +944,7 @@ module ActiveRecord
arel.where(where_clause.ast) unless where_clause.empty?
arel.having(having_clause.ast) unless having_clause.empty?
- if limit_value
- if string_containing_comma?(limit_value)
- arel.take(connection.sanitize_limit(limit_value))
- else
- arel.take(Arel::Nodes::BindParam.new)
- end
- end
+ arel.take(Arel::Nodes::BindParam.new) if limit_value
arel.skip(Arel::Nodes::BindParam.new) if offset_value
arel.group(*arel_columns(group_values.uniq.reject(&:blank?))) unless group_values.empty?
@@ -1184,10 +1172,6 @@ module ActiveRecord
end
alias having_clause_factory where_clause_factory
- def string_containing_comma?(value)
- ::String === value && value.include?(",")
- end
-
def default_value_for(name)
case name
when :create_with
diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb
index 190e339ea8..ada89b5ec3 100644
--- a/activerecord/lib/active_record/relation/spawn_methods.rb
+++ b/activerecord/lib/active_record/relation/spawn_methods.rb
@@ -66,7 +66,7 @@ module ActiveRecord
private
- def relation_with(values) # :nodoc:
+ def relation_with(values)
result = Relation.create(klass, table, predicate_builder, values)
result.extend(*extending_values) if extending_values.any?
result
diff --git a/activerecord/lib/active_record/relation/where_clause.rb b/activerecord/lib/active_record/relation/where_clause.rb
index 402f8acfd1..ef0d059d1c 100644
--- a/activerecord/lib/active_record/relation/where_clause.rb
+++ b/activerecord/lib/active_record/relation/where_clause.rb
@@ -84,6 +84,8 @@ module ActiveRecord
@empty ||= new([], [])
end
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
+ # Workaround for Ruby 2.2 "private attribute?" warning.
protected
attr_reader :predicates
diff --git a/activerecord/lib/active_record/relation/where_clause_factory.rb b/activerecord/lib/active_record/relation/where_clause_factory.rb
index 1e7deeffad..04bee73e8f 100644
--- a/activerecord/lib/active_record/relation/where_clause_factory.rb
+++ b/activerecord/lib/active_record/relation/where_clause_factory.rb
@@ -15,9 +15,12 @@ module ActiveRecord
attributes = klass.send(:expand_hash_conditions_for_aggregates, attributes)
attributes.stringify_keys!
- attributes, binds = predicate_builder.create_binds(attributes)
-
- parts = predicate_builder.build_from_hash(attributes)
+ if perform_case_sensitive?(options = other.last)
+ parts, binds = build_for_case_sensitive(attributes, options)
+ else
+ attributes, binds = predicate_builder.create_binds(attributes)
+ parts = predicate_builder.build_from_hash(attributes)
+ end
when Arel::Nodes::Node
parts = [opts]
else
@@ -27,9 +30,48 @@ module ActiveRecord
WhereClause.new(parts, binds || [])
end
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
+ # Workaround for Ruby 2.2 "private attribute?" warning.
protected
attr_reader :klass, :predicate_builder
+
+ private
+
+ def perform_case_sensitive?(options)
+ options && options.key?(:case_sensitive)
+ end
+
+ def build_for_case_sensitive(attributes, options)
+ parts, binds = [], []
+ table = klass.arel_table
+
+ attributes.each do |attribute, value|
+ if reflection = klass._reflect_on_association(attribute)
+ attribute = reflection.foreign_key.to_s
+ value = value[reflection.klass.primary_key] unless value.nil?
+ end
+
+ if value.nil?
+ parts << table[attribute].eq(value)
+ else
+ column = klass.column_for_attribute(attribute)
+
+ binds << predicate_builder.send(:build_bind_param, attribute, value)
+ value = Arel::Nodes::BindParam.new
+
+ predicate = if options[:case_sensitive]
+ klass.connection.case_sensitive_comparison(table, attribute, column, value)
+ else
+ klass.connection.case_insensitive_comparison(table, attribute, column, value)
+ end
+
+ parts << predicate
+ end
+ end
+
+ [parts, binds]
+ end
end
end
end