Skip to Content Skip to Search
Methods
S

Instance Public methods

sanitize_sql(condition)

sanitize_sql_array(ary)

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'"

Note that this sanitization method is not schema-aware, hence won’t do any type casting and will directly use the database adapter’s quote method. For MySQL specifically this means that numeric parameters will be quoted as strings to prevent query manipulation attacks.

sanitize_sql_array(["role = ?", 0])
# => "role = '0'"
# File activerecord/lib/active_record/sanitization.rb, line 152
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

sanitize_sql_for_assignment(assignments, default_table_name = table_name)

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'"

Note that this sanitization method is not schema-aware, hence won’t do any type casting and will directly use the database adapter’s quote method. For MySQL specifically this means that numeric parameters will be quoted as strings to prevent query manipulation attacks.

sanitize_sql_for_assignment(["role = ?", 0])
# => "role = '0'"
# File activerecord/lib/active_record/sanitization.rb, line 62
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
end

sanitize_sql_for_conditions(condition)

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'"

Note that this sanitization method is not schema-aware, hence won’t do any type casting and will directly use the database adapter’s quote method. For MySQL specifically this means that numeric parameters will be quoted as strings to prevent query manipulation attacks.

sanitize_sql_for_conditions(["role = ?", 0])
# => "role = '0'"
Also aliased as: sanitize_sql
# File activerecord/lib/active_record/sanitization.rb, line 30
def sanitize_sql_for_conditions(condition)
  return nil if condition.blank?

  case condition
  when Array; sanitize_sql_array(condition)
  else        condition
  end
end

sanitize_sql_for_order(condition)

Accepts an array, or string of SQL conditions and sanitizes them into a valid SQL fragment for an ORDER clause.

sanitize_sql_for_order([Arel.sql("field(id, ?)"), [1,3,2]])
# => "field(id, 1,3,2)"

sanitize_sql_for_order("id ASC")
# => "id ASC"
# File activerecord/lib/active_record/sanitization.rb, line 78
def sanitize_sql_for_order(condition)
  if condition.is_a?(Array) && condition.first.to_s.include?("?")
    disallow_raw_sql!(
      [condition.first],
      permit: connection.column_name_with_order_matcher
    )

    # Ensure we aren't dealing with a subclass of String that might
    # override methods we use (e.g. 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

sanitize_sql_hash_for_assignment(attrs, table)

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"
# File activerecord/lib/active_record/sanitization.rb, line 101
def sanitize_sql_hash_for_assignment(attrs, table)
  c = connection
  attrs.map do |attr, value|
    type = type_for_attribute(attr)
    value = type.serialize(type.cast(value))
    "#{c.quote_table_name_for_assignment(table, attr)} = #{c.quote(value)}"
  end.join(", ")
end

sanitize_sql_like(string, escape_character = "\\")

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 itself, “_” and “%”.

sanitize_sql_like("100% true!")
# => "100\\% true!"

sanitize_sql_like("snake_cased_string")
# => "snake\\_cased\\_string"

sanitize_sql_like("100% true!", "!")
# => "100!% true!!"

sanitize_sql_like("snake_cased_string", "!")
# => "snake!_cased!_string"
# File activerecord/lib/active_record/sanitization.rb, line 125
def sanitize_sql_like(string, escape_character = "\\")
  if string.include?(escape_character) && escape_character != "%" && escape_character != "_"
    string = string.gsub(escape_character, '\0\0')
  end

  string.gsub(/(?=[%_])/, escape_character)
end