azeroth 0.6.5 → 0.7.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -21,6 +21,29 @@ module Azeroth
21
21
  autoload :Builder, 'azeroth/resourceable/builder'
22
22
  autoload :ClassMethods, 'azeroth/resourceable/class_methods'
23
23
 
24
+ class << self
25
+ # @method self.resource_for(name, **options)
26
+ # @api public
27
+ #
28
+ # @param name [String, Symbol] Name of the resource
29
+ # @param options [Hash] resource building options
30
+ # @option options only [Array<Symbol,String>] List of
31
+ # actions to be built
32
+ # @option options except [Array<Symbol,String>] List of
33
+ # actions to not to be built
34
+ # @option options decorator [Azeroth::Decorator,TrueClass,FalseClass]
35
+ # Decorator class or flag allowing/disallowing decorators
36
+ # @option options before_save [Symbol,Proc] method/block
37
+ # to be ran on the controller before saving the resource
38
+ # @option options build_with [Symbol,Proc] method/block
39
+ # to be ran when building resource
40
+ # (default proc { <resource_collection>.build(resource_params) }
41
+ #
42
+ # @return [Array<MethodDefinition>] list of methods created
43
+ #
44
+ # @see Options::DEFAULT_OPTIONS
45
+ end
46
+
24
47
  private
25
48
 
26
49
  # @api private
@@ -9,18 +9,11 @@ module Azeroth
9
9
  module ClassMethods
10
10
  # Adds resource methods for resource
11
11
  #
12
- # @param name [String, Symbol] Name of the resource
13
- # @param options [Hash] resource building options
14
- # @option options only [Array<Symbol,String>] List of
15
- # actions to be built
16
- # @option options except [Array<Symbol,String>] List of
17
- # actions to not to be built
18
- # @option options decorator [Azeroth::Decorator,TrueClass,FalseClass]
19
- # Decorator class or flag allowing/disallowing decorators
12
+ # @param (see Resourceable.resource_for)
13
+ # @option (see Resourceable.resource_for)
14
+ # @return (see Resourceable.resource_for)
20
15
  #
21
- # @return [Array<MethodDefinition>] list of methods created
22
- #
23
- # @see Options
16
+ # @see (see Resourceable.resource_for)
24
17
  #
25
18
  # @example Controller without delete
26
19
  # class DocumentsController < ApplicationController
@@ -124,6 +117,33 @@ module Azeroth
124
117
  # # name: 'Nintendo'
125
118
  # # }
126
119
  # }
120
+ #
121
+ # @example Controller with before_save
122
+ # class PokemonsController < ApplicationController
123
+ # include Azeroth::Resourceable
124
+ #
125
+ # resource_for :pokemon,
126
+ # only: %i[create update],
127
+ # before_save: :set_favorite
128
+ #
129
+ # private
130
+ #
131
+ # def set_favorite
132
+ # pokemon.favorite = true
133
+ # end
134
+ #
135
+ # def pokemons
136
+ # master.pokemons
137
+ # end
138
+ #
139
+ # def master
140
+ # @master ||= PokemonMaster.find(master_id)
141
+ # end
142
+ #
143
+ # def master_id
144
+ # params.require(:pokemon_master_id)
145
+ # end
146
+ # end
127
147
  def resource_for(name, **options)
128
148
  Builder.new(
129
149
  self, name, Azeroth::Options.new(options)
@@ -62,13 +62,14 @@ module Azeroth
62
62
 
63
63
  def route_code(route)
64
64
  model_interface = model
65
+ options_object = options
65
66
  handler_class = Azeroth::RequestHandler.const_get(
66
67
  route.to_s.capitalize
67
68
  )
68
69
 
69
70
  proc do
70
71
  handler_class.new(
71
- self, model_interface
72
+ self, model_interface, options_object
72
73
  ).process
73
74
  end
74
75
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Azeroth
4
- VERSION = '0.6.5'
4
+ VERSION = '0.7.4'
5
5
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe PokemonMastersController do
6
+ describe 'POST create' do
7
+ let(:parameters) do
8
+ {
9
+ format: :json,
10
+ pokemon_master: {
11
+ first_name: 'Ash'
12
+ }
13
+ }
14
+ end
15
+
16
+ it 'creates pokemon master' do
17
+ expect { post :create, params: parameters }
18
+ .to change(PokemonMaster, :count)
19
+ .by(1)
20
+ end
21
+
22
+ it 'updates pokemon master age' do
23
+ post :create, params: parameters
24
+
25
+ expect(PokemonMaster.last.age).to eq(10)
26
+ end
27
+ end
28
+
29
+ describe 'POST update' do
30
+ let(:master) do
31
+ create(:pokemon_master, age: 20, last_name: nil)
32
+ end
33
+
34
+ let(:parameters) do
35
+ {
36
+ id: master.id,
37
+ format: :json,
38
+ pokemon_master: { last_name: 'Joe' }
39
+ }
40
+ end
41
+
42
+ it 'updates pokemon master' do
43
+ expect { post :update, params: parameters }
44
+ .to change { master.reload.last_name }
45
+ .from(nil)
46
+ .to('Joe')
47
+ end
48
+
49
+ it 'updates pokemon master age' do
50
+ expect { post :update, params: parameters }
51
+ .to change { master.reload.age }
52
+ .from(20)
53
+ .to(10)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe PokemonsController do
6
+ let(:master) { create(:pokemon_master) }
7
+
8
+ describe 'POST create' do
9
+ let(:parameters) do
10
+ {
11
+ pokemon_master_id: master.id,
12
+ format: :json,
13
+ pokemon: { name: 'Bulbasaur' }
14
+ }
15
+ end
16
+
17
+ it 'creates pokemon' do
18
+ expect { post :create, params: parameters }
19
+ .to change(Pokemon, :count)
20
+ .by(1)
21
+ end
22
+
23
+ it 'updates pokemon to be favorite' do
24
+ expect { post :create, params: parameters }
25
+ .to change { master.reload.favorite_pokemon }
26
+ .from(nil)
27
+ end
28
+ end
29
+
30
+ describe 'POST update' do
31
+ let(:pokemon) { create(:pokemon) }
32
+ let(:master) { pokemon.pokemon_master }
33
+
34
+ let(:parameters) do
35
+ {
36
+ pokemon_master_id: master.id,
37
+ id: pokemon.id,
38
+ format: :json,
39
+ pokemon: { name: 'Butterfree' }
40
+ }
41
+ end
42
+
43
+ it 'updates pokemon' do
44
+ expect { post :update, params: parameters }
45
+ .to change { pokemon.reload.name }
46
+ .from('Bulbasaur')
47
+ .to('Butterfree')
48
+ end
49
+
50
+ it 'updates pokemon to be favorite' do
51
+ expect { post :update, params: parameters }
52
+ .to change { pokemon.reload.favorite }
53
+ .from(nil)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class PokemonMastersController < ApplicationController
4
+ include Azeroth::Resourceable
5
+
6
+ resource_for :pokemon_master,
7
+ only: %i[create update],
8
+ before_save: proc { pokemon_master.age = 10 }
9
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ class PokemonsController < ApplicationController
4
+ include Azeroth::Resourceable
5
+
6
+ resource_for :pokemon,
7
+ only: %i[create update],
8
+ before_save: :set_favorite
9
+
10
+ private
11
+
12
+ def set_favorite
13
+ pokemon.favorite = true
14
+ end
15
+
16
+ def pokemons
17
+ master.pokemons
18
+ end
19
+
20
+ def master
21
+ @master ||= PokemonMaster.find(master_id)
22
+ end
23
+
24
+ def master_id
25
+ params.require(:pokemon_master_id)
26
+ end
27
+ end
@@ -8,4 +8,8 @@ Rails.application.routes.draw do
8
8
  resources :publishers, only: %i[create index] do
9
9
  resources :games, except: :delete
10
10
  end
11
+
12
+ resources :pokemon_masters, only: %i[create update] do
13
+ resources :pokemons, only: %i[create update]
14
+ end
11
15
  end
@@ -23,6 +23,278 @@ describe Azeroth::RequestHandler::Create do
23
23
  .by(1)
24
24
  end
25
25
  end
26
+
27
+ context 'with before_save block option' do
28
+ it_behaves_like 'a request handler', status: :created do
29
+ let(:block) do
30
+ value = 10
31
+ proc do
32
+ document.reference = "X-MAGIC-#{value}"
33
+ end
34
+ end
35
+
36
+ let(:options_hash) do
37
+ {
38
+ before_save: block
39
+ }
40
+ end
41
+
42
+ let(:extra_params) do
43
+ {
44
+ document: {
45
+ name: 'My Document'
46
+ }
47
+ }
48
+ end
49
+
50
+ let(:expected_json) do
51
+ {
52
+ 'name' => 'My Document',
53
+ 'reference' => 'X-MAGIC-10'
54
+ }
55
+ end
56
+
57
+ it 'creates entry' do
58
+ expect { handler.process }
59
+ .to change(Document, :count)
60
+ .by(1)
61
+ end
62
+
63
+ it 'changes entry before saving' do
64
+ handler.process
65
+
66
+ expect(Document.last.reference)
67
+ .to eq('X-MAGIC-10')
68
+ end
69
+ end
70
+ end
71
+
72
+ context 'with before_save symbol option' do
73
+ it_behaves_like 'a request handler', status: :created do
74
+ let(:options_hash) do
75
+ {
76
+ before_save: :add_magic_reference
77
+ }
78
+ end
79
+
80
+ let(:extra_params) do
81
+ {
82
+ document: {
83
+ name: 'My Document'
84
+ }
85
+ }
86
+ end
87
+
88
+ let(:expected_json) do
89
+ {
90
+ 'name' => 'My Document',
91
+ 'reference' => 'X-MAGIC-15'
92
+ }
93
+ end
94
+
95
+ it 'creates entry' do
96
+ expect { handler.process }
97
+ .to change(Document, :count)
98
+ .by(1)
99
+ end
100
+
101
+ it 'changes entry before saving' do
102
+ handler.process
103
+
104
+ expect(Document.last.reference)
105
+ .to eq('X-MAGIC-15')
106
+ end
107
+ end
108
+ end
109
+
110
+ context 'with after_save block option' do
111
+ it_behaves_like 'a request handler', status: :created do
112
+ let(:block) do
113
+ value = 10
114
+ proc do
115
+ document.update(reference: "X-MAGIC-#{value}")
116
+ Worker.perform(document.id)
117
+ end
118
+ end
119
+
120
+ let(:options_hash) do
121
+ {
122
+ after_save: block
123
+ }
124
+ end
125
+
126
+ let(:extra_params) do
127
+ {
128
+ document: {
129
+ name: 'My Document'
130
+ }
131
+ }
132
+ end
133
+
134
+ let(:expected_json) do
135
+ {
136
+ 'name' => 'My Document',
137
+ 'reference' => 'X-MAGIC-10'
138
+ }
139
+ end
140
+
141
+ before do
142
+ allow(Worker).to receive(:perform)
143
+ end
144
+
145
+ it 'creates entry' do
146
+ expect { handler.process }
147
+ .to change(Document, :count)
148
+ .by(1)
149
+ end
150
+
151
+ it 'trigger workers after saving' do
152
+ handler.process
153
+
154
+ expect(Worker).to have_received(:perform)
155
+ .with(Document.last.id)
156
+ end
157
+
158
+ it 'changes entry after saving' do
159
+ handler.process
160
+
161
+ expect(Document.last.reference)
162
+ .to eq('X-MAGIC-10')
163
+ end
164
+ end
165
+ end
166
+
167
+ context 'with after_save symbol option' do
168
+ it_behaves_like 'a request handler', status: :created do
169
+ let(:options_hash) do
170
+ {
171
+ after_save: :add_magic_reference_and_trigger
172
+ }
173
+ end
174
+
175
+ let(:extra_params) do
176
+ {
177
+ document: {
178
+ name: 'My Document'
179
+ }
180
+ }
181
+ end
182
+
183
+ let(:expected_json) do
184
+ {
185
+ 'name' => 'My Document',
186
+ 'reference' => 'X-MAGIC-15'
187
+ }
188
+ end
189
+
190
+ before do
191
+ allow(Worker).to receive(:perform)
192
+ end
193
+
194
+ it 'creates entry' do
195
+ expect { handler.process }
196
+ .to change(Document, :count)
197
+ .by(1)
198
+ end
199
+
200
+ it 'trigger workers after saving' do
201
+ handler.process
202
+
203
+ expect(Worker).to have_received(:perform)
204
+ .with(Document.last.id)
205
+ end
206
+
207
+ it 'changes entry after saving' do
208
+ handler.process
209
+
210
+ expect(Document.last.reference)
211
+ .to eq('X-MAGIC-15')
212
+ end
213
+ end
214
+ end
215
+ end
216
+
217
+ context 'with build_with as symbol' do
218
+ it_behaves_like 'a request handler', status: :created do
219
+ let(:options_hash) do
220
+ {
221
+ build_with: :build_magic_document
222
+ }
223
+ end
224
+
225
+ let(:extra_params) do
226
+ {
227
+ document: {
228
+ name: 'My Document'
229
+ }
230
+ }
231
+ end
232
+
233
+ let(:expected_json) do
234
+ {
235
+ 'name' => 'My Document',
236
+ 'reference' => 'X-MAGIC-15'
237
+ }
238
+ end
239
+
240
+ it 'creates entry' do
241
+ expect { handler.process }
242
+ .to change(Document, :count)
243
+ .by(1)
244
+ end
245
+
246
+ it 'builds entity with custom method' do
247
+ handler.process
248
+
249
+ expect(Document.last.reference)
250
+ .to eq('X-MAGIC-15')
251
+ end
252
+ end
253
+ end
254
+
255
+ context 'with build_with as block' do
256
+ it_behaves_like 'a request handler', status: :created do
257
+ let(:block) do
258
+ proc do
259
+ documents.where(reference: 'X-MAGIC-20')
260
+ .build(document_params)
261
+ end
262
+ end
263
+
264
+ let(:options_hash) do
265
+ {
266
+ build_with: block
267
+ }
268
+ end
269
+
270
+ let(:extra_params) do
271
+ {
272
+ document: {
273
+ name: 'My Document'
274
+ }
275
+ }
276
+ end
277
+
278
+ let(:expected_json) do
279
+ {
280
+ 'name' => 'My Document',
281
+ 'reference' => 'X-MAGIC-20'
282
+ }
283
+ end
284
+
285
+ it 'creates entry' do
286
+ expect { handler.process }
287
+ .to change(Document, :count)
288
+ .by(1)
289
+ end
290
+
291
+ it 'builds entity with custom method' do
292
+ handler.process
293
+
294
+ expect(Document.last.reference)
295
+ .to eq('X-MAGIC-20')
296
+ end
297
+ end
26
298
  end
27
299
 
28
300
  context 'when payload is invalid' do