module Hanami module Model module Plugins # Automatically set/update timestamp columns for create/update commands # # @since 0.7.0 # @api private module Timestamps # Takes the input and applies the timestamp transformation. # This is an "abstract class", please look at the subclasses for # specific behaviors. # # @since 0.7.0 # @api private class InputWithTimestamp < WrappingInput # Conventional timestamp names # # @since 0.7.0 # @api private TIMESTAMPS = [:created_at, :updated_at].freeze # @since 0.7.0 # @api private def initialize(relation, input) super columns = relation.columns.sort @timestamps = (columns & TIMESTAMPS) == TIMESTAMPS end # Processes the input # # @since 0.7.0 # @api private def [](value) return value unless timestamps? _touch(@input[value], Time.now) end protected # @since 0.7.0 # @api private def _touch(_value) raise NotImplementedError end private # @since 0.7.0 # @api private def timestamps? @timestamps end end # Updates updated_at timestamp for update commands # # @since 0.7.0 # @api private class InputWithUpdateTimestamp < InputWithTimestamp protected # @since 0.7.0 # @api private def _touch(value, now) value[:updated_at] ||= now value end end # Sets created_at and updated_at timestamps for create commands # # @since 0.7.0 # @api private class InputWithCreateTimestamp < InputWithUpdateTimestamp protected # @since 0.7.0 # @api private def _touch(value, now) super value[:created_at] ||= now value end end # Class interface # # @since 0.7.0 # @api private module ClassMethods # Build an input processor according to the current command (create or update). # # @since 0.7.0 # @api private def build(relation, options = {}) plugin = if self < ROM::Commands::Create InputWithCreateTimestamp else InputWithUpdateTimestamp end input(plugin.new(relation, input)) super(relation, options.merge(input: input)) end end # @since 0.7.0 # @api private def self.included(klass) super klass.extend ClassMethods end end end end end