aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activemodel/lib/active_model/type/registry.rb107
-rw-r--r--activemodel/test/cases/type/registry_test.rb39
-rw-r--r--activerecord/lib/active_record/type/adapter_specific_registry.rb17
3 files changed, 60 insertions, 103 deletions
diff --git a/activemodel/lib/active_model/type/registry.rb b/activemodel/lib/active_model/type/registry.rb
index 8070a4bd38..adc88eb624 100644
--- a/activemodel/lib/active_model/type/registry.rb
+++ b/activemodel/lib/active_model/type/registry.rb
@@ -12,9 +12,7 @@ module ActiveModel
end
def lookup(symbol, *args)
- registration = registrations
- .select { |r| r.matches?(symbol, *args) }
- .max
+ registration = find_registration(symbol, *args)
if registration
registration.call(self, symbol, *args)
@@ -23,30 +21,26 @@ module ActiveModel
end
end
- def add_modifier(options, klass, **args)
- registrations << decoration_registration_klass.new(options, klass, **args)
- end
-
protected
attr_reader :registrations
-
+
private
-
+
def registration_klass
Registration
end
-
- def decoration_registration_klass
- DecorationRegistration
+
+ def find_registration(symbol, *args)
+ registrations.find { |r| r.matches?(symbol, *args) }
end
end
class Registration
- def initialize(name, block, override: nil)
+ # Options must be taken because of https://bugs.ruby-lang.org/issues/10856
+ def initialize(name, block, **)
@name = name
@block = block
- @override = override
end
def call(_registry, *args, **kwargs)
@@ -58,94 +52,13 @@ module ActiveModel
end
def matches?(type_name, *args, **kwargs)
- type_name == name# && matches_adapter?(**kwargs)
- end
-
- def <=>(other)
- # if conflicts_with?(other)
- # raise TypeConflictError.new("Type #{name} was registered for all
- # adapters, but shadows a native type with
- # the same name for #{other.adapter}".squish)
- # end
- priority <=> other.priority
+ type_name == name
end
protected
- attr_reader :name, :block, :override
-
- def priority
- result = 0
- # if adapter
- # result |= 1
- # end
- if override
- result |= 2
- end
- result
- end
-
- # def priority_except_adapter
- # priority & 0b111111100
- # end
-
- private
-
- # def matches_adapter?(adapter: nil, **)
- # (self.adapter.nil? || adapter == self.adapter)
- # end
-
- # def conflicts_with?(other)
- # same_priority_except_adapter?(other) &&
- # has_adapter_conflict?(other)
- # end
-
- # def same_priority_except_adapter?(other)
- # priority_except_adapter == other.priority_except_adapter
- # end
-
- # def has_adapter_conflict?(other)
- # (override.nil? && other.adapter) ||
- # (adapter && other.override.nil?)
- # end
+ attr_reader :name, :block
end
-
- class DecorationRegistration < Registration
- def initialize(options, klass)
- @options = options
- @klass = klass
- # @adapter = adapter
- end
-
- def call(registry, *args, **kwargs)
- subtype = registry.lookup(*args, **kwargs.except(*options.keys))
- klass.new(subtype)
- end
-
- def matches?(*args, **kwargs)
- matches_options?(**kwargs)
- end
-
- def priority
- super | 4
- end
-
- protected
-
- attr_reader :options, :klass
-
- private
-
- def matches_options?(**kwargs)
- options.all? do |key, value|
- kwargs[key] == value
- end
- end
- end
- end
-
- class TypeConflictError < StandardError
end
-
# :startdoc:
end
diff --git a/activemodel/test/cases/type/registry_test.rb b/activemodel/test/cases/type/registry_test.rb
new file mode 100644
index 0000000000..2a48998a62
--- /dev/null
+++ b/activemodel/test/cases/type/registry_test.rb
@@ -0,0 +1,39 @@
+require "cases/helper"
+require "active_model/type"
+
+module ActiveModel
+ class RegistryTest < ActiveModel::TestCase
+ test "a class can be registered for a symbol" do
+ registry = Type::Registry.new
+ registry.register(:foo, ::String)
+ registry.register(:bar, ::Array)
+
+ assert_equal "", registry.lookup(:foo)
+ assert_equal [], registry.lookup(:bar)
+ end
+
+ test "a block can be registered" do
+ registry = Type::Registry.new
+ registry.register(:foo) do |*args|
+ [*args, "block for foo"]
+ end
+ registry.register(:bar) do |*args|
+ [*args, "block for bar"]
+ end
+
+ assert_equal [:foo, 1, "block for foo"], registry.lookup(:foo, 1)
+ assert_equal [:foo, 2, "block for foo"], registry.lookup(:foo, 2)
+ assert_equal [:bar, 1, 2, 3, "block for bar"], registry.lookup(:bar, 1, 2, 3)
+ end
+
+ test "a reasonable error is given when no type is found" do
+ registry = Type::Registry.new
+
+ e = assert_raises(ArgumentError) do
+ registry.lookup(:foo)
+ end
+
+ assert_equal "Unknown type :foo", e.message
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/type/adapter_specific_registry.rb b/activerecord/lib/active_record/type/adapter_specific_registry.rb
index 3509429058..d440eac619 100644
--- a/activerecord/lib/active_record/type/adapter_specific_registry.rb
+++ b/activerecord/lib/active_record/type/adapter_specific_registry.rb
@@ -4,14 +4,20 @@ module ActiveRecord
# :stopdoc:
module Type
class AdapterSpecificRegistry < ActiveModel::Type::Registry
+ def add_modifier(options, klass, **args)
+ registrations << DecorationRegistration.new(options, klass, **args)
+ end
+
private
-
+
def registration_klass
Registration
end
-
- def decoration_registration_klass
- DecorationRegistration
+
+ def find_registration(symbol, *args)
+ registrations
+ .select { |registration| registration.matches?(symbol, *args) }
+ .max
end
end
@@ -118,8 +124,7 @@ module ActiveRecord
end
end
- class TypeConflictError < ::ActiveModel::TypeConflictError
+ class TypeConflictError < StandardError
end
-
# :startdoc:
end