From e360ac12315ed6b9eadca5bcc0d95dc766ba8523 Mon Sep 17 00:00:00 2001 From: Evgenii Pecherkin Date: Tue, 17 Oct 2017 16:05:05 +0400 Subject: Introduce serializers to ActiveJob --- guides/source/active_job_basics.md | 65 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) (limited to 'guides') diff --git a/guides/source/active_job_basics.md b/guides/source/active_job_basics.md index 914ef2c327..a7067cb97d 100644 --- a/guides/source/active_job_basics.md +++ b/guides/source/active_job_basics.md @@ -339,8 +339,21 @@ UserMailer.welcome(@user).deliver_later # Email will be localized to Esperanto. ``` -GlobalID --------- +Supported types for arguments +---------------------------- + +ActiveJob supports the following types of arguments by default: + + - Basic types (`NilClass`, `String`, `Integer`, `Fixnum`, `Bignum`, `Float`, `BigDecimal`, `TrueClass`, `FalseClass`) + - `Symbol` (`:foo`, `:bar`, ...) + - `ActiveSupport::Duration` (`1.day`, `2.weeks`, ...) + - Classes constants (`ActiveRecord::Base`, `MySpecialService`, ...) + - Struct instances (`Struct.new('Rectangle', :width, :height).new(12, 20)`, ...) + - `Hash`. Keys should be of `String` or `Symbol` type + - `ActiveSupport::HashWithIndifferentAccess` + - `Array` + +### GlobalID Active Job supports GlobalID for parameters. This makes it possible to pass live Active Record objects to your job instead of class/id pairs, which you then have @@ -368,6 +381,54 @@ end This works with any class that mixes in `GlobalID::Identification`, which by default has been mixed into Active Record classes. +### Serializers + +You can extend list of supported types for arguments. You just need to define your own serializer. + +```ruby +class MySpecialSerializer + class << self + # Check if this object should be serialized using this serializer + def serialize?(argument) + argument.is_a? MySpecialValueObject + end + + # Convert an object to a simpler representative using supported object types. + # The recommended representative is a Hash with a specific key. Keys can be of basic types only + def serialize(object) + { + key => ActiveJob::Serializers.serialize(object.value) + 'another_attribute' => ActiveJob::Serializers.serialize(object.another_attribute) + } + end + + # Check if this serialized value be deserialized using this serializer + def deserialize?(argument) + argument.is_a?(Hash) && argument.keys == [key, 'another_attribute'] + end + + # Convert serialized value into a proper object + def deserialize(object) + value = ActiveJob::Serializers.deserialize(object[key]) + another_attribute = ActiveJob::Serializers.deserialize(object['another_attribute']) + MySpecialValueObject.new value, another_attribute + end + + # Define this method if you are using a hash as a representative. + # This key will be added to a list of restricted keys for hashes. Use basic types only + def key + "_aj_custom_dummy_value_object" + end + end +end +``` + +And now you just need to add this serializer to a list: + +```ruby +ActiveJob::Base.add_serializers(MySpecialSerializer) +``` + Exceptions ---------- -- cgit v1.2.3 From 3785a5729959a838bb13f2d298a59e12e1844f74 Mon Sep 17 00:00:00 2001 From: Evgenii Pecherkin Date: Mon, 23 Oct 2017 17:29:28 +0400 Subject: Remove non-default serializers --- guides/source/active_job_basics.md | 4 ---- 1 file changed, 4 deletions(-) (limited to 'guides') diff --git a/guides/source/active_job_basics.md b/guides/source/active_job_basics.md index a7067cb97d..eea64f9367 100644 --- a/guides/source/active_job_basics.md +++ b/guides/source/active_job_basics.md @@ -345,10 +345,6 @@ Supported types for arguments ActiveJob supports the following types of arguments by default: - Basic types (`NilClass`, `String`, `Integer`, `Fixnum`, `Bignum`, `Float`, `BigDecimal`, `TrueClass`, `FalseClass`) - - `Symbol` (`:foo`, `:bar`, ...) - - `ActiveSupport::Duration` (`1.day`, `2.weeks`, ...) - - Classes constants (`ActiveRecord::Base`, `MySpecialService`, ...) - - Struct instances (`Struct.new('Rectangle', :width, :height).new(12, 20)`, ...) - `Hash`. Keys should be of `String` or `Symbol` type - `ActiveSupport::HashWithIndifferentAccess` - `Array` -- cgit v1.2.3 From a5f7357a3dff2617ba13a274feb8d8ac2492f26a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Fri, 9 Feb 2018 17:27:01 -0500 Subject: Add configuration to set custom serializers --- guides/source/configuring.md | 2 ++ 1 file changed, 2 insertions(+) (limited to 'guides') diff --git a/guides/source/configuring.md b/guides/source/configuring.md index b0f39e7ab5..fd747c1686 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -741,6 +741,8 @@ There are a few configuration options available in Active Support: * `config.active_job.logger` accepts a logger conforming to the interface of Log4r or the default Ruby Logger class, which is then used to log information from Active Job. You can retrieve this logger by calling `logger` on either an Active Job class or an Active Job instance. Set to `nil` to disable logging. +* `config.active_job.custom_serializers` allows to set custom argument serializers. Defaults to `[]`. + ### Configuring Action Cable * `config.action_cable.url` accepts a string for the URL for where -- cgit v1.2.3 From 71721dc1c9b769d3c06317122dc88cad4a346580 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Fri, 9 Feb 2018 17:27:39 -0500 Subject: Improve documentation on custom serializers --- guides/source/active_job_basics.md | 43 +++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 22 deletions(-) (limited to 'guides') diff --git a/guides/source/active_job_basics.md b/guides/source/active_job_basics.md index eea64f9367..0ee522e23d 100644 --- a/guides/source/active_job_basics.md +++ b/guides/source/active_job_basics.md @@ -345,6 +345,12 @@ Supported types for arguments ActiveJob supports the following types of arguments by default: - Basic types (`NilClass`, `String`, `Integer`, `Fixnum`, `Bignum`, `Float`, `BigDecimal`, `TrueClass`, `FalseClass`) + - `Symbol + - `ActiveSupport::Duration` + - `Date` + - `Time` + - `DateTime` + - `ActiveSupport::TimeWithZone` - `Hash`. Keys should be of `String` or `Symbol` type - `ActiveSupport::HashWithIndifferentAccess` - `Array` @@ -382,38 +388,31 @@ by default has been mixed into Active Record classes. You can extend list of supported types for arguments. You just need to define your own serializer. ```ruby -class MySpecialSerializer - class << self - # Check if this object should be serialized using this serializer +class MoneySerializer < ActiveJob::Serializers::ObjectSerializer + # Check if this object should be serialized using this serializer. def serialize?(argument) - argument.is_a? MySpecialValueObject + argument.is_a? Money end # Convert an object to a simpler representative using supported object types. - # The recommended representative is a Hash with a specific key. Keys can be of basic types only + # The recommended representative is a Hash with a specific key. Keys can be of basic types only. + # You should call `super` to add the custom serializer type to the hash def serialize(object) - { - key => ActiveJob::Serializers.serialize(object.value) - 'another_attribute' => ActiveJob::Serializers.serialize(object.another_attribute) - } + super( + "cents" => object.cents, + "currency" => object.currency + ) end - # Check if this serialized value be deserialized using this serializer + # Check if this serialized value be deserialized using this serializer. + # ActiveJob::Serializers::ObjectSerializer#deserialize? already take care of this. def deserialize?(argument) - argument.is_a?(Hash) && argument.keys == [key, 'another_attribute'] + super end # Convert serialized value into a proper object - def deserialize(object) - value = ActiveJob::Serializers.deserialize(object[key]) - another_attribute = ActiveJob::Serializers.deserialize(object['another_attribute']) - MySpecialValueObject.new value, another_attribute - end - - # Define this method if you are using a hash as a representative. - # This key will be added to a list of restricted keys for hashes. Use basic types only - def key - "_aj_custom_dummy_value_object" + def deserialize(hash) + Money.new hash["cents"], hash["currency"] end end end @@ -422,7 +421,7 @@ end And now you just need to add this serializer to a list: ```ruby -ActiveJob::Base.add_serializers(MySpecialSerializer) +Rails.application.config.active_job.custom_serializers << MySpecialSerializer ``` -- cgit v1.2.3 From 69645cba727dfa1c18c666d2a2f1c0dedffde938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Mon, 12 Feb 2018 14:16:41 -0500 Subject: Simplify the implementation of custom argument serializers We can speed up things for the supported types by keeping the code in the way it was. We can also avoid to loop trough all serializers in the deserialization by trying to access the class already in the Hash. We could also speed up the custom serialization if we define the class that is going to be serialized when registering the serializers, but that will remove the possibility of defining a serialzer for a superclass and have the subclass serialized using it. --- guides/source/active_job_basics.md | 6 ------ 1 file changed, 6 deletions(-) (limited to 'guides') diff --git a/guides/source/active_job_basics.md b/guides/source/active_job_basics.md index 0ee522e23d..92a04c585f 100644 --- a/guides/source/active_job_basics.md +++ b/guides/source/active_job_basics.md @@ -404,12 +404,6 @@ class MoneySerializer < ActiveJob::Serializers::ObjectSerializer ) end - # Check if this serialized value be deserialized using this serializer. - # ActiveJob::Serializers::ObjectSerializer#deserialize? already take care of this. - def deserialize?(argument) - super - end - # Convert serialized value into a proper object def deserialize(hash) Money.new hash["cents"], hash["currency"] -- cgit v1.2.3