Skip to content

Commit

Permalink
Improved integration with Global ID
Browse files Browse the repository at this point in the history
Implementing `Decorator.find` improves compatibility with Global ID and
allows one to use decorated objects in jobs seamlessly.

Resolves #663.
Improves #817.
  • Loading branch information
Alexander-Senko committed Feb 6, 2024
1 parent 26a18c8 commit 5b647d2
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 16 deletions.
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -652,9 +652,8 @@ you can include this module manually.
[Active Job](http://edgeguides.rubyonrails.org/active_job_basics.html) allows you to pass ActiveRecord
objects to background tasks directly and performs the necessary serialization and deserialization. In
order to do this, arguments to a background job must implement [Global ID](https://github.com/rails/globalid).
Decorated objects implement Global ID by delegating to the object they are decorating. This means
you can pass decorated objects to background jobs, however, the object won't be decorated when it is
deserialized.
Decorators implement Global ID.
This means you can pass decorated objects to background jobs, and get them just as decorated when deserialized.

## Contributors

Expand Down
14 changes: 9 additions & 5 deletions lib/draper/compatibility/global_id.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,21 @@ module Compatibility
# and deserialization. In order to do this, arguments to a background job must implement
# [Global ID](https://github.com/rails/globalid).
#
# This compatibility patch implements Global ID for decorated objects by delegating to the object
# that is decorated. This means you can pass decorated objects to background jobs, but
# the object won't be decorated when it is deserialized. This patch is meant as an intermediate
# fix until we can find a way to deserialize the decorated object correctly.
# This compatibility patch implements Global ID for decorated objects by defining `.find(id)`
# class method that uses the original one and decorates the result.
# This means you can pass decorated objects to background jobs and they will be decorated when
# deserialized.
module GlobalID
extend ActiveSupport::Concern

included do
include ::GlobalID::Identification
end

delegate :to_global_id, :to_signed_global_id, to: :object
class_methods do
def find(*args)
object_class.find(*args).decorate
end
end
end
end
Expand Down
9 changes: 9 additions & 0 deletions spec/dummy/spec/decorators/post_decorator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,13 @@
it "uses a test view context from BaseController" do
expect(Draper::ViewContext.current.controller).to be_an BaseController
end

describe 'Global ID' do
it { expect(GlobalID::Locator.locate decorator.to_gid).to eq decorator }
it { expect(GlobalID::Locator.locate decorator.to_gid).to be_decorated }
it { expect(GlobalID::Locator.locate object.to_gid).not_to be_decorated }
it { expect(GlobalID::Locator.locate_signed decorator.to_sgid).to eq decorator }
it { expect(GlobalID::Locator.locate_signed decorator.to_sgid).to be_decorated }
it { expect(GlobalID::Locator.locate_signed object.to_sgid).not_to be_decorated }
end
end
4 changes: 3 additions & 1 deletion spec/dummy/spec/jobs/publish_post_job_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
subject(:job) { described_class.perform_later(post) }

it 'queues the job' do
expect { job }.to have_enqueued_job(described_class).with(post.object)
expect { job }.to have_enqueued_job(described_class).with { |post|
expect(post).to be_decorated
}
end
end
7 changes: 0 additions & 7 deletions spec/dummy/spec/models/post_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,4 @@
it_behaves_like 'a decoratable model'

it { should be_a ApplicationRecord }

describe '#to_global_id' do
let(:post) { Post.create }
subject { post.to_global_id }

it { is_expected.to eq post.decorate.to_global_id }
end
end

0 comments on commit 5b647d2

Please sign in to comment.