Sha256: f6123d1e45fdd723c41978fc47fd718f7eeca93e1f0cb94dc87ca662d9702515

Contents?: true

Size: 1.74 KB

Versions: 1

Compression:

Stored size: 1.74 KB

Contents

# frozen_string_literal: true

require 'activerecord-import'
require 'rails_or'
require 'atomically/patches/none' if not ActiveRecord::Base.respond_to?(:none)
require 'atomically/patches/from' if Gem::Version.new(ActiveRecord::VERSION::STRING) < Gem::Version.new('4.0.0')

class Atomically::QueryService
  def initialize(klass, relation: nil)
    @klass = klass
    @relation = relation || @klass
  end

  def create_or_plus(columns, data, update_columns)
    @klass.import(columns, data, on_duplicate_key_update: on_duplicate_key_plus_sql(update_columns))
  end

  def pay_all(hash, update_columns, primary_key: :id) # { id => pay_count }
    return 0 if hash.blank?

    update_columns = update_columns.map(&method(:quote_column))

    query = hash.inject(@klass.none) do |relation, (id, pay_count)|
      condition = @relation.where(primary_key => id)
      update_columns.each{|s| condition = condition.where("#{s} >= ?", pay_count) }
      next relation.or(condition)
    end

    raw_when_sql = hash.map{|id, pay_count| "WHEN #{sanitize(id)} THEN #{sanitize(-pay_count)}" }.join("\n")
    update_sqls = update_columns.map.with_index do |column, idx|
      value = idx == 0 ? "(@change := \nCASE #{quote_column(primary_key)}\n#{raw_when_sql}\nEND)" : '@change'
      next "#{column} = #{column} + #{value}"
    end

    return query.where("(#{@klass.from(query).select('COUNT(*)').to_sql}) = ?", hash.size)
                .update_all(update_sqls.join(', '))
  end

  private

  def on_duplicate_key_plus_sql( columns)
    columns.lazy.map(&method(:quote_column)).map{|s| "#{s} = #{s} + VALUES(#{s})" }.force.join(', ')
  end

  def quote_column(column)
    @klass.connection.quote_column_name(column)
  end

  def sanitize(value)
    @klass.connection.quote(value)
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
atomically-1.0.1 lib/atomically/query_service.rb