Class: Marj::Record

Inherits:
ActiveRecord::Base
  • Object
show all
Defined in:
lib/marj/record.rb

Overview

The default ActiveRecord class.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.by_due_dateActiveRecord::Relation

Returns an ActiveRecord::Relation scope for jobs ordered by due date.

Jobs are ordered by the following criteria, in order:

  1. past or null scheduled_at before future scheduled_at

  2. ascending priority, nulls last

  3. ascending scheduled_at, nulls last

  4. ascending enqueued_at

Returns:

  • (ActiveRecord::Relation)


113
114
115
116
117
118
119
120
121
122
# File 'lib/marj/record.rb', line 113

def by_due_date
  order(
    Arel.sql(<<~SQL.squish, Time.now.utc)
      CASE WHEN scheduled_at IS NULL OR scheduled_at <= ? THEN 0 ELSE 1 END,
      CASE WHEN priority IS NULL THEN 1 ELSE 0 END, priority,
      CASE WHEN scheduled_at IS NULL THEN 1 ELSE 0 END, scheduled_at,
      enqueued_at
    SQL
  )
end

.dueActiveRecord::Relation

Returns an ActiveRecord::Relation scope for enqueued jobs with a scheduled_at that is either null or in the past.

Returns:

  • (ActiveRecord::Relation)


100
101
102
# File 'lib/marj/record.rb', line 100

def due
  where('scheduled_at IS NULL OR scheduled_at <= ?', Time.now.utc)
end

Instance Method Details

#to_jobActiveJob::Base

Returns a job object for this record which will update the database when successfully executed, enqueued or discarded.

Returns:

  • (ActiveJob::Base)


53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/marj/record.rb', line 53

def to_job
  # See register_callbacks for details on how callbacks are used.
  job = job_class.new.tap { register_callbacks(_1) }

  # ActiveJob::Base#deserialize expects serialized arguments. But the record arguments have already been
  # deserialized by a custom ActiveRecord serializer (see below). So instead we use the raw arguments string.
  job_data = attributes.merge('arguments' => JSON.parse(read_attribute_before_type_cast(:arguments)))

  # ActiveJob::Base#deserialize expects dates to be strings rather than Time objects.
  job_data = job_data.to_h { |k, v| [k, %w[enqueued_at scheduled_at].include?(k) ? v&.iso8601 : v] }

  job.deserialize(job_data)

  # ActiveJob deserializes arguments on demand when a job is performed. Until then they are empty. That's strange.
  # Instead, deserialize them now. Also, clear `serialized_arguments` to prevent ActiveJob from overwriting changes
  # to arguments when serializing later.
  job.arguments = arguments
  job.serialized_arguments = nil

  job
end