diff --git a/app/models/card/entropic.rb b/app/models/card/entropic.rb index 23e33c18a..b238156f9 100644 --- a/app/models/card/entropic.rb +++ b/app/models/card/entropic.rb @@ -7,7 +7,7 @@ module Card::Entropic .joins(board: :account) .left_outer_joins(board: :entropy) .joins("LEFT OUTER JOIN entropies AS account_entropies ON account_entropies.account_id = accounts.id AND account_entropies.container_type = 'Account' AND account_entropies.container_id = accounts.id") - .where("last_active_at <= DATE_SUB(?, INTERVAL COALESCE(entropies.auto_postpone_period, account_entropies.auto_postpone_period) SECOND)", Time.now) + .where("last_active_at <= #{connection.date_subtract('?', 'COALESCE(entropies.auto_postpone_period, account_entropies.auto_postpone_period)')}", Time.now) end scope :postponing_soon, -> do @@ -16,8 +16,8 @@ module Card::Entropic .joins(board: :account) .left_outer_joins(board: :entropy) .joins("LEFT OUTER JOIN entropies AS account_entropies ON account_entropies.account_id = accounts.id AND account_entropies.container_type = 'Account' AND account_entropies.container_id = accounts.id") - .where("last_active_at > DATE_SUB(?, INTERVAL COALESCE(entropies.auto_postpone_period, account_entropies.auto_postpone_period) SECOND)", now) - .where("last_active_at <= DATE_SUB(?, INTERVAL CAST(COALESCE(entropies.auto_postpone_period, account_entropies.auto_postpone_period) * 0.75 AS SIGNED) SECOND)", now) + .where("last_active_at > #{connection.date_subtract('?', 'COALESCE(entropies.auto_postpone_period, account_entropies.auto_postpone_period)')}", now) + .where("last_active_at <= #{connection.date_subtract('?', 'COALESCE(entropies.auto_postpone_period, account_entropies.auto_postpone_period) * 0.75')}", now) end delegate :auto_postpone_period, to: :board diff --git a/lib/rails_ext/active_record_date_arithmetic.rb b/lib/rails_ext/active_record_date_arithmetic.rb new file mode 100644 index 000000000..5121c3f12 --- /dev/null +++ b/lib/rails_ext/active_record_date_arithmetic.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +# Adds database-agnostic date arithmetic methods to ActiveRecord adapters. +# This allows code to perform date calculations without checking which database adapter is in use. +# +# Usage: +# connection.date_subtract("created_at", "3600") +# # MySQL/Trilogy: "DATE_SUB(created_at, INTERVAL 3600 SECOND)" +# # SQLite: "datetime(created_at, '-' || (3600) || ' seconds')" + +# Module for MySQL-based adapters (Trilogy, Mysql2, etc.) +module MysqlDateArithmetic + # Generates SQL for subtracting seconds from a date/time column in MySQL. + # + # @param date_column [String] The date/time column or expression + # @param seconds_expression [String] SQL expression that evaluates to number of seconds + # @return [String] MySQL DATE_SUB expression + # + # Example: + # date_subtract("last_active_at", "COALESCE(auto_postpone_period, 3600)") + # # => "DATE_SUB(last_active_at, INTERVAL COALESCE(auto_postpone_period, 3600) SECOND)" + def date_subtract(date_column, seconds_expression) + "DATE_SUB(#{date_column}, INTERVAL #{seconds_expression} SECOND)" + end +end + +# Module for SQLite adapter +module SqliteDateArithmetic + # Generates SQL for subtracting seconds from a date/time column in SQLite. + # + # @param date_column [String] The date/time column or expression + # @param seconds_expression [String] SQL expression that evaluates to number of seconds + # @return [String] SQLite datetime expression + # + # Example: + # date_subtract("last_active_at", "COALESCE(auto_postpone_period, 3600)") + # # => "datetime(last_active_at, '-' || (COALESCE(auto_postpone_period, 3600)) || ' seconds')" + def date_subtract(date_column, seconds_expression) + "datetime(#{date_column}, '-' || (#{seconds_expression}) || ' seconds')" + end +end + +ActiveSupport.on_load(:active_record) do + # Prepend MySQL date arithmetic to AbstractMysqlAdapter (covers Trilogy, Mysql2, etc.) + if defined?(ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter) + ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter.prepend(MysqlDateArithmetic) + end + + # Prepend SQLite date arithmetic to SQLite3Adapter + if defined?(ActiveRecord::ConnectionAdapters::SQLite3Adapter) + ActiveRecord::ConnectionAdapters::SQLite3Adapter.prepend(SqliteDateArithmetic) + end +end