Skip to content

Commit 57cbf41

Browse files
authored
Merge pull request rails#41866 from etiennebarrie/simplify-active-model-record-registry
Simplify ActiveModel & ActiveRecord Type::Registry
2 parents b8b1c9e + 81d0653 commit 57cbf41

File tree

4 files changed

+66
-50
lines changed

4 files changed

+66
-50
lines changed

activemodel/lib/active_model/type.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ module Type
2424
class << self
2525
attr_accessor :registry # :nodoc:
2626

27-
# Add a new type to the registry, allowing it to be gotten through ActiveModel::Type#lookup
28-
def register(type_name, klass = nil, **options, &block)
29-
registry.register(type_name, klass, **options, &block)
27+
# Add a new type to the registry, allowing it to be referenced as a
28+
# symbol by {attribute}[rdoc-ref:Attributes::ClassMethods#attribute].
29+
def register(type_name, klass = nil, &block)
30+
registry.register(type_name, klass, &block)
3031
end
3132

3233
def lookup(*args, **kwargs) # :nodoc:
Lines changed: 7 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,37 @@
11
# frozen_string_literal: true
22

33
module ActiveModel
4-
# :stopdoc:
54
module Type
6-
class Registry
5+
class Registry # :nodoc:
76
def initialize
8-
@registrations = []
7+
@registrations = {}
98
end
109

11-
def initialize_dup(other)
10+
def initialize_copy(other)
1211
@registrations = @registrations.dup
1312
super
1413
end
1514

16-
def register(type_name, klass = nil, **options, &block)
15+
def register(type_name, klass = nil, &block)
1716
unless block_given?
1817
block = proc { |_, *args| klass.new(*args) }
1918
block.ruby2_keywords if block.respond_to?(:ruby2_keywords)
2019
end
21-
registrations << registration_klass.new(type_name, block, **options)
20+
registrations[type_name] = block
2221
end
2322

2423
def lookup(symbol, *args, **kwargs)
25-
registration = find_registration(symbol, *args, **kwargs)
24+
registration = registrations[symbol]
2625

2726
if registration
28-
registration.call(self, symbol, *args, **kwargs)
27+
registration.call(symbol, *args, **kwargs)
2928
else
3029
raise ArgumentError, "Unknown type #{symbol.inspect}"
3130
end
3231
end
3332

3433
private
3534
attr_reader :registrations
36-
37-
def registration_klass
38-
Registration
39-
end
40-
41-
def find_registration(symbol, *args, **kwargs)
42-
registrations.find { |r| r.matches?(symbol, *args, **kwargs) }
43-
end
44-
end
45-
46-
class Registration
47-
# Options must be taken because of https://bugs.ruby-lang.org/issues/10856
48-
def initialize(name, block, **)
49-
@name = name
50-
@block = block
51-
end
52-
53-
def call(_registry, *args, **kwargs)
54-
if kwargs.any? # https://bugs.ruby-lang.org/issues/10856
55-
block.call(*args, **kwargs)
56-
else
57-
block.call(*args)
58-
end
59-
end
60-
61-
def matches?(type_name, *args, **kwargs)
62-
type_name == name
63-
end
64-
65-
private
66-
attr_reader :name, :block
6735
end
6836
end
69-
# :startdoc:
7037
end

activemodel/test/cases/type_test.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# frozen_string_literal: true
2+
3+
require "cases/helper"
4+
5+
module ActiveModel
6+
class TypeTest < ActiveModel::TestCase
7+
setup do
8+
@old_registry = ActiveModel::Type.registry
9+
ActiveModel::Type.registry = @old_registry.dup
10+
end
11+
12+
teardown do
13+
ActiveModel::Type.registry = @old_registry
14+
end
15+
16+
test "registering a new type" do
17+
type = Struct.new(:args)
18+
ActiveModel::Type.register(:foo, type)
19+
20+
assert_equal type.new(:arg), ActiveModel::Type.lookup(:foo, :arg)
21+
end
22+
end
23+
end

activerecord/lib/active_record/type/adapter_specific_registry.rb

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,40 @@
55
module ActiveRecord
66
# :stopdoc:
77
module Type
8-
class AdapterSpecificRegistry < ActiveModel::Type::Registry
8+
class AdapterSpecificRegistry # :nodoc:
9+
def initialize
10+
@registrations = []
11+
end
12+
13+
def initialize_copy(other)
14+
@registrations = @registrations.dup
15+
super
16+
end
17+
918
def add_modifier(options, klass, **args)
1019
registrations << DecorationRegistration.new(options, klass, **args)
1120
end
1221

13-
private
14-
def registration_klass
15-
Registration
22+
def register(type_name, klass = nil, **options, &block)
23+
unless block_given?
24+
block = proc { |_, *args| klass.new(*args) }
25+
block.ruby2_keywords if block.respond_to?(:ruby2_keywords)
1626
end
27+
registrations << Registration.new(type_name, block, **options)
28+
end
29+
30+
def lookup(symbol, *args, **kwargs)
31+
registration = find_registration(symbol, *args, **kwargs)
32+
33+
if registration
34+
registration.call(self, symbol, *args, **kwargs)
35+
else
36+
raise ArgumentError, "Unknown type #{symbol.inspect}"
37+
end
38+
end
39+
40+
private
41+
attr_reader :registrations
1742

1843
def find_registration(symbol, *args, **kwargs)
1944
registrations
@@ -22,7 +47,7 @@ def find_registration(symbol, *args, **kwargs)
2247
end
2348
end
2449

25-
class Registration
50+
class Registration # :nodoc:
2651
def initialize(name, block, adapter: nil, override: nil)
2752
@name = name
2853
@block = block
@@ -89,7 +114,7 @@ def has_adapter_conflict?(other)
89114
end
90115
end
91116

92-
class DecorationRegistration < Registration
117+
class DecorationRegistration < Registration # :nodoc:
93118
def initialize(options, klass, adapter: nil)
94119
@options = options
95120
@klass = klass
@@ -120,7 +145,7 @@ def matches_options?(**kwargs)
120145
end
121146
end
122147

123-
class TypeConflictError < StandardError
148+
class TypeConflictError < StandardError # :nodoc:
124149
end
125150
# :startdoc:
126151
end

0 commit comments

Comments
 (0)