Serialize classes and modules with ActiveJob
This commit allows ActiveJob to serialize classes and modules without a custom serializer. This allows for workflows like: ``` class EmailJob < ApplicationJob queue_as :default def perform(template_class, *arguments) template_class.new(*arguments).send! end end module Email class FooTemplate ... end class BarTemplate ... end end EmailJob.perform_later(Email::FooTemplate, ...) EmailJob.perform_later(Email::BarTemplate, ...) ``` Currently this is only achieveable through a custom serializer or through constantizing in each instance.
This commit is contained in:
parent
352560308b
commit
fbebeabd6d
|
@ -1,3 +1,7 @@
|
|||
* Allow `Class` and `Module` instances to be serialized.
|
||||
|
||||
*Kevin Deisz*
|
||||
|
||||
* Log potential matches in `assert_enqueued_with` and `assert_performed_with`
|
||||
|
||||
*Gareth du Plooy*
|
||||
|
|
|
@ -15,6 +15,7 @@ module ActiveJob
|
|||
autoload :DateSerializer
|
||||
autoload :TimeWithZoneSerializer
|
||||
autoload :TimeSerializer
|
||||
autoload :ModuleSerializer
|
||||
|
||||
mattr_accessor :_additional_serializers
|
||||
self._additional_serializers = Set.new
|
||||
|
@ -58,6 +59,7 @@ module ActiveJob
|
|||
DateTimeSerializer,
|
||||
DateSerializer,
|
||||
TimeWithZoneSerializer,
|
||||
TimeSerializer
|
||||
TimeSerializer,
|
||||
ModuleSerializer
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module ActiveJob
|
||||
module Serializers
|
||||
class ModuleSerializer < ObjectSerializer # :nodoc:
|
||||
def serialize(constant)
|
||||
super("value" => constant.name)
|
||||
end
|
||||
|
||||
def deserialize(hash)
|
||||
hash["value"].constantize
|
||||
end
|
||||
|
||||
private
|
||||
def klass
|
||||
Module
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -8,6 +8,12 @@ require "jobs/kwargs_job"
|
|||
require "support/stubs/strong_parameters"
|
||||
|
||||
class ArgumentSerializationTest < ActiveSupport::TestCase
|
||||
module ModuleArgument
|
||||
class ClassArgument; end
|
||||
end
|
||||
|
||||
class ClassArgument; end
|
||||
|
||||
setup do
|
||||
@person = Person.find("5")
|
||||
end
|
||||
|
@ -18,14 +24,17 @@ class ArgumentSerializationTest < ActiveSupport::TestCase
|
|||
DateTime.new(2001, 2, 3, 4, 5, 6, "+03:00"),
|
||||
ActiveSupport::TimeWithZone.new(Time.utc(1999, 12, 31, 23, 59, 59), ActiveSupport::TimeZone["UTC"]),
|
||||
[ 1, "a" ],
|
||||
{ "a" => 1 }
|
||||
{ "a" => 1 },
|
||||
ModuleArgument,
|
||||
ModuleArgument::ClassArgument,
|
||||
ClassArgument
|
||||
].each do |arg|
|
||||
test "serializes #{arg.class} - #{arg} verbatim" do
|
||||
assert_arguments_unchanged arg
|
||||
end
|
||||
end
|
||||
|
||||
[ Object.new, self, Person.find("5").to_gid ].each do |arg|
|
||||
[ Object.new, Person.find("5").to_gid ].each do |arg|
|
||||
test "does not serialize #{arg.class}" do
|
||||
assert_raises ActiveJob::SerializationError do
|
||||
ActiveJob::Arguments.serialize [ arg ]
|
||||
|
|
|
@ -355,6 +355,8 @@ ActiveJob supports the following types of arguments by default:
|
|||
- `Hash` (Keys should be of `String` or `Symbol` type)
|
||||
- `ActiveSupport::HashWithIndifferentAccess`
|
||||
- `Array`
|
||||
- `Module`
|
||||
- `Class`
|
||||
|
||||
### GlobalID
|
||||
|
||||
|
|
Loading…
Reference in New Issue