Skip to content

Commit 9822694

Browse files
authored
Fix compatibility with Rails delegated_type (#3)
* Fix compatibility with Rails delegated_type belongs_to accepts an optional scope as the second argument. safe_polymorphic was not forwarding this argument correctly, causing an ArgumentError when used with APIs like delegated_type. * Add suggestions
1 parent 43629e3 commit 9822694

7 files changed

Lines changed: 83 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
## [Unreleased]
22

3+
- Fix compatibility with Rails `delegated_type` by accepting optional `scope` parameter in `safe_polymorphic` method signature
4+
35
## [0.1.0] - 2022-12-28
46

57
- Initial release
@@ -11,4 +13,4 @@
1113

1214
## [0.1.2] - 2022-12-28
1315

14-
- Fix issue that forced to declare the I18n locale (`class_not_allowed`) in each project using this gem instead of using the default locale included in the gem
16+
- Fix issue that forced to declare the I18n locale (`class_not_allowed`) in each project using this gem instead of using the default locale included in the gem

Gemfile.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ GEM
114114
PLATFORMS
115115
arm64-darwin-21
116116
arm64-darwin-23
117+
arm64-darwin-24
117118
x86_64-linux
118119

119120
DEPENDENCIES

lib/safe_polymorphic/associations.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ class << base
1111
end
1212

1313
module ClassMethods
14-
def safe_polymorphic(name, **options)
15-
unsafe_polymorphic name, **options
14+
def safe_polymorphic(name, scope = nil, **options)
15+
unsafe_polymorphic name, scope, **options
1616
polymorphic = options[:polymorphic]
1717

1818
return unless polymorphic.present? && polymorphic.class != TrueClass

spec/safe_polymorphic/associations_spec.rb

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,4 +205,65 @@
205205
end
206206
end
207207
end
208+
209+
describe 'with delegated_type' do
210+
before do
211+
Book.create(title: 'Book', owner: User.first)
212+
end
213+
it 'should work alongside delegated_type without errors' do
214+
expect(Address).to respond_to(:addressable_types)
215+
expect(Address.respond_to?(:with_addressable_user)).to be true
216+
expect(Address.respond_to?(:with_addressable_publisher)).to be true
217+
end
218+
219+
it 'should create an Address with a User addressable' do
220+
user = User.first
221+
address = Address.new(addressable: user, delegated: Book.first)
222+
223+
expect(address.addressable_type).to eq('User')
224+
expect(address.addressable).to eq(user)
225+
end
226+
227+
it 'should create an Address with a Publisher addressable' do
228+
publisher = Publisher.first
229+
address = Address.new(addressable: publisher, delegated: Book.first)
230+
231+
expect(address.addressable_type).to eq('Publisher')
232+
expect(address.addressable).to eq(publisher)
233+
end
234+
235+
it 'should have safe_polymorphic helper methods working' do
236+
expect(Address.addressable_types).to match_array([User, Publisher])
237+
end
238+
239+
it 'should reject invalid addressable types' do
240+
other = OtherThing.create
241+
address = Address.new(addressable: other, delegated: Book.first)
242+
243+
expect(address).to_not be_valid
244+
expect(address.errors[:addressable_type]).to include('OtherThing is not an allowed class')
245+
end
246+
247+
it 'should provide scopes for safe_polymorphic' do
248+
user = User.first
249+
publisher = Publisher.first
250+
251+
Address.create(addressable: user, delegated: Book.first)
252+
Address.create(addressable: publisher, delegated: Book.first)
253+
254+
expect(Address.with_addressable_user.count).to eq(1)
255+
expect(Address.with_addressable_publisher.count).to eq(1)
256+
end
257+
258+
it 'should provide class methods of delegated_type ' do
259+
user = User.first
260+
book = Book.first
261+
262+
address = Address.create(addressable: user, delegated: book)
263+
264+
expect(Address.with_addressable_user.first).to eq(address)
265+
expect(address.addressable).to eq(user)
266+
expect(address.delegated).to eq(book)
267+
end
268+
end
208269
end

spec/support/models.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
require_relative 'models/publisher'
55
require_relative 'models/book'
66
require_relative 'models/other_thing'
7+
require_relative 'models/address'

spec/support/models/address.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# frozen_string_literal: true
2+
3+
class Address < ActiveRecord::Base
4+
belongs_to :addressable, polymorphic: [Publisher, User]
5+
delegated_type :delegated, types: %w[Book], dependent: :destroy
6+
end

spec/support/schema.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,13 @@
2929

3030
t.timestamps
3131
end
32+
33+
create_table :addresses, force: true do |t|
34+
t.integer :addressable_id
35+
t.string :addressable_type
36+
t.bigint :delegated_id, null: false
37+
t.string :delegated_type, null: false
38+
39+
t.timestamps
40+
end
3241
end

0 commit comments

Comments
 (0)