jat 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +21 -0
- data/jat.gemspec +37 -0
- data/lib/jat/attribute.rb +85 -0
- data/lib/jat/config.rb +38 -0
- data/lib/jat/plugins/_activerecord_preloads/_activerecord_preloads.rb +29 -0
- data/lib/jat/plugins/_activerecord_preloads/lib/preloader.rb +89 -0
- data/lib/jat/plugins/_json_api_activerecord/_json_api_activerecord.rb +22 -0
- data/lib/jat/plugins/_json_api_activerecord/lib/preloads.rb +84 -0
- data/lib/jat/plugins/_preloads/_preloads.rb +53 -0
- data/lib/jat/plugins/_preloads/lib/format_user_preloads.rb +52 -0
- data/lib/jat/plugins/_preloads/lib/preloads_with_path.rb +78 -0
- data/lib/jat/plugins/cache/cache.rb +39 -0
- data/lib/jat/plugins/camel_lower/camel_lower.rb +18 -0
- data/lib/jat/plugins/json_api/json_api.rb +207 -0
- data/lib/jat/plugins/json_api/lib/construct_traversal_map.rb +91 -0
- data/lib/jat/plugins/json_api/lib/map.rb +54 -0
- data/lib/jat/plugins/json_api/lib/params/fields/parse.rb +27 -0
- data/lib/jat/plugins/json_api/lib/params/fields/validate.rb +55 -0
- data/lib/jat/plugins/json_api/lib/params/fields.rb +23 -0
- data/lib/jat/plugins/json_api/lib/params/include/parse.rb +55 -0
- data/lib/jat/plugins/json_api/lib/params/include/validate.rb +29 -0
- data/lib/jat/plugins/json_api/lib/params/include.rb +49 -0
- data/lib/jat/plugins/json_api/lib/presenters/document_links_presenter.rb +48 -0
- data/lib/jat/plugins/json_api/lib/presenters/document_meta_presenter.rb +48 -0
- data/lib/jat/plugins/json_api/lib/presenters/jsonapi_presenter.rb +48 -0
- data/lib/jat/plugins/json_api/lib/presenters/links_presenter.rb +48 -0
- data/lib/jat/plugins/json_api/lib/presenters/meta_presenter.rb +48 -0
- data/lib/jat/plugins/json_api/lib/presenters/relationship_links_presenter.rb +53 -0
- data/lib/jat/plugins/json_api/lib/presenters/relationship_meta_presenter.rb +53 -0
- data/lib/jat/plugins/json_api/lib/response.rb +239 -0
- data/lib/jat/plugins/json_api/lib/traversal_map.rb +34 -0
- data/lib/jat/plugins/simple_api/lib/construct_traversal_map.rb +45 -0
- data/lib/jat/plugins/simple_api/lib/map.rb +29 -0
- data/lib/jat/plugins/simple_api/lib/params/parse.rb +68 -0
- data/lib/jat/plugins/simple_api/lib/response.rb +134 -0
- data/lib/jat/plugins/simple_api/simple_api.rb +65 -0
- data/lib/jat/plugins/to_str/to_str.rb +44 -0
- data/lib/jat/plugins.rb +39 -0
- data/lib/jat/presenter.rb +51 -0
- data/lib/jat/utils/enum_deep_dup.rb +29 -0
- data/lib/jat/utils/enum_deep_freeze.rb +19 -0
- data/lib/jat.rb +66 -144
- data/test/lib/jat/attribute_test.rb +142 -0
- data/test/lib/jat/config_test.rb +57 -0
- data/test/lib/jat/plugins/_activerecord_preloads/_activerecord_preloads_test.rb +40 -0
- data/test/lib/jat/plugins/_activerecord_preloads/lib/preloader_test.rb +98 -0
- data/test/lib/jat/plugins/_json_api_activerecord/_json_api_activerecord_test.rb +29 -0
- data/test/lib/jat/plugins/_json_api_activerecord/lib/preloads_test.rb +191 -0
- data/test/lib/jat/plugins/_preloads/_preloads_test.rb +68 -0
- data/test/lib/jat/plugins/_preloads/lib/format_user_preloads_test.rb +47 -0
- data/test/lib/jat/plugins/_preloads/lib/preloads_with_path_test.rb +33 -0
- data/test/lib/jat/plugins/cache/cache_test.rb +82 -0
- data/test/lib/jat/plugins/camel_lower/camel_lower_test.rb +78 -0
- data/test/lib/jat/plugins/json_api/json_api_test.rb +154 -0
- data/test/lib/jat/plugins/json_api/lib/construct_traversal_map_test.rb +119 -0
- data/test/lib/jat/plugins/json_api/lib/map_test.rb +117 -0
- data/test/lib/jat/plugins/json_api/lib/params/fields/parse_test.rb +24 -0
- data/test/lib/jat/plugins/json_api/lib/params/fields/validate_test.rb +47 -0
- data/test/lib/jat/plugins/json_api/lib/params/fields_test.rb +37 -0
- data/test/lib/jat/plugins/json_api/lib/params/include/parse_test.rb +46 -0
- data/test/lib/jat/plugins/json_api/lib/params/include/validate_test.rb +51 -0
- data/test/lib/jat/plugins/json_api/lib/params/include_test.rb +41 -0
- data/test/lib/jat/plugins/json_api/lib/presenters/document_links_presenter_test.rb +69 -0
- data/test/lib/jat/plugins/json_api/lib/presenters/document_meta_presenter_test.rb +69 -0
- data/test/lib/jat/plugins/json_api/lib/presenters/jsonapi_presenter_test.rb +69 -0
- data/test/lib/jat/plugins/json_api/lib/presenters/links_presenter_test.rb +69 -0
- data/test/lib/jat/plugins/json_api/lib/presenters/meta_presenter_test.rb +69 -0
- data/test/lib/jat/plugins/json_api/lib/presenters/relationship_links_presenter_test.rb +75 -0
- data/test/lib/jat/plugins/json_api/lib/presenters/relationship_meta_presenter_test.rb +75 -0
- data/test/lib/jat/plugins/json_api/lib/response_test.rb +489 -0
- data/test/lib/jat/plugins/json_api/lib/traversal_map_test.rb +58 -0
- data/test/lib/jat/plugins/simple_api/lib/construct_traversal_map_test.rb +100 -0
- data/test/lib/jat/plugins/simple_api/lib/map_test.rb +56 -0
- data/test/lib/jat/plugins/simple_api/lib/params/parse_test.rb +71 -0
- data/test/lib/jat/plugins/simple_api/lib/response_test.rb +342 -0
- data/test/lib/jat/plugins/simple_api/simple_api_test.rb +81 -0
- data/test/lib/jat/plugins/to_str/to_str_test.rb +52 -0
- data/test/lib/jat/presenter_test.rb +61 -0
- data/test/lib/jat/utils/enum_deep_dup_test.rb +31 -0
- data/test/lib/jat/utils/enum_deep_freeze_test.rb +28 -0
- data/test/lib/jat_test.rb +120 -0
- data/test/lib/plugin_test.rb +49 -0
- data/test/support/activerecord.rb +24 -0
- data/test/test_helper.rb +16 -0
- data/test/test_plugin.rb +59 -0
- metadata +240 -11
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
describe Jat::Attribute do
|
|
6
|
+
let(:jat_class) { Class.new(Jat) }
|
|
7
|
+
let(:attribute_class) { jat_class::Attribute }
|
|
8
|
+
|
|
9
|
+
describe ".jat_class=" do
|
|
10
|
+
it "assigns @jat_class" do
|
|
11
|
+
attribute_class.jat_class = :foo
|
|
12
|
+
assert_equal :foo, attribute_class.instance_variable_get(:@jat_class)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe ".jat_class" do
|
|
17
|
+
it "returns self @jat_class" do
|
|
18
|
+
assert_same jat_class, attribute_class.instance_variable_get(:@jat_class)
|
|
19
|
+
assert_same jat_class, attribute_class.jat_class
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe ".inspect" do
|
|
24
|
+
it "returns self name" do
|
|
25
|
+
assert_equal "#{jat_class}::Attribute", attribute_class.inspect
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe "#initialize" do
|
|
30
|
+
it "deeply copies provided params" do
|
|
31
|
+
params = {name: :foo, opts: {include: {foo: :bar}}, block: -> {}}
|
|
32
|
+
|
|
33
|
+
attribute = attribute_class.new(**params)
|
|
34
|
+
assert_equal attribute.params, params
|
|
35
|
+
refute_same attribute.params, params
|
|
36
|
+
refute_same attribute.opts, params[:opts]
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
describe "#name" do
|
|
41
|
+
it "symbolizes name" do
|
|
42
|
+
attribute = attribute_class.new(name: "foo")
|
|
43
|
+
assert_equal :foo, attribute.name
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe "#key" do
|
|
48
|
+
it "returns same as #name when key not provided" do
|
|
49
|
+
attribute = attribute_class.new(name: "foo")
|
|
50
|
+
assert_equal :foo, attribute.key
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "returns symbolized key option" do
|
|
54
|
+
attribute = attribute_class.new(name: "foo", opts: {key: "bar"})
|
|
55
|
+
assert_equal :bar, attribute.key
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
describe "#exposed?" do
|
|
60
|
+
it "returns provided value" do
|
|
61
|
+
attribute = attribute_class.new(name: "foo", opts: {exposed: false})
|
|
62
|
+
assert_equal false, attribute.exposed?
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "returns true when all keys are exposed by config" do
|
|
66
|
+
jat_class.config[:exposed] = :all
|
|
67
|
+
attribute = attribute_class.new(name: "foo")
|
|
68
|
+
assert_equal true, attribute.exposed?
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "returns false when no keys are exposed by config" do
|
|
72
|
+
jat_class.config[:exposed] = :none
|
|
73
|
+
attribute = attribute_class.new(name: "foo")
|
|
74
|
+
assert_equal false, attribute.exposed?
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "returns false when serializer exists and config[:exposed] is default" do
|
|
78
|
+
jat_class.config[:exposed] = :default
|
|
79
|
+
attribute = attribute_class.new(name: "foo", opts: {serializer: jat_class})
|
|
80
|
+
assert_equal false, attribute.exposed?
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "returns true when serializer not exists and config[:exposed] is default" do
|
|
84
|
+
jat_class.config[:exposed] = :default
|
|
85
|
+
attribute = attribute_class.new(name: "foo")
|
|
86
|
+
assert_equal true, attribute.exposed?
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
describe "#many?" do
|
|
91
|
+
it "returns nil when no key provided" do
|
|
92
|
+
attribute = attribute_class.new(name: "foo")
|
|
93
|
+
assert_nil attribute.many?
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it "returns provided data" do
|
|
97
|
+
attribute = attribute_class.new(name: "foo", opts: {many: false})
|
|
98
|
+
assert_equal false, attribute.many?
|
|
99
|
+
assert_equal false, attribute.instance_variable_get(:@many)
|
|
100
|
+
assert_same attribute.instance_variable_get(:@many), attribute.many?
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
describe "#relation?" do
|
|
105
|
+
it "returns false when no serializer key" do
|
|
106
|
+
attribute = attribute_class.new(name: "foo")
|
|
107
|
+
assert_equal false, attribute.relation?
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it "returns true with serializer key" do
|
|
111
|
+
attribute = attribute_class.new(name: "foo", opts: {serializer: jat_class})
|
|
112
|
+
assert_equal true, attribute.relation?
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
describe "#serializer" do
|
|
117
|
+
it "returns nil when no serializer key" do
|
|
118
|
+
attribute = attribute_class.new(name: "foo")
|
|
119
|
+
assert_nil attribute.serializer
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it "returns provided serializer" do
|
|
123
|
+
attribute = attribute_class.new(name: "foo", opts: {serializer: jat_class})
|
|
124
|
+
assert_same jat_class, attribute.serializer
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
describe "#block" do
|
|
129
|
+
it "returns provided block" do
|
|
130
|
+
block = -> {}
|
|
131
|
+
attribute = attribute_class.new(name: "foo", block: block)
|
|
132
|
+
assert_equal block, attribute.block
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it "constructs block that calls current key method on object" do
|
|
136
|
+
attribute = attribute_class.new(name: "foo", opts: {key: :length})
|
|
137
|
+
presenter = jat_class::Presenter.new([1, 2, 3], {})
|
|
138
|
+
|
|
139
|
+
assert_equal 3, presenter.instance_exec(&attribute.block)
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
describe Jat::Config do
|
|
6
|
+
let(:jat_class) { Class.new(Jat) }
|
|
7
|
+
let(:config) { jat_class.config }
|
|
8
|
+
|
|
9
|
+
describe ".jat_class=" do
|
|
10
|
+
it "assigns @jat_class" do
|
|
11
|
+
config.class.jat_class = :foo
|
|
12
|
+
assert_equal :foo, config.class.instance_variable_get(:@jat_class)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe ".jat_class" do
|
|
17
|
+
it "returns self @jat_class" do
|
|
18
|
+
assert_same jat_class, config.class.instance_variable_get(:@jat_class)
|
|
19
|
+
assert_same jat_class, config.class.jat_class
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe ".inspect" do
|
|
24
|
+
it "returns self name" do
|
|
25
|
+
assert_equal "#{jat_class}::Config", config.class.inspect
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe "#initialize" do
|
|
30
|
+
it "deeply copies provided opts" do
|
|
31
|
+
opts = {foo: {bar: {bazz: :bazz2}}}
|
|
32
|
+
|
|
33
|
+
config = Jat::Config.new(opts)
|
|
34
|
+
assert_equal config.opts, opts
|
|
35
|
+
refute_same config.opts[:foo], opts[:foo]
|
|
36
|
+
refute_same config.opts[:foo][:bar], opts[:foo][:bar]
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
describe "#[]=" do
|
|
41
|
+
it "adds options" do
|
|
42
|
+
config = Jat::Config.new
|
|
43
|
+
config[:foo] = :bar
|
|
44
|
+
|
|
45
|
+
assert_equal :bar, config.opts[:foo]
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe "#[]" do
|
|
50
|
+
it "reads options" do
|
|
51
|
+
config = Jat::Config.new
|
|
52
|
+
config[:foo] = :bar
|
|
53
|
+
|
|
54
|
+
assert_equal :bar, config[:foo]
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
describe "Jat::Plugins::ActiverecordPreloads" do
|
|
6
|
+
let(:jat_class) { Class.new(Jat) { plugin(:_activerecord_preloads) } }
|
|
7
|
+
let(:preloader) { Jat::Plugins::ActiverecordPreloads::Preloader }
|
|
8
|
+
|
|
9
|
+
describe "InstanceMethods" do
|
|
10
|
+
it "adds preloads to object in initialize call" do
|
|
11
|
+
obj = "OBJ"
|
|
12
|
+
preloads = "PRELOADS"
|
|
13
|
+
jat_class.expects(:jat_preloads).with(kind_of(jat_class)).returns(preloads)
|
|
14
|
+
preloader.expects(:preload).with(obj, preloads).returns("OBJ_WITH_PRELOADS")
|
|
15
|
+
|
|
16
|
+
jat = jat_class.new(obj, {})
|
|
17
|
+
assert_equal("OBJ_WITH_PRELOADS", jat.object)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "skips preloadings for nil" do
|
|
21
|
+
object = nil
|
|
22
|
+
jat = jat_class.new(object, {})
|
|
23
|
+
assert_same object, jat.object
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "skips preloadings for empty array" do
|
|
27
|
+
object = []
|
|
28
|
+
jat = jat_class.new(object, {})
|
|
29
|
+
assert_same object, jat.object
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "skips preloadings when nothing to preload" do
|
|
33
|
+
object = "OBJECT"
|
|
34
|
+
jat_class.expects(:jat_preloads).with(kind_of(jat_class)).returns({})
|
|
35
|
+
|
|
36
|
+
jat = jat_class.new(object, {})
|
|
37
|
+
assert_same object, jat.object
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
require "support/activerecord"
|
|
5
|
+
|
|
6
|
+
describe "Jat::Plugins::ActiverecordPreloads" do
|
|
7
|
+
before { Jat::Plugins.load_plugin(:_activerecord_preloads) }
|
|
8
|
+
|
|
9
|
+
describe "Preloader" do
|
|
10
|
+
let(:described_class) { plugin::Preloader }
|
|
11
|
+
let(:plugin) { Jat::Plugins::ActiverecordPreloads }
|
|
12
|
+
|
|
13
|
+
describe ".handlers" do
|
|
14
|
+
it "returns memorized array of handlers" do
|
|
15
|
+
assert_equal [
|
|
16
|
+
plugin::ActiverecordRelation,
|
|
17
|
+
plugin::ActiverecordObject,
|
|
18
|
+
plugin::ActiverecordArray
|
|
19
|
+
], described_class.handlers
|
|
20
|
+
|
|
21
|
+
assert_same described_class.handlers, described_class.handlers
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
describe ".preload" do
|
|
26
|
+
it "raises error when can't find appropriate handler" do
|
|
27
|
+
preloads = {}
|
|
28
|
+
|
|
29
|
+
object = nil
|
|
30
|
+
err = assert_raises(Jat::Error) { described_class.preload(object, {}) }
|
|
31
|
+
assert_equal "Can't preload #{preloads.inspect} to #{object.inspect}", err.message
|
|
32
|
+
|
|
33
|
+
object = []
|
|
34
|
+
err = assert_raises(Jat::Error) { described_class.preload(object, {}) }
|
|
35
|
+
assert_equal "Can't preload #{preloads.inspect} to #{object.inspect}", err.message
|
|
36
|
+
|
|
37
|
+
object = 123
|
|
38
|
+
err = assert_raises(Jat::Error) { described_class.preload(object, {}) }
|
|
39
|
+
assert_equal "Can't preload #{preloads.inspect} to #{object.inspect}", err.message
|
|
40
|
+
|
|
41
|
+
object = [AR::User.create!, AR::Comment.create!]
|
|
42
|
+
err = assert_raises(Jat::Error) { described_class.preload(object, {}) }
|
|
43
|
+
assert_equal "Can't preload #{preloads.inspect} to #{object.inspect}", err.message
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "preloads data to activerecord object" do
|
|
47
|
+
user = AR::User.create!
|
|
48
|
+
|
|
49
|
+
result = described_class.preload(user, {comments: {}})
|
|
50
|
+
|
|
51
|
+
assert_same result, user
|
|
52
|
+
assert_equal true, user.association(:comments).loaded?
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "resets activerecord object preloaded relations" do
|
|
56
|
+
user = AR::User.create!
|
|
57
|
+
comment = user.comments.create!
|
|
58
|
+
user.comments.to_a && comment.delete # preload comments manually and delete comment
|
|
59
|
+
|
|
60
|
+
described_class.preload(user, {comments: {}})
|
|
61
|
+
|
|
62
|
+
assert_equal true, user.association(:comments).loaded?
|
|
63
|
+
assert_equal [], user.comments
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "preloads data to activerecord relation object" do
|
|
67
|
+
user = AR::User.create!
|
|
68
|
+
|
|
69
|
+
result = described_class.preload(AR::User.where(id: user.id), {comments: {}})
|
|
70
|
+
|
|
71
|
+
assert_equal result, [user]
|
|
72
|
+
assert_equal true, result[0].association(:comments).loaded?
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "preloads data to activerecord array" do
|
|
76
|
+
user = AR::User.create!
|
|
77
|
+
|
|
78
|
+
users = [user]
|
|
79
|
+
result = described_class.preload(users, {comments: {}})
|
|
80
|
+
|
|
81
|
+
assert_same result, users
|
|
82
|
+
assert_equal true, result[0].association(:comments).loaded?
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "resets activerecord array preloaded relations" do
|
|
86
|
+
user = AR::User.create!
|
|
87
|
+
comment = user.comments.create!
|
|
88
|
+
user.comments.to_a && comment.delete # preload comments manually and delete comment
|
|
89
|
+
|
|
90
|
+
users = [user]
|
|
91
|
+
result = described_class.preload(users, {comments: {}})
|
|
92
|
+
|
|
93
|
+
assert_equal true, result[0].association(:comments).loaded?
|
|
94
|
+
assert_equal [], result[0].comments
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
describe "Jat::Plugins::JsonApiActiverecord" do
|
|
6
|
+
before do
|
|
7
|
+
@plugin = Jat::Plugins.load_plugin(:_json_api_activerecord)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "loads other plugins in after_load" do
|
|
11
|
+
jat_class = Class.new(Jat)
|
|
12
|
+
jat_class.expects(:plugin).with(:_preloads, foo: :bar)
|
|
13
|
+
jat_class.expects(:plugin).with(:_activerecord_preloads, foo: :bar)
|
|
14
|
+
|
|
15
|
+
Jat::Plugins.after_load(@plugin, jat_class, foo: :bar)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe "ClassMethods" do
|
|
19
|
+
it "add .jat_preloads method as a delegator to #{@plugin}::Preloads" do
|
|
20
|
+
jat_class = Class.new(Jat)
|
|
21
|
+
jat_class.plugin @plugin
|
|
22
|
+
jat = jat_class.allocate
|
|
23
|
+
|
|
24
|
+
@plugin::Preloads.expects(:call).with(jat).returns("RES")
|
|
25
|
+
|
|
26
|
+
assert_equal "RES", jat_class.jat_preloads(jat)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
describe "Jat::Plugins::JsonApiActiverecord::Preloads" do
|
|
6
|
+
let(:base) { Class.new(Jat) { plugin :json_api, activerecord: true } }
|
|
7
|
+
|
|
8
|
+
let(:user_serializer) { Class.new(base) { type(:user) } }
|
|
9
|
+
let(:profile_serializer) { Class.new(base) { type(:profile) } }
|
|
10
|
+
let(:email_serializer) { Class.new(base) { type(:email) } }
|
|
11
|
+
|
|
12
|
+
let(:jat_user) { user_serializer.allocate }
|
|
13
|
+
let(:jat_profile) { profile_serializer.allocate }
|
|
14
|
+
let(:jat_email) { email_serializer.allocate }
|
|
15
|
+
|
|
16
|
+
let(:described_class) { Jat::Plugins::JsonApiActiverecord::Preloads }
|
|
17
|
+
|
|
18
|
+
def define_map(map)
|
|
19
|
+
jat_user.traversal_map.expects(:current).returns(map)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "returns empty hash when no attributes requested" do
|
|
23
|
+
define_map(user: {attributes: [], relationships: []})
|
|
24
|
+
|
|
25
|
+
result = described_class.call(jat_user)
|
|
26
|
+
assert_equal({}, result)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "returns empty hash when no attributes with preloads requested" do
|
|
30
|
+
user_serializer.attribute :name
|
|
31
|
+
define_map(user: {attributes: [:name], relationships: []})
|
|
32
|
+
|
|
33
|
+
result = described_class.call(jat_user)
|
|
34
|
+
assert_equal({}, result)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "returns preloads for requested attributes" do
|
|
38
|
+
user_serializer.attribute :name, preload: :profile
|
|
39
|
+
define_map(user: {attributes: [:name], relationships: []})
|
|
40
|
+
|
|
41
|
+
result = described_class.call(jat_user)
|
|
42
|
+
assert_equal({profile: {}}, result)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "returns merged preloads for requested attributes" do
|
|
46
|
+
user_serializer.attribute :first_name, preload: :profile
|
|
47
|
+
user_serializer.attribute :phone, preload: {profile: :phones}
|
|
48
|
+
user_serializer.attribute :email, preload: {profile: :emails}
|
|
49
|
+
|
|
50
|
+
define_map(user: {attributes: %i[first_name phone email], relationships: []})
|
|
51
|
+
|
|
52
|
+
result = described_class.call(jat_user)
|
|
53
|
+
assert_equal({profile: {phones: {}, emails: {}}}, result)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "returns no preloads and no nested preloads for relationships when specified preloads is nil" do
|
|
57
|
+
user_serializer.relationship :profile, serializer: profile_serializer, preload: nil
|
|
58
|
+
profile_serializer.attribute :email, preload: :email # should not be preloaded
|
|
59
|
+
define_map(
|
|
60
|
+
user: {attributes: [], relationships: %i[profile]},
|
|
61
|
+
profile: {attributes: %i[email], relationships: []}
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
result = described_class.call(jat_user)
|
|
65
|
+
assert_equal({}, result)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "returns preloads for nested relationships joined to root when specified preloads is {} or []" do
|
|
69
|
+
[{}, []].each do |preloads|
|
|
70
|
+
user_serializer.relationship :profile, serializer: profile_serializer, preload: preloads
|
|
71
|
+
profile_serializer.attribute :email, preload: :email # should be preloaded to root
|
|
72
|
+
define_map(
|
|
73
|
+
user: {attributes: [], relationships: %i[profile]},
|
|
74
|
+
profile: {attributes: %i[email], relationships: []}
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
result = described_class.call(jat_user)
|
|
78
|
+
assert_equal({email: {}}, result)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "returns preloads for relationships" do
|
|
83
|
+
user_serializer.relationship :profile, serializer: profile_serializer
|
|
84
|
+
define_map(
|
|
85
|
+
user: {attributes: [], relationships: %i[profile]},
|
|
86
|
+
profile: {attributes: [], relationships: []}
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
result = described_class.call(jat_user)
|
|
90
|
+
assert_equal({profile: {}}, result)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "returns nested preloads for relationships" do
|
|
94
|
+
user_serializer.relationship :profile, serializer: profile_serializer
|
|
95
|
+
profile_serializer.attribute :email, preload: %i[confirmed_email unconfirmed_email]
|
|
96
|
+
|
|
97
|
+
define_map(
|
|
98
|
+
user: {attributes: [], relationships: %i[profile]},
|
|
99
|
+
profile: {attributes: %i[email], relationships: []}
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
result = described_class.call(jat_user)
|
|
103
|
+
assert_equal({profile: {confirmed_email: {}, unconfirmed_email: {}}}, result)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "preloads nested relationships for nested relationship" do
|
|
107
|
+
user_serializer.relationship :profile, serializer: profile_serializer, preload: {company: :profile}
|
|
108
|
+
profile_serializer.attribute :email, preload: %i[confirmed_email unconfirmed_email]
|
|
109
|
+
|
|
110
|
+
define_map(
|
|
111
|
+
user: {attributes: [], relationships: %i[profile]},
|
|
112
|
+
profile: {attributes: %i[email], relationships: []}
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
result = described_class.call(jat_user)
|
|
116
|
+
assert_equal({company: {profile: {confirmed_email: {}, unconfirmed_email: {}}}}, result)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it "preloads nested relationships to main (!) resource" do
|
|
120
|
+
user_serializer.relationship :profile, serializer: profile_serializer, preload: {company!: :profile}
|
|
121
|
+
profile_serializer.attribute :email, preload: %i[confirmed_email unconfirmed_email]
|
|
122
|
+
|
|
123
|
+
define_map(
|
|
124
|
+
user: {attributes: [], relationships: %i[profile]},
|
|
125
|
+
profile: {attributes: %i[email], relationships: []}
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
result = described_class.call(jat_user)
|
|
129
|
+
assert_equal({company: {profile: {}, confirmed_email: {}, unconfirmed_email: {}}}, result)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it "raises error if with 2 serializers have recursive preloads" do
|
|
133
|
+
user_serializer.relationship :profile, serializer: profile_serializer, preload: :profile
|
|
134
|
+
profile_serializer.relationship :user, serializer: user_serializer, preload: :user
|
|
135
|
+
|
|
136
|
+
define_map(
|
|
137
|
+
user: {attributes: [], relationships: %i[profile]},
|
|
138
|
+
profile: {attributes: [], relationships: %i[user]}
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
error = assert_raises(Jat::Error) { described_class.call(jat_user) }
|
|
142
|
+
assert_match(/recursive preloads/, error.message)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it "raises error if 3 serializers recursive preloads" do
|
|
146
|
+
user_serializer.relationship :profile, serializer: profile_serializer, preload: :profile
|
|
147
|
+
profile_serializer.relationship :email, serializer: email_serializer, preload: :email
|
|
148
|
+
email_serializer.relationship :user, serializer: user_serializer, preload: :user
|
|
149
|
+
|
|
150
|
+
define_map(
|
|
151
|
+
user: {attributes: [], relationships: %i[profile]},
|
|
152
|
+
profile: {attributes: [], relationships: %i[email]},
|
|
153
|
+
email: {attributes: [], relationships: %i[user]}
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
error = assert_raises(Jat::Error) { described_class.call(jat_user) }
|
|
157
|
+
assert_match(/recursive preloads/, error.message)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it "does not raises error if 2 serializers preloads same preloads" do
|
|
161
|
+
user_serializer.relationship :profile, serializer: profile_serializer, preload: :profile
|
|
162
|
+
user_serializer.relationship :email, serializer: email_serializer, preload: :email
|
|
163
|
+
profile_serializer.relationship :email, serializer: email_serializer, preload: :email
|
|
164
|
+
|
|
165
|
+
define_map(
|
|
166
|
+
user: {attributes: [], relationships: %i[profile email]},
|
|
167
|
+
profile: {attributes: [], relationships: %i[email]},
|
|
168
|
+
email: {attributes: [], relationships: %i[]}
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
described_class.call(jat_user) # should not raise
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it "merges preloads the same way regardless of order of preloads" do
|
|
175
|
+
a = Class.new(base) { type(:a) }
|
|
176
|
+
a.attribute :a1, preload: {foo: {bar: {bazz1: {}, bazz: {}}}}
|
|
177
|
+
a.attribute :a2, preload: {foo: {bar: {bazz2: {}, bazz: {last: {}}}}}
|
|
178
|
+
|
|
179
|
+
jat_a1 = a.allocate
|
|
180
|
+
jat_a2 = a.allocate
|
|
181
|
+
|
|
182
|
+
jat_a1.traversal_map.expects(:current).returns(a: {attributes: %i[a1 a2], relationships: %i[]})
|
|
183
|
+
jat_a2.traversal_map.expects(:current).returns(a: {attributes: %i[a2 a1], relationships: %i[]})
|
|
184
|
+
|
|
185
|
+
result1 = described_class.call(jat_a1)
|
|
186
|
+
result2 = described_class.call(jat_a2)
|
|
187
|
+
|
|
188
|
+
assert_equal(result2, result1)
|
|
189
|
+
assert_equal({foo: {bar: {bazz: {last: {}}, bazz1: {}, bazz2: {}}}}, result1)
|
|
190
|
+
end
|
|
191
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
describe "Jat::Plugins::Preloads" do
|
|
6
|
+
let(:jat_class) do
|
|
7
|
+
Class.new(Jat) { plugin(:_preloads) }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def attribute(name, opts)
|
|
11
|
+
jat_class.attribute(name, **opts)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe "AttributeMethods" do
|
|
15
|
+
it "saves @preloads and @preloads_path after first access" do
|
|
16
|
+
attribute = attribute(:foo, preload: :bar)
|
|
17
|
+
|
|
18
|
+
assert_same attribute.preloads, attribute.preloads
|
|
19
|
+
assert_same attribute.preloads_path, attribute.preloads_path
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe "#preloads" do
|
|
23
|
+
it "returns formatted data provided by user" do
|
|
24
|
+
assert_equal({}, attribute(:foo, preload: {}).preloads)
|
|
25
|
+
assert_equal({}, attribute(:foo, preload: []).preloads)
|
|
26
|
+
assert_equal({some: {}}, attribute(:foo, preload: :some).preloads)
|
|
27
|
+
assert_equal({some: {data: {}}}, attribute(:foo, preload: {some: :data}).preloads)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "preloads main key when serializer exists and preloads are not" do
|
|
31
|
+
assert_equal({foo: {}}, attribute(:foo, serializer: jat_class).preloads)
|
|
32
|
+
assert_equal({bar: {}}, attribute(:foo, key: :bar, serializer: jat_class).preloads)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "returns nil when requested to preload nil or false" do
|
|
36
|
+
assert_nil attribute(:foo, serializer: jat_class, preload: nil).preloads
|
|
37
|
+
assert_nil attribute(:foo, key: :bar, serializer: jat_class, preload: false).preloads
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "removes bang (!) from preloads" do
|
|
41
|
+
assert_equal({foo: {}}, attribute(:foo, preload: :foo!).preloads)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe "#preloads_path" do
|
|
46
|
+
it "returns path to main resource provided by user" do
|
|
47
|
+
assert_equal([], attribute(:foo, preload: nil).preloads_path)
|
|
48
|
+
assert_equal([], attribute(:foo, preload: {}).preloads_path)
|
|
49
|
+
assert_equal([], attribute(:foo, preload: []).preloads_path)
|
|
50
|
+
assert_equal([:some], attribute(:foo, preload: :some).preloads_path)
|
|
51
|
+
assert_equal(%i[some data], attribute(:foo, preload: {some: :data}).preloads_path)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "show path to main key when serializer exists and preloads are not" do
|
|
55
|
+
assert_equal([:foo], attribute(:foo, serializer: jat_class).preloads_path)
|
|
56
|
+
assert_equal([:bar], attribute(:foo, key: :bar, serializer: jat_class).preloads_path)
|
|
57
|
+
|
|
58
|
+
# serializer with empty preloads provided
|
|
59
|
+
assert_equal([], attribute(:foo, serializer: jat_class, preload: nil).preloads_path)
|
|
60
|
+
assert_equal([], attribute(:foo, key: :bar, serializer: jat_class, preload: false).preloads_path)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "removes bang (!) and construct path to this preload" do
|
|
64
|
+
assert_equal([:some], attribute(:foo, preload: {some!: :data}).preloads_path)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
describe "Jat::Plugins::Preloads::FormatUserPreloads" do
|
|
6
|
+
before { Jat::Plugins.load_plugin(:_preloads) }
|
|
7
|
+
|
|
8
|
+
let(:format) { Jat::Plugins::Preloads::FormatUserPreloads }
|
|
9
|
+
|
|
10
|
+
it "transforms nil to empty hash" do
|
|
11
|
+
preloads = nil
|
|
12
|
+
assert_equal ({}), format.to_hash(preloads)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "transforms false to empty hash" do
|
|
16
|
+
preloads = false
|
|
17
|
+
assert_equal({}, format.to_hash(preloads))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "transforms Symbol" do
|
|
21
|
+
preloads = :foo
|
|
22
|
+
assert_equal({foo: {}}, format.to_hash(preloads))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "transforms String" do
|
|
26
|
+
preloads = "foo"
|
|
27
|
+
assert_equal({foo: {}}, format.to_hash(preloads))
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "transforms Hash" do
|
|
31
|
+
preloads = {foo: :bar}
|
|
32
|
+
assert_equal({foo: {bar: {}}}, format.to_hash(preloads))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "transforms Array" do
|
|
36
|
+
preloads = %i[foo bar]
|
|
37
|
+
assert_equal({foo: {}, bar: {}}, format.to_hash(preloads))
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "transforms nested hashes and arrays" do
|
|
41
|
+
preloads = [:foo, {"bar" => "bazz"}, ["bazz"]]
|
|
42
|
+
assert_equal({foo: {}, bar: {bazz: {}}, bazz: {}}, format.to_hash(preloads))
|
|
43
|
+
|
|
44
|
+
preloads = {"bar" => "bazz", :foo => [:bar, "bazz"]}
|
|
45
|
+
assert_equal({bar: {bazz: {}}, foo: {bar: {}, bazz: {}}}, format.to_hash(preloads))
|
|
46
|
+
end
|
|
47
|
+
end
|