aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel/test/cases/serialization_test.rb
blob: 6826d2bbd1650d28dfcf0eeb0a3c9a51b0021169 (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
177
178
179
180
181
182
183
184
# frozen_string_literal: true

require "cases/helper"
require "active_support/core_ext/object/instance_variables"

class SerializationTest < ActiveModel::TestCase
  class User
    include ActiveModel::Serialization

    attr_accessor :name, :email, :gender, :address, :friends

    def initialize(name, email, gender)
      @name, @email, @gender = name, email, gender
      @friends = []
    end

    def attributes
      instance_values.except("address", "friends")
    end

    def method_missing(method_name, *args)
      if method_name == :bar
        "i_am_bar"
      else
        super
      end
    end

    def foo
      "i_am_foo"
    end
  end

  class Address
    include ActiveModel::Serialization

    attr_accessor :street, :city, :state, :zip

    def attributes
      instance_values
    end
  end

  setup do
    @user = User.new("David", "david@example.com", "male")
    @user.address = Address.new
    @user.address.street = "123 Lane"
    @user.address.city = "Springfield"
    @user.address.state = "CA"
    @user.address.zip = 11111
    @user.friends = [User.new("Joe", "joe@example.com", "male"),
                     User.new("Sue", "sue@example.com", "female")]
  end

  def test_method_serializable_hash_should_work
    expected = { "name" => "David", "gender" => "male", "email" => "david@example.com" }
    assert_equal expected, @user.serializable_hash
  end

  def test_method_serializable_hash_should_work_with_only_option
    expected = { "name" => "David" }
    assert_equal expected, @user.serializable_hash(only: [:name])
  end

  def test_method_serializable_hash_should_work_with_except_option
    expected = { "gender" => "male", "email" => "david@example.com" }
    assert_equal expected, @user.serializable_hash(except: [:name])
  end

  def test_method_serializable_hash_should_work_with_methods_option
    expected = { "name" => "David", "gender" => "male", "foo" => "i_am_foo", "bar" => "i_am_bar", "email" => "david@example.com" }
    assert_equal expected, @user.serializable_hash(methods: [:foo, :bar])
  end

  def test_method_serializable_hash_should_work_with_only_and_methods
    expected = { "foo" => "i_am_foo", "bar" => "i_am_bar" }
    assert_equal expected, @user.serializable_hash(only: [], methods: [:foo, :bar])
  end

  def test_method_serializable_hash_should_work_with_except_and_methods
    expected = { "gender" => "male", "foo" => "i_am_foo", "bar" => "i_am_bar" }
    assert_equal expected, @user.serializable_hash(except: [:name, :email], methods: [:foo, :bar])
  end

  def test_should_raise_NoMethodError_for_non_existing_method
    assert_raise(NoMethodError) { @user.serializable_hash(methods: [:nada]) }
  end

  def test_should_use_read_attribute_for_serialization
    def @user.read_attribute_for_serialization(n)
      "Jon"
    end

    expected = { "name" => "Jon" }
    assert_equal expected, @user.serializable_hash(only: :name)
  end

  def test_include_option_with_singular_association
    expected = { "name" => "David", "gender" => "male", "email" => "david@example.com",
                "address" => { "street" => "123 Lane", "city" => "Springfield", "state" => "CA", "zip" => 11111 } }
    assert_equal expected, @user.serializable_hash(include: :address)
  end

  def test_include_option_with_plural_association
    expected = { "email" => "david@example.com", "gender" => "male", "name" => "David",
                "friends" => [{ "name" => "Joe", "email" => "joe@example.com", "gender" => "male" },
                           { "name" => "Sue", "email" => "sue@example.com", "gender" => "female" }] }
    assert_equal expected, @user.serializable_hash(include: :friends)
  end

  def test_include_option_with_empty_association
    @user.friends = []
    expected = { "email" => "david@example.com", "gender" => "male", "name" => "David", "friends" => [] }
    assert_equal expected, @user.serializable_hash(include: :friends)
  end

  class FriendList
    def initialize(friends)
      @friends = friends
    end

    def to_ary
      @friends
    end
  end

  def test_include_option_with_ary
    @user.friends = FriendList.new(@user.friends)
    expected = { "email" => "david@example.com", "gender" => "male", "name" => "David",
                "friends" => [{ "name" => "Joe", "email" => "joe@example.com", "gender" => "male" },
                           { "name" => "Sue", "email" => "sue@example.com", "gender" => "female" }] }
    assert_equal expected, @user.serializable_hash(include: :friends)
  end

  def test_multiple_includes
    expected = { "email" => "david@example.com", "gender" => "male", "name" => "David",
                "address" => { "street" => "123 Lane", "city" => "Springfield", "state" => "CA", "zip" => 11111 },
                "friends" => [{ "name" => "Joe", "email" => "joe@example.com", "gender" => "male" },
                           { "name" => "Sue", "email" => "sue@example.com", "gender" => "female" }] }
    assert_equal expected, @user.serializable_hash(include: [:address, :friends])
  end

  def test_include_with_options
    expected = { "email" => "david@example.com", "gender" => "male", "name" => "David",
                "address" => { "street" => "123 Lane" } }
    assert_equal expected, @user.serializable_hash(include: { address: { only: "street" } })
  end

  def test_nested_include
    @user.friends.first.friends = [@user]
    expected = { "email" => "david@example.com", "gender" => "male", "name" => "David",
                "friends" => [{ "name" => "Joe", "email" => "joe@example.com", "gender" => "male",
                            "friends" => [{ "email" => "david@example.com", "gender" => "male", "name" => "David" }] },
                            { "name" => "Sue", "email" => "sue@example.com", "gender" => "female", "friends" => [] }] }
    assert_equal expected, @user.serializable_hash(include: { friends: { include: :friends } })
  end

  def test_only_include
    expected = { "name" => "David", "friends" => [{ "name" => "Joe" }, { "name" => "Sue" }] }
    assert_equal expected, @user.serializable_hash(only: :name, include: { friends: { only: :name } })
  end

  def test_except_include
    expected = { "name" => "David", "email" => "david@example.com",
                "friends" => [{ "name" => "Joe", "email" => "joe@example.com" },
                             { "name" => "Sue", "email" => "sue@example.com" }] }
    assert_equal expected, @user.serializable_hash(except: :gender, include: { friends: { except: :gender } })
  end

  def test_multiple_includes_with_options
    expected = { "email" => "david@example.com", "gender" => "male", "name" => "David",
                "address" => { "street" => "123 Lane" },
                "friends" => [{ "name" => "Joe", "email" => "joe@example.com", "gender" => "male" },
                           { "name" => "Sue", "email" => "sue@example.com", "gender" => "female" }] }
    assert_equal expected, @user.serializable_hash(include: [{ address: { only: "street" } }, :friends])
  end

  def test_all_includes_with_options
    expected = { "email" => "david@example.com", "gender" => "male", "name" => "David",
                "address" => { "street" => "123 Lane" },
                "friends" => [{ "name" => "Joe" }, { "name" => "Sue" }] }
    assert_equal expected, @user.serializable_hash(include: [address: { only: "street" }, friends: { only: "name" }])
  end
end