From 9d43a84f73c1b3853a91d052a462ee60eccaf957 Mon Sep 17 00:00:00 2001
From: "yuuji.yaginuma" <yuuji.yaginuma@gmail.com>
Date: Mon, 11 Dec 2017 11:41:27 +0900
Subject: Make `sanitize_sql_` methods public

Currently, sanitize methods are private. So need `send` to use from
outside class.
However, sometimes want to use sanitize methods from outside Class when
want to generate SQL including multiple tables like search.
In order to avoid using `send` in such a case, changed methods to public.
---
 activerecord/lib/active_record/relation.rb         |   2 +-
 .../lib/active_record/relation/query_methods.rb    |   2 +-
 .../active_record/relation/where_clause_factory.rb |   2 +-
 activerecord/lib/active_record/sanitization.rb     | 249 ++++++++++-----------
 4 files changed, 127 insertions(+), 128 deletions(-)

(limited to 'activerecord/lib')

diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index 081ef5771f..9ae40e4f4d 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -306,7 +306,7 @@ module ActiveRecord
 
       stmt = Arel::UpdateManager.new
 
-      stmt.set Arel.sql(@klass.send(:sanitize_sql_for_assignment, updates))
+      stmt.set Arel.sql(@klass.sanitize_sql_for_assignment(updates))
       stmt.table(table)
 
       if has_join_values?
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 808f796abe..6b3ff3d610 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -1121,7 +1121,7 @@ module ActiveRecord
 
       def preprocess_order_args(order_args)
         order_args.map! do |arg|
-          klass.send(:sanitize_sql_for_order, arg)
+          klass.sanitize_sql_for_order(arg)
         end
         order_args.flatten!
 
diff --git a/activerecord/lib/active_record/relation/where_clause_factory.rb b/activerecord/lib/active_record/relation/where_clause_factory.rb
index 1374785354..4ae94f4bfe 100644
--- a/activerecord/lib/active_record/relation/where_clause_factory.rb
+++ b/activerecord/lib/active_record/relation/where_clause_factory.rb
@@ -11,7 +11,7 @@ module ActiveRecord
       def build(opts, other)
         case opts
         when String, Array
-          parts = [klass.send(:sanitize_sql, other.empty? ? opts : ([opts] + other))]
+          parts = [klass.sanitize_sql(other.empty? ? opts : ([opts] + other))]
         when Hash
           attributes = predicate_builder.resolve_column_aliases(opts)
           attributes = klass.send(:expand_hash_conditions_for_aggregates, attributes)
diff --git a/activerecord/lib/active_record/sanitization.rb b/activerecord/lib/active_record/sanitization.rb
index 21f8bc7cb2..58da106092 100644
--- a/activerecord/lib/active_record/sanitization.rb
+++ b/activerecord/lib/active_record/sanitization.rb
@@ -5,80 +5,135 @@ module ActiveRecord
     extend ActiveSupport::Concern
 
     module ClassMethods
-      private
-
-        # Accepts an array or string of SQL conditions and sanitizes
-        # them into a valid SQL fragment for a WHERE clause.
-        #
-        #   sanitize_sql_for_conditions(["name=? and group_id=?", "foo'bar", 4])
-        #   # => "name='foo''bar' and group_id=4"
-        #
-        #   sanitize_sql_for_conditions(["name=:name and group_id=:group_id", name: "foo'bar", group_id: 4])
-        #   # => "name='foo''bar' and group_id='4'"
-        #
-        #   sanitize_sql_for_conditions(["name='%s' and group_id='%s'", "foo'bar", 4])
-        #   # => "name='foo''bar' and group_id='4'"
-        #
-        #   sanitize_sql_for_conditions("name='foo''bar' and group_id='4'")
-        #   # => "name='foo''bar' and group_id='4'"
-        def sanitize_sql_for_conditions(condition) # :doc:
-          return nil if condition.blank?
-
-          case condition
-          when Array; sanitize_sql_array(condition)
-          else        condition
-          end
+      # Accepts an array or string of SQL conditions and sanitizes
+      # them into a valid SQL fragment for a WHERE clause.
+      #
+      #   sanitize_sql_for_conditions(["name=? and group_id=?", "foo'bar", 4])
+      #   # => "name='foo''bar' and group_id=4"
+      #
+      #   sanitize_sql_for_conditions(["name=:name and group_id=:group_id", name: "foo'bar", group_id: 4])
+      #   # => "name='foo''bar' and group_id='4'"
+      #
+      #   sanitize_sql_for_conditions(["name='%s' and group_id='%s'", "foo'bar", 4])
+      #   # => "name='foo''bar' and group_id='4'"
+      #
+      #   sanitize_sql_for_conditions("name='foo''bar' and group_id='4'")
+      #   # => "name='foo''bar' and group_id='4'"
+      def sanitize_sql_for_conditions(condition)
+        return nil if condition.blank?
+
+        case condition
+        when Array; sanitize_sql_array(condition)
+        else        condition
         end
-        alias :sanitize_sql :sanitize_sql_for_conditions
-
-        # Accepts an array, hash, or string of SQL conditions and sanitizes
-        # them into a valid SQL fragment for a SET clause.
-        #
-        #   sanitize_sql_for_assignment(["name=? and group_id=?", nil, 4])
-        #   # => "name=NULL and group_id=4"
-        #
-        #   sanitize_sql_for_assignment(["name=:name and group_id=:group_id", name: nil, group_id: 4])
-        #   # => "name=NULL and group_id=4"
-        #
-        #   Post.send(:sanitize_sql_for_assignment, { name: nil, group_id: 4 })
-        #   # => "`posts`.`name` = NULL, `posts`.`group_id` = 4"
-        #
-        #   sanitize_sql_for_assignment("name=NULL and group_id='4'")
-        #   # => "name=NULL and group_id='4'"
-        def sanitize_sql_for_assignment(assignments, default_table_name = table_name) # :doc:
-          case assignments
-          when Array; sanitize_sql_array(assignments)
-          when Hash;  sanitize_sql_hash_for_assignment(assignments, default_table_name)
-          else        assignments
-          end
+      end
+      alias :sanitize_sql :sanitize_sql_for_conditions
+
+      # Accepts an array, hash, or string of SQL conditions and sanitizes
+      # them into a valid SQL fragment for a SET clause.
+      #
+      #   sanitize_sql_for_assignment(["name=? and group_id=?", nil, 4])
+      #   # => "name=NULL and group_id=4"
+      #
+      #   sanitize_sql_for_assignment(["name=:name and group_id=:group_id", name: nil, group_id: 4])
+      #   # => "name=NULL and group_id=4"
+      #
+      #   Post.sanitize_sql_for_assignment({ name: nil, group_id: 4 })
+      #   # => "`posts`.`name` = NULL, `posts`.`group_id` = 4"
+      #
+      #   sanitize_sql_for_assignment("name=NULL and group_id='4'")
+      #   # => "name=NULL and group_id='4'"
+      def sanitize_sql_for_assignment(assignments, default_table_name = table_name)
+        case assignments
+        when Array; sanitize_sql_array(assignments)
+        when Hash;  sanitize_sql_hash_for_assignment(assignments, default_table_name)
+        else        assignments
         end
-
-        # Accepts an array, or string of SQL conditions and sanitizes
-        # them into a valid SQL fragment for an ORDER clause.
-        #
-        #   sanitize_sql_for_order(["field(id, ?)", [1,3,2]])
-        #   # => "field(id, 1,3,2)"
-        #
-        #   sanitize_sql_for_order("id ASC")
-        #   # => "id ASC"
-        def sanitize_sql_for_order(condition) # :doc:
-          if condition.is_a?(Array) && condition.first.to_s.include?("?")
-            enforce_raw_sql_whitelist([condition.first],
-              whitelist: AttributeMethods::ClassMethods::COLUMN_NAME_ORDER_WHITELIST
-            )
-
-            # Ensure we aren't dealing with a subclass of String that might
-            # override methods we use (eg. Arel::Nodes::SqlLiteral).
-            if condition.first.kind_of?(String) && !condition.first.instance_of?(String)
-              condition = [String.new(condition.first), *condition[1..-1]]
-            end
-
-            Arel.sql(sanitize_sql_array(condition))
-          else
-            condition
+      end
+
+      # Accepts an array, or string of SQL conditions and sanitizes
+      # them into a valid SQL fragment for an ORDER clause.
+      #
+      #   sanitize_sql_for_order(["field(id, ?)", [1,3,2]])
+      #   # => "field(id, 1,3,2)"
+      #
+      #   sanitize_sql_for_order("id ASC")
+      #   # => "id ASC"
+      def sanitize_sql_for_order(condition)
+        if condition.is_a?(Array) && condition.first.to_s.include?("?")
+          enforce_raw_sql_whitelist([condition.first],
+            whitelist: AttributeMethods::ClassMethods::COLUMN_NAME_ORDER_WHITELIST
+          )
+
+          # Ensure we aren't dealing with a subclass of String that might
+          # override methods we use (eg. Arel::Nodes::SqlLiteral).
+          if condition.first.kind_of?(String) && !condition.first.instance_of?(String)
+            condition = [String.new(condition.first), *condition[1..-1]]
           end
+
+          Arel.sql(sanitize_sql_array(condition))
+        else
+          condition
         end
+      end
+
+      # Sanitizes a hash of attribute/value pairs into SQL conditions for a SET clause.
+      #
+      #   sanitize_sql_hash_for_assignment({ status: nil, group_id: 1 }, "posts")
+      #   # => "`posts`.`status` = NULL, `posts`.`group_id` = 1"
+      def sanitize_sql_hash_for_assignment(attrs, table)
+        c = connection
+        attrs.map do |attr, value|
+          type = type_for_attribute(attr.to_s)
+          value = type.serialize(type.cast(value))
+          "#{c.quote_table_name_for_assignment(table, attr)} = #{c.quote(value)}"
+        end.join(", ")
+      end
+
+      # Sanitizes a +string+ so that it is safe to use within an SQL
+      # LIKE statement. This method uses +escape_character+ to escape all occurrences of "\", "_" and "%".
+      #
+      #   sanitize_sql_like("100%")
+      #   # => "100\\%"
+      #
+      #   sanitize_sql_like("snake_cased_string")
+      #   # => "snake\\_cased\\_string"
+      #
+      #   sanitize_sql_like("100%", "!")
+      #   # => "100!%"
+      #
+      #   sanitize_sql_like("snake_cased_string", "!")
+      #   # => "snake!_cased!_string"
+      def sanitize_sql_like(string, escape_character = "\\")
+        pattern = Regexp.union(escape_character, "%", "_")
+        string.gsub(pattern) { |x| [escape_character, x].join }
+      end
+
+      # Accepts an array of conditions. The array has each value
+      # sanitized and interpolated into the SQL statement.
+      #
+      #   sanitize_sql_array(["name=? and group_id=?", "foo'bar", 4])
+      #   # => "name='foo''bar' and group_id=4"
+      #
+      #   sanitize_sql_array(["name=:name and group_id=:group_id", name: "foo'bar", group_id: 4])
+      #   # => "name='foo''bar' and group_id=4"
+      #
+      #   sanitize_sql_array(["name='%s' and group_id='%s'", "foo'bar", 4])
+      #   # => "name='foo''bar' and group_id='4'"
+      def sanitize_sql_array(ary)
+        statement, *values = ary
+        if values.first.is_a?(Hash) && /:\w+/.match?(statement)
+          replace_named_bind_variables(statement, values.first)
+        elsif statement.include?("?")
+          replace_bind_variables(statement, values)
+        elsif statement.blank?
+          statement
+        else
+          statement % values.collect { |value| connection.quote_string(value.to_s) }
+        end
+      end
 
+      private
         # Accepts a hash of SQL conditions and replaces those attributes
         # that correspond to a {#composed_of}[rdoc-ref:Aggregations::ClassMethods#composed_of]
         # relationship with their expanded aggregate attribute values.
@@ -113,62 +168,6 @@ module ActiveRecord
           expanded_attrs
         end
 
-        # Sanitizes a hash of attribute/value pairs into SQL conditions for a SET clause.
-        #
-        #   sanitize_sql_hash_for_assignment({ status: nil, group_id: 1 }, "posts")
-        #   # => "`posts`.`status` = NULL, `posts`.`group_id` = 1"
-        def sanitize_sql_hash_for_assignment(attrs, table) # :doc:
-          c = connection
-          attrs.map do |attr, value|
-            type = type_for_attribute(attr.to_s)
-            value = type.serialize(type.cast(value))
-            "#{c.quote_table_name_for_assignment(table, attr)} = #{c.quote(value)}"
-          end.join(", ")
-        end
-
-        # Sanitizes a +string+ so that it is safe to use within an SQL
-        # LIKE statement. This method uses +escape_character+ to escape all occurrences of "\", "_" and "%".
-        #
-        #   sanitize_sql_like("100%")
-        #   # => "100\\%"
-        #
-        #   sanitize_sql_like("snake_cased_string")
-        #   # => "snake\\_cased\\_string"
-        #
-        #   sanitize_sql_like("100%", "!")
-        #   # => "100!%"
-        #
-        #   sanitize_sql_like("snake_cased_string", "!")
-        #   # => "snake!_cased!_string"
-        def sanitize_sql_like(string, escape_character = "\\") # :doc:
-          pattern = Regexp.union(escape_character, "%", "_")
-          string.gsub(pattern) { |x| [escape_character, x].join }
-        end
-
-        # Accepts an array of conditions. The array has each value
-        # sanitized and interpolated into the SQL statement.
-        #
-        #   sanitize_sql_array(["name=? and group_id=?", "foo'bar", 4])
-        #   # => "name='foo''bar' and group_id=4"
-        #
-        #   sanitize_sql_array(["name=:name and group_id=:group_id", name: "foo'bar", group_id: 4])
-        #   # => "name='foo''bar' and group_id=4"
-        #
-        #   sanitize_sql_array(["name='%s' and group_id='%s'", "foo'bar", 4])
-        #   # => "name='foo''bar' and group_id='4'"
-        def sanitize_sql_array(ary) # :doc:
-          statement, *values = ary
-          if values.first.is_a?(Hash) && /:\w+/.match?(statement)
-            replace_named_bind_variables(statement, values.first)
-          elsif statement.include?("?")
-            replace_bind_variables(statement, values)
-          elsif statement.blank?
-            statement
-          else
-            statement % values.collect { |value| connection.quote_string(value.to_s) }
-          end
-        end
-
         def replace_bind_variables(statement, values)
           raise_if_bind_arity_mismatch(statement, statement.count("?"), values.size)
           bound = values.dup
-- 
cgit v1.2.3