aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/type/type_map_test.rb
blob: 2959d36466d12a7f024677ade86ec48ebe70ef22 (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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
require "cases/helper"

module ActiveRecord
  module Type
    class TypeMapTest < ActiveRecord::TestCase
      def test_default_type
        mapping = TypeMap.new

        assert_kind_of Value, mapping.lookup(:undefined)
      end

      def test_registering_types
        boolean = Boolean.new
        mapping = TypeMap.new

        mapping.register_type(/boolean/i, boolean)

        assert_equal mapping.lookup("boolean"), boolean
      end

      def test_overriding_registered_types
        time = Time.new
        timestamp = DateTime.new
        mapping = TypeMap.new

        mapping.register_type(/time/i, time)
        mapping.register_type(/time/i, timestamp)

        assert_equal mapping.lookup("time"), timestamp
      end

      def test_fuzzy_lookup
        string = String.new
        mapping = TypeMap.new

        mapping.register_type(/varchar/i, string)

        assert_equal mapping.lookup("varchar(20)"), string
      end

      def test_aliasing_types
        string = String.new
        mapping = TypeMap.new

        mapping.register_type(/string/i, string)
        mapping.alias_type(/varchar/i, "string")

        assert_equal mapping.lookup("varchar"), string
      end

      def test_changing_type_changes_aliases
        time = Time.new
        timestamp = DateTime.new
        mapping = TypeMap.new

        mapping.register_type(/timestamp/i, time)
        mapping.alias_type(/datetime/i, "timestamp")
        mapping.register_type(/timestamp/i, timestamp)

        assert_equal mapping.lookup("datetime"), timestamp
      end

      def test_aliases_keep_metadata
        mapping = TypeMap.new

        mapping.register_type(/decimal/i) { |sql_type| sql_type }
        mapping.alias_type(/number/i, "decimal")

        assert_equal mapping.lookup("number(20)"), "decimal(20)"
        assert_equal mapping.lookup("number"), "decimal"
      end

      def test_register_proc
        string = String.new
        binary = Binary.new
        mapping = TypeMap.new

        mapping.register_type(/varchar/i) do |type|
          if type.include?("(")
            string
          else
            binary
          end
        end

        assert_equal mapping.lookup("varchar(20)"), string
        assert_equal mapping.lookup("varchar"), binary
      end

      def test_additional_lookup_args
        mapping = TypeMap.new

        mapping.register_type(/varchar/i) do |type, limit|
          if limit > 255
            "text"
          else
            "string"
          end
        end
        mapping.alias_type(/string/i, "varchar")

        assert_equal mapping.lookup("varchar", 200), "string"
        assert_equal mapping.lookup("varchar", 400), "text"
        assert_equal mapping.lookup("string", 400), "text"
      end

      def test_requires_value_or_block
        mapping = TypeMap.new

        assert_raises(ArgumentError) do
          mapping.register_type(/only key/i)
        end
      end

      def test_lookup_non_strings
        mapping = HashLookupTypeMap.new

        mapping.register_type(1, "string")
        mapping.register_type(2, "int")
        mapping.alias_type(3, 1)

        assert_equal mapping.lookup(1), "string"
        assert_equal mapping.lookup(2), "int"
        assert_equal mapping.lookup(3), "string"
        assert_kind_of Type::Value, mapping.lookup(4)
      end

      def test_fetch
        mapping = TypeMap.new
        mapping.register_type(1, "string")

        assert_equal "string", mapping.fetch(1) { "int" }
        assert_equal "int", mapping.fetch(2) { "int" }
      end

      def test_fetch_yields_args
        mapping = TypeMap.new

        assert_equal "foo-1-2-3", mapping.fetch("foo", 1, 2, 3) { |*args| args.join("-") }
        assert_equal "bar-1-2-3", mapping.fetch("bar", 1, 2, 3) { |*args| args.join("-") }
      end

      def test_fetch_memoizes
        mapping = TypeMap.new

        looked_up = false
        mapping.register_type(1) do
          fail if looked_up
          looked_up = true
          "string"
        end

        assert_equal "string", mapping.fetch(1)
        assert_equal "string", mapping.fetch(1)
      end

      def test_fetch_memoizes_on_args
        mapping = TypeMap.new
        mapping.register_type("foo") { |*args| args.join("-") }

        assert_equal "foo-1-2-3", mapping.fetch("foo", 1, 2, 3) { |*args| args.join("-") }
        assert_equal "foo-2-3-4", mapping.fetch("foo", 2, 3, 4) { |*args| args.join("-") }
      end

      def test_register_clears_cache
        mapping = TypeMap.new

        mapping.register_type(1, "string")
        mapping.lookup(1)
        mapping.register_type(1, "int")

        assert_equal "int", mapping.lookup(1)
      end
    end
  end
end