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:
parent
7fd8079ef2
commit
81d0653f84
|
@ -24,9 +24,10 @@ module ActiveModel
|
||||||
class << self
|
class << self
|
||||||
attr_accessor :registry # :nodoc:
|
attr_accessor :registry # :nodoc:
|
||||||
|
|
||||||
# Add a new type to the registry, allowing it to be gotten through ActiveModel::Type#lookup
|
# Add a new type to the registry, allowing it to be referenced as a
|
||||||
def register(type_name, klass = nil, **options, &block)
|
# symbol by {attribute}[rdoc-ref:Attributes::ClassMethods#attribute].
|
||||||
registry.register(type_name, klass, **options, &block)
|
def register(type_name, klass = nil, &block)
|
||||||
|
registry.register(type_name, klass, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
def lookup(*args, **kwargs) # :nodoc:
|
def lookup(*args, **kwargs) # :nodoc:
|
||||||
|
|
|
@ -1,31 +1,30 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module ActiveModel
|
module ActiveModel
|
||||||
# :stopdoc:
|
|
||||||
module Type
|
module Type
|
||||||
class Registry
|
class Registry # :nodoc:
|
||||||
def initialize
|
def initialize
|
||||||
@registrations = []
|
@registrations = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize_dup(other)
|
def initialize_copy(other)
|
||||||
@registrations = @registrations.dup
|
@registrations = @registrations.dup
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
def register(type_name, klass = nil, **options, &block)
|
def register(type_name, klass = nil, &block)
|
||||||
unless block_given?
|
unless block_given?
|
||||||
block = proc { |_, *args| klass.new(*args) }
|
block = proc { |_, *args| klass.new(*args) }
|
||||||
block.ruby2_keywords if block.respond_to?(:ruby2_keywords)
|
block.ruby2_keywords if block.respond_to?(:ruby2_keywords)
|
||||||
end
|
end
|
||||||
registrations << registration_klass.new(type_name, block, **options)
|
registrations[type_name] = block
|
||||||
end
|
end
|
||||||
|
|
||||||
def lookup(symbol, *args, **kwargs)
|
def lookup(symbol, *args, **kwargs)
|
||||||
registration = find_registration(symbol, *args, **kwargs)
|
registration = registrations[symbol]
|
||||||
|
|
||||||
if registration
|
if registration
|
||||||
registration.call(self, symbol, *args, **kwargs)
|
registration.call(symbol, *args, **kwargs)
|
||||||
else
|
else
|
||||||
raise ArgumentError, "Unknown type #{symbol.inspect}"
|
raise ArgumentError, "Unknown type #{symbol.inspect}"
|
||||||
end
|
end
|
||||||
|
@ -33,38 +32,6 @@ module ActiveModel
|
||||||
|
|
||||||
private
|
private
|
||||||
attr_reader :registrations
|
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
|
||||||
end
|
end
|
||||||
# :startdoc:
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -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
|
|
@ -5,15 +5,40 @@ require "active_model/type/registry"
|
||||||
module ActiveRecord
|
module ActiveRecord
|
||||||
# :stopdoc:
|
# :stopdoc:
|
||||||
module Type
|
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)
|
def add_modifier(options, klass, **args)
|
||||||
registrations << DecorationRegistration.new(options, klass, **args)
|
registrations << DecorationRegistration.new(options, klass, **args)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
def register(type_name, klass = nil, **options, &block)
|
||||||
def registration_klass
|
unless block_given?
|
||||||
Registration
|
block = proc { |_, *args| klass.new(*args) }
|
||||||
|
block.ruby2_keywords if block.respond_to?(:ruby2_keywords)
|
||||||
end
|
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)
|
def find_registration(symbol, *args, **kwargs)
|
||||||
registrations
|
registrations
|
||||||
|
@ -22,7 +47,7 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Registration
|
class Registration # :nodoc:
|
||||||
def initialize(name, block, adapter: nil, override: nil)
|
def initialize(name, block, adapter: nil, override: nil)
|
||||||
@name = name
|
@name = name
|
||||||
@block = block
|
@block = block
|
||||||
|
@ -89,7 +114,7 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class DecorationRegistration < Registration
|
class DecorationRegistration < Registration # :nodoc:
|
||||||
def initialize(options, klass, adapter: nil)
|
def initialize(options, klass, adapter: nil)
|
||||||
@options = options
|
@options = options
|
||||||
@klass = klass
|
@klass = klass
|
||||||
|
@ -120,7 +145,7 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class TypeConflictError < StandardError
|
class TypeConflictError < StandardError # :nodoc:
|
||||||
end
|
end
|
||||||
# :startdoc:
|
# :startdoc:
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue