aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/type/adapter_specific_registry_test.rb
blob: a723a952ea0ea96ef141b339bbd89d6f3d78de4e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# frozen_string_literal: true
require "cases/helper"

module ActiveRecord
  class AdapterSpecificRegistryTest < ActiveRecord::TestCase
    test "a class can be registered for a symbol" do
      registry = Type::AdapterSpecificRegistry.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::AdapterSpecificRegistry.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 "filtering by adapter" do
      registry = Type::AdapterSpecificRegistry.new
      registry.register(:foo, String, adapter: :sqlite3)
      registry.register(:foo, Array, adapter: :postgresql)

      assert_equal "", registry.lookup(:foo, adapter: :sqlite3)
      assert_equal [], registry.lookup(:foo, adapter: :postgresql)
    end

    test "an error is raised if both a generic and adapter specific type match" do
      registry = Type::AdapterSpecificRegistry.new
      registry.register(:foo, String)
      registry.register(:foo, Array, adapter: :postgresql)

      assert_raises TypeConflictError do
        registry.lookup(:foo, adapter: :postgresql)
      end
      assert_equal "", registry.lookup(:foo, adapter: :sqlite3)
    end

    test "a generic type can explicitly override an adapter specific type" do
      registry = Type::AdapterSpecificRegistry.new
      registry.register(:foo, String, override: true)
      registry.register(:foo, Array, adapter: :postgresql)

      assert_equal "", registry.lookup(:foo, adapter: :postgresql)
      assert_equal "", registry.lookup(:foo, adapter: :sqlite3)
    end

    test "a generic type can explicitly allow an adapter type to be used instead" do
      registry = Type::AdapterSpecificRegistry.new
      registry.register(:foo, String, override: false)
      registry.register(:foo, Array, adapter: :postgresql)

      assert_equal [], registry.lookup(:foo, adapter: :postgresql)
      assert_equal "", registry.lookup(:foo, adapter: :sqlite3)
    end

    test "a reasonable error is given when no type is found" do
      registry = Type::AdapterSpecificRegistry.new

      e = assert_raises(ArgumentError) do
        registry.lookup(:foo)
      end

      assert_equal "Unknown type :foo", e.message
    end

    test "construct args are passed to the type" do
      type = Struct.new(:args)
      registry = Type::AdapterSpecificRegistry.new
      registry.register(:foo, type)

      assert_equal type.new, registry.lookup(:foo)
      assert_equal type.new(:ordered_arg), registry.lookup(:foo, :ordered_arg)
      assert_equal type.new(keyword: :arg), registry.lookup(:foo, keyword: :arg)
      assert_equal type.new(keyword: :arg), registry.lookup(:foo, keyword: :arg, adapter: :postgresql)
    end

    test "registering a modifier" do
      decoration = Struct.new(:value)
      registry = Type::AdapterSpecificRegistry.new
      registry.register(:foo, String)
      registry.register(:bar, Hash)
      registry.add_modifier({ array: true }, decoration)

      assert_equal decoration.new(""), registry.lookup(:foo, array: true)
      assert_equal decoration.new({}), registry.lookup(:bar, array: true)
      assert_equal "", registry.lookup(:foo)
    end

    test "registering multiple modifiers" do
      decoration = Struct.new(:value)
      other_decoration = Struct.new(:value)
      registry = Type::AdapterSpecificRegistry.new
      registry.register(:foo, String)
      registry.add_modifier({ array: true }, decoration)
      registry.add_modifier({ range: true }, other_decoration)

      assert_equal "", registry.lookup(:foo)
      assert_equal decoration.new(""), registry.lookup(:foo, array: true)
      assert_equal other_decoration.new(""), registry.lookup(:foo, range: true)
      assert_equal(
        decoration.new(other_decoration.new("")),
        registry.lookup(:foo, array: true, range: true)
      )
    end

    test "registering adapter specific modifiers" do
      decoration = Struct.new(:value)
      type = Struct.new(:args)
      registry = Type::AdapterSpecificRegistry.new
      registry.register(:foo, type)
      registry.add_modifier({ array: true }, decoration, adapter: :postgresql)

      assert_equal(
        decoration.new(type.new(keyword: :arg)),
        registry.lookup(:foo, array: true, adapter: :postgresql, keyword: :arg)
      )
      assert_equal(
        type.new(array: true),
        registry.lookup(:foo, array: true, adapter: :sqlite3)
      )
    end
  end
end