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/calculations.rb8
-rw-r--r--activerecord/lib/active_record/relation/delegation.rb10
-rw-r--r--activerecord/lib/active_record/relation/finder_methods.rb32
-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.rb32
-rw-r--r--activerecord/lib/active_record/relation/spawn_methods.rb2
-rw-r--r--activerecord/lib/active_record/relation/where_clause.rb42
-rw-r--r--activerecord/lib/active_record/relation/where_clause_factory.rb48
14 files changed, 111 insertions, 107 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/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb
index 827688a663..f4cdaf3948 100644
--- a/activerecord/lib/active_record/relation/calculations.rb
+++ b/activerecord/lib/active_record/relation/calculations.rb
@@ -193,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
@@ -232,7 +232,7 @@ module ActiveRecord
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)
+ relation = unscope(:order).distinct!(false)
column = aggregate_column(column_name)
@@ -282,7 +282,7 @@ module ActiveRecord
operation,
distinct).as(aggregate_alias)
]
- select_values += select_values unless having_clause.empty?
+ select_values += self.select_values unless having_clause.empty?
select_values.concat group_columns.map { |aliaz, field|
if field.respond_to?(:as)
@@ -292,7 +292,7 @@ module ActiveRecord
end
}
- relation = except(:group)
+ relation = except(:group).distinct!(false)
relation.group_values = group_fields
relation.select_values = select_values
diff --git a/activerecord/lib/active_record/relation/delegation.rb b/activerecord/lib/active_record/relation/delegation.rb
index 4b9310b225..d3ba724507 100644
--- a/activerecord/lib/active_record/relation/delegation.rb
+++ b/activerecord/lib/active_record/relation/delegation.rb
@@ -15,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
@@ -35,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,
@@ -78,7 +82,7 @@ module ActiveRecord
end
end
- protected
+ private
def method_missing(method, *args, &block)
if @klass.respond_to?(method)
@@ -110,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 5e456452e9..5d24f5f5ca 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
#
@@ -147,19 +147,11 @@ module ActiveRecord
def last(limit = nil)
return find_last(limit) if loaded? || limit_value
- result = limit(limit || 1)
+ result = limit(limit)
result.order!(arel_attribute(primary_key)) if order_values.empty? && primary_key
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
@@ -439,8 +430,6 @@ module ActiveRecord
reflections.none?(&:collection?)
end
- protected
-
def find_with_ids(*ids)
raise UnknownPrimaryKey.new(@klass) if primary_key.nil?
@@ -464,8 +453,7 @@ module ActiveRecord
def find_one(id)
if ActiveRecord::Base === id
- id = id.id
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
+ 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
@@ -548,8 +536,12 @@ module ActiveRecord
self
end
- relation = relation.offset(offset_index + index) unless index.zero?
- relation.limit(limit).to_a
+ if limit_value.nil? || index < limit_value
+ relation = relation.offset(offset_index + index) unless index.zero?
+ relation.limit(limit).to_a
+ else
+ []
+ end
end
end
@@ -572,8 +564,6 @@ module ActiveRecord
end
end
- private
-
def find_last(limit)
limit ? records.last(limit) : records.last
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 5f5d8ceea3..4ee413c805 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -3,7 +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"
module ActiveRecord
module QueryMethods
@@ -76,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),
@@ -243,9 +242,7 @@ module ActiveRecord
def select(*fields)
if block_given?
if fields.any?
- ActiveSupport::Deprecation.warn(<<-WARNING.squish)
- When select is called with a block, it ignores other arguments. This behavior is now deprecated and will result in an ArgumentError in Rails 5.1. You can safely remove the arguments to resolve the deprecation warning because they do not have any effect on the output of the call to the select method with a block.
- WARNING
+ raise ArgumentError, "`select' with block doesn't take arguments."
end
return super()
@@ -659,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
@@ -690,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
@@ -848,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.
@@ -958,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?
@@ -1192,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..417b24c7bb 100644
--- a/activerecord/lib/active_record/relation/where_clause.rb
+++ b/activerecord/lib/active_record/relation/where_clause.rb
@@ -25,10 +25,7 @@ module ActiveRecord
end
def except(*columns)
- WhereClause.new(
- predicates_except(columns),
- binds_except(columns),
- )
+ WhereClause.new(*except_predicates_and_binds(columns))
end
def or(other)
@@ -84,6 +81,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
@@ -132,20 +131,35 @@ module ActiveRecord
end
end
- def predicates_except(columns)
- predicates.reject do |node|
- case node
- when Arel::Nodes::Between, Arel::Nodes::In, Arel::Nodes::NotIn, Arel::Nodes::Equality, Arel::Nodes::NotEqual, Arel::Nodes::LessThan, Arel::Nodes::LessThanOrEqual, Arel::Nodes::GreaterThan, Arel::Nodes::GreaterThanOrEqual
- subrelation = (node.left.kind_of?(Arel::Attributes::Attribute) ? node.left : node.right)
- columns.include?(subrelation.name.to_s)
+ def except_predicates_and_binds(columns)
+ except_binds = []
+ binds_index = 0
+
+ predicates = self.predicates.reject do |node|
+ except = \
+ case node
+ when Arel::Nodes::Between, Arel::Nodes::In, Arel::Nodes::NotIn, Arel::Nodes::Equality, Arel::Nodes::NotEqual, Arel::Nodes::LessThan, Arel::Nodes::LessThanOrEqual, Arel::Nodes::GreaterThan, Arel::Nodes::GreaterThanOrEqual
+ binds_contains = node.grep(Arel::Nodes::BindParam).size
+ subrelation = (node.left.kind_of?(Arel::Attributes::Attribute) ? node.left : node.right)
+ columns.include?(subrelation.name.to_s)
+ end
+
+ if except && binds_contains > 0
+ (binds_index...(binds_index + binds_contains)).each do |i|
+ except_binds[i] = true
+ end
+
+ binds_index += binds_contains
end
+
+ except
end
- end
- def binds_except(columns)
- binds.reject do |attr|
- columns.include?(attr.name)
+ binds = self.binds.reject.with_index do |_, i|
+ except_binds[i]
end
+
+ [predicates, binds]
end
def predicates_with_wrapped_sql_literals
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