class UpdateAllScope::UpdateAllScope

Constants

AREL_SUPPORT_JOIN_TABLE

Public Class Methods

new(model: nil, relation: nil) click to toggle source
# File lib/update_all_scope/update_all_scope.rb, line 8
def initialize(model: nil, relation: nil)
  @queries = []
  @relation = relation || model.class.where(id: model.id)
end

Public Instance Methods

do_query!() click to toggle source
# File lib/update_all_scope/update_all_scope.rb, line 24
def do_query!
  return 0 if @queries.empty?
  return @relation.update_all(updates_as_string)
end
klass() click to toggle source
# File lib/update_all_scope/update_all_scope.rb, line 33
def klass
  @relation.klass
end
to_arel() click to toggle source

See: github.com/rails/rails/blob/fc5dd0b85189811062c85520fd70de8389b55aeb/activerecord/lib/active_record/relation.rb#L315

# File lib/update_all_scope/update_all_scope.rb, line 38
def to_arel
  if @relation.eager_loading?
    scope = UpdateAllScope.new(model: model, relation: @relation.apply_join_dependency)
    return scope.update(updates_as_string).to_update_manager
  end

  stmt = new_arel_update_manager

  stmt.set Arel.sql(klass.send(:sanitize_sql_for_assignment, updates_as_string))
  stmt.table(stmt_table)
  stmt.key = arel_attribute(@relation.primary_key)

  if should_use_join_to_update?
    join_to_update(klass.connection, stmt, stmt.key)
  else
    stmt.take(@relation.arel.limit)
    stmt.order(*@relation.arel.orders)
    stmt.wheres = @relation.arel.constraints
  end

  return stmt
end
to_sql() click to toggle source
# File lib/update_all_scope/update_all_scope.rb, line 61
def to_sql
  connection = klass.connection
  sql, binds = to_sql_and_binds(connection, to_arel)
  type_casted_binds(connection, binds).each_with_index{|var, idx| sql = sql.gsub("$#{idx + 1}", connection.quote(var)) }
  return sql
end
update(query, *binding_values) click to toggle source
# File lib/update_all_scope/update_all_scope.rb, line 18
def update(query, *binding_values)
  args = binding_values.size > 0 ? [[query, *binding_values]] : [query]
  @queries << klass.send(:sanitize_sql_for_assignment, *args)
  return self
end
updates_as_string() click to toggle source
# File lib/update_all_scope/update_all_scope.rb, line 29
def updates_as_string
  @queries.join(',')
end
where(*args) click to toggle source
# File lib/update_all_scope/update_all_scope.rb, line 13
def where(*args)
  @relation = @relation.where(*args)
  return self
end

Private Instance Methods

accept(connection, ast) click to toggle source
# File lib/update_all_scope/update_all_scope.rb, line 109
def accept(connection, ast)
  return connection.visitor.accept(ast) if not connection.respond_to?(:collector) # For Rails 3
  return connection.visitor.accept(ast, connection.collector)
end
arel_attribute(name) click to toggle source
# File lib/update_all_scope/update_all_scope.rb, line 94
def arel_attribute(name)
  return @relation.arel_attribute(name) if @relation.respond_to?(:arel_attribute)
  name = klass.attribute_alias(name) if klass.respond_to?(:attribute_alias?) && klass.attribute_alias?(name) # attribute_alias? is not defined in Rails 3.
  return @relation.arel_table[name]
end
bind_values() click to toggle source
# File lib/update_all_scope/update_all_scope.rb, line 125
def bind_values
  return @relation.bound_attributes if @relation.respond_to?(:bound_attributes) # For Rails 5.1, 5.2
  return @relation.bind_values # For Rails 4.2
end
has_join_values?() click to toggle source
# File lib/update_all_scope/update_all_scope.rb, line 87
def has_join_values?
  return @relation.send(:has_join_values?) if @relation.respond_to?(:has_join_values?, true)
  return true if @relation.joins_values.any?
  return true if @relation.respond_to?(:left_outer_joins_values) and @relation.left_outer_joins_values.any?
  return false
end
join_to_update(connection, stmt, key) click to toggle source
# File lib/update_all_scope/update_all_scope.rb, line 120
def join_to_update(connection, stmt, key)
  return connection.join_to_update(stmt, @relation.arel) if connection.method(:join_to_update).arity == 2
  return connection.join_to_update(stmt, @relation.arel, key)
end
new_arel_update_manager() click to toggle source
# File lib/update_all_scope/update_all_scope.rb, line 82
def new_arel_update_manager
  return Arel::UpdateManager.new(ActiveRecord::Base) if Gem::Version.new(Arel::VERSION) < Gem::Version.new('7')
  return Arel::UpdateManager.new
end
should_use_join_to_update?() click to toggle source
# File lib/update_all_scope/update_all_scope.rb, line 70
def should_use_join_to_update?
  return false if AREL_SUPPORT_JOIN_TABLE
  return true if has_join_values?
  return true if @relation.offset_value
  return false
end
stmt_table() click to toggle source
# File lib/update_all_scope/update_all_scope.rb, line 77
def stmt_table
  return @relation.table if not AREL_SUPPORT_JOIN_TABLE
  return @relation.arel.join_sources.empty? ? @relation.table : @relation.arel.source
end
to_sql_and_binds(connection, arel_or_sql_string) click to toggle source
# File lib/update_all_scope/update_all_scope.rb, line 100
def to_sql_and_binds(connection, arel_or_sql_string)
  return connection.send(:to_sql_and_binds, arel_or_sql_string, []) if connection.respond_to?(:to_sql_and_binds, true)
  return [arel_or_sql_string.dup.freeze, []] if !arel_or_sql_string.respond_to?(:ast)

  sql = accept(connection, arel_or_sql_string.ast)
  return [sql.freeze, bind_values] if sql.is_a?(String)
  return [sql.compile(bind_values, connection), bind_values]
end
type_casted_binds(connection, binds) click to toggle source
# File lib/update_all_scope/update_all_scope.rb, line 114
def type_casted_binds(connection, binds)
  return connection.type_casted_binds(binds) if connection.respond_to?(:type_casted_binds)
  return binds.map{|column, value| connection.type_cast(value, column) } if binds.first.is_a?(Array)
  return binds.map{|attr| connection.type_cast(attr.value_for_database) }
end