Simplify ActiveModel & ActiveRecord Type::Registry

ActiveRecord::Type::Registry doesn't need to inherit from
ActiveModel::Type::Registry, and it makes both classes more simple.

Co-authored-by: Adrianna Chang <adrianna.chang@shopify.com>
This commit is contained in:
Étienne Barrié 2021-04-01 15:04:13 -04:00
parent 7fd8079ef2
commit 81d0653f84
4 changed files with 66 additions and 50 deletions

View File

@ -24,9 +24,10 @@ module ActiveModel
class << self
attr_accessor :registry # :nodoc:
# Add a new type to the registry, allowing it to be gotten through ActiveModel::Type#lookup
def register(type_name, klass = nil, **options, &block)
registry.register(type_name, klass, **options, &block)
# Add a new type to the registry, allowing it to be referenced as a
# symbol by {attribute}[rdoc-ref:Attributes::ClassMethods#attribute].
def register(type_name, klass = nil, &block)
registry.register(type_name, klass, &block)
end
def lookup(*args, **kwargs) # :nodoc:

View File

@ -1,31 +1,30 @@
# frozen_string_literal: true
module ActiveModel
# :stopdoc:
module Type
class Registry
class Registry # :nodoc:
def initialize
@registrations = []
@registrations = {}
end
def initialize_dup(other)
def initialize_copy(other)
@registrations = @registrations.dup
super
end
def register(type_name, klass = nil, **options, &block)
def register(type_name, klass = nil, &block)
unless block_given?
block = proc { |_, *args| klass.new(*args) }
block.ruby2_keywords if block.respond_to?(:ruby2_keywords)
end
registrations << registration_klass.new(type_name, block, **options)
registrations[type_name] = block
end
def lookup(symbol, *args, **kwargs)
registration = find_registration(symbol, *args, **kwargs)
registration = registrations[symbol]
if registration
registration.call(self, symbol, *args, **kwargs)
registration.call(symbol, *args, **kwargs)
else
raise ArgumentError, "Unknown type #{symbol.inspect}"
end
@ -33,38 +32,6 @@ module ActiveModel
private
attr_reader :registrations
def registration_klass
Registration
end
def find_registration(symbol, *args, **kwargs)
registrations.find { |r| r.matches?(symbol, *args, **kwargs) }
end
end
class Registration
# Options must be taken because of https://bugs.ruby-lang.org/issues/10856
def initialize(name, block, **)
@name = name
@block = block
end
def call(_registry, *args, **kwargs)
if kwargs.any? # https://bugs.ruby-lang.org/issues/10856
block.call(*args, **kwargs)
else
block.call(*args)
end
end
def matches?(type_name, *args, **kwargs)
type_name == name
end
private
attr_reader :name, :block
end
end
# :startdoc:
end

View File

@ -0,0 +1,23 @@
# frozen_string_literal: true
require "cases/helper"
module ActiveModel
class TypeTest < ActiveModel::TestCase
setup do
@old_registry = ActiveModel::Type.registry
ActiveModel::Type.registry = @old_registry.dup
end
teardown do
ActiveModel::Type.registry = @old_registry
end
test "registering a new type" do
type = Struct.new(:args)
ActiveModel::Type.register(:foo, type)
assert_equal type.new(:arg), ActiveModel::Type.lookup(:foo, :arg)
end
end
end

View File

@ -5,15 +5,40 @@ require "active_model/type/registry"
module ActiveRecord
# :stopdoc:
module Type
class AdapterSpecificRegistry < ActiveModel::Type::Registry
class AdapterSpecificRegistry # :nodoc:
def initialize
@registrations = []
end
def initialize_copy(other)
@registrations = @registrations.dup
super
end
def add_modifier(options, klass, **args)
registrations << DecorationRegistration.new(options, klass, **args)
end
private
def registration_klass
Registration
def register(type_name, klass = nil, **options, &block)
unless block_given?
block = proc { |_, *args| klass.new(*args) }
block.ruby2_keywords if block.respond_to?(:ruby2_keywords)
end
registrations << Registration.new(type_name, block, **options)
end
def lookup(symbol, *args, **kwargs)
registration = find_registration(symbol, *args, **kwargs)
if registration
registration.call(self, symbol, *args, **kwargs)
else
raise ArgumentError, "Unknown type #{symbol.inspect}"
end
end
private
attr_reader :registrations
def find_registration(symbol, *args, **kwargs)
registrations
@ -22,7 +47,7 @@ module ActiveRecord
end
end
class Registration
class Registration # :nodoc:
def initialize(name, block, adapter: nil, override: nil)
@name = name
@block = block
@ -89,7 +114,7 @@ module ActiveRecord
end
end
class DecorationRegistration < Registration
class DecorationRegistration < Registration # :nodoc:
def initialize(options, klass, adapter: nil)
@options = options
@klass = klass
@ -120,7 +145,7 @@ module ActiveRecord
end
end
class TypeConflictError < StandardError
class TypeConflictError < StandardError # :nodoc:
end
# :startdoc:
end