azeroth 0.6.3 → 0.6.4
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/.rubocop.yml +11 -0
- data/README.md +113 -1
- data/lib/azeroth/decorator.rb +121 -0
- data/lib/azeroth/decorator/key_value_extractor.rb +2 -2
- data/lib/azeroth/decorator/options.rb +3 -3
- data/lib/azeroth/resourceable.rb +4 -0
- data/lib/azeroth/resourceable/class_methods.rb +96 -2
- data/lib/azeroth/version.rb +1 -1
- data/spec/dummy/app/controllers/games_controller.rb +22 -0
- data/spec/dummy/app/controllers/publishers_controller.rb +8 -0
- data/spec/dummy/app/models/game.rb +5 -0
- data/spec/dummy/app/models/game/decorator.rb +9 -0
- data/spec/dummy/app/models/name_decorator.rb +5 -0
- data/spec/dummy/app/models/pokemon.rb +8 -0
- data/spec/dummy/app/models/pokemon/decorator.rb +16 -0
- data/spec/dummy/app/models/pokemon/favorite_decorator.rb +7 -0
- data/spec/dummy/app/models/pokemon_master.rb +7 -0
- data/spec/dummy/app/models/pokemon_master/decorator.rb +17 -0
- data/spec/dummy/app/models/publisher.rb +5 -0
- data/spec/dummy/config/routes.rb +4 -0
- data/spec/dummy/db/schema.rb +26 -0
- data/spec/integration/readme/azeroth/decorator_spec.rb +48 -0
- data/spec/integration/readme/controllers/games_controller_spec.rb +42 -0
- data/spec/integration/yard/azeroth/decorator_spec.rb +58 -17
- data/spec/integration/yard/controllers/games_controller_spec.rb +42 -0
- data/spec/support/factories/game.rb +8 -0
- data/spec/support/factories/publisher.rb +7 -0
- metadata +34 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ac2c03e9a7b51ed50db9ecab43a4f7257d98839126f79a45cc6b3563efd7b296
|
|
4
|
+
data.tar.gz: 95d18220fae24c2f049cf186fe25a0d5cdc94bada48ccd9ce02b867c5334f3ce
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8dd092347ebebde2ccdaad5b2c165a8a595a2f8f2a6fc463303566f1b3812d84b22a0295f75ce9dbf696c752ad045691953696166705e0294f94ae3450b0f3e7
|
|
7
|
+
data.tar.gz: 4a406a9e2d4609034cab48bd8aff6ead1c644f3535d3cacd6e18523881572dde035afccbc4279ee96f9a110a0b078897641ebcfc5008a93cf47b7b4ce89bd746
|
data/.rubocop.yml
CHANGED
|
@@ -7,6 +7,7 @@ AllCops:
|
|
|
7
7
|
Metrics/BlockLength:
|
|
8
8
|
Exclude:
|
|
9
9
|
- 'spec/**/*_spec.rb'
|
|
10
|
+
- 'spec/dummy/db/schema.rb'
|
|
10
11
|
- 'spec/support/shared_*/**/*.rb'
|
|
11
12
|
- 'azeroth.gemspec'
|
|
12
13
|
|
|
@@ -24,3 +25,13 @@ Style/HashTransformKeys:
|
|
|
24
25
|
|
|
25
26
|
Style/HashTransformValues:
|
|
26
27
|
Enabled: true
|
|
28
|
+
|
|
29
|
+
RSpec/ExampleLength:
|
|
30
|
+
Exclude:
|
|
31
|
+
- 'spec/integration/readme/**/*_spec.rb'
|
|
32
|
+
- 'spec/integration/yard/**/*_spec.rb'
|
|
33
|
+
|
|
34
|
+
RSpec/MultipleExpectations:
|
|
35
|
+
Exclude:
|
|
36
|
+
- 'spec/integration/readme/**/*_spec.rb'
|
|
37
|
+
- 'spec/integration/yard/**/*_spec.rb'
|
data/README.md
CHANGED
|
@@ -11,4 +11,116 @@ Azeroth
|
|
|
11
11
|
|
|
12
12
|
Yard Documentation
|
|
13
13
|
-------------------
|
|
14
|
-
[https://www.rubydoc.info/gems/azeroth/0.6.
|
|
14
|
+
[https://www.rubydoc.info/gems/azeroth/0.6.4](https://www.rubydoc.info/gems/azeroth/0.6.4)
|
|
15
|
+
|
|
16
|
+
Azeroth has been designed making the coding of controllers easier
|
|
17
|
+
as routes in controllers are usually copy, paste and replace of same
|
|
18
|
+
code.
|
|
19
|
+
|
|
20
|
+
Azeroth was originally developed for controller actions
|
|
21
|
+
which will respond with json or template rendering based
|
|
22
|
+
on the requested format `.json` or `.html` where `html` rendering
|
|
23
|
+
does not perform database operations
|
|
24
|
+
|
|
25
|
+
Future versions will enable `html` rendering to also perform
|
|
26
|
+
database operations.
|
|
27
|
+
|
|
28
|
+
Usage
|
|
29
|
+
-----
|
|
30
|
+
|
|
31
|
+
## Azeroth::Resourceable
|
|
32
|
+
|
|
33
|
+
[Resourceable](https://www.rubydoc.info/gems/azeroth/Azeroth/Resourceable)
|
|
34
|
+
module adds class method [resource_for](https://www.rubydoc.info/gems/azeroth/Azeroth/Resourceable/ClassMethods#resource_for-instance_method)
|
|
35
|
+
which adds a resource and action methods for `create`, `show`, `index`,
|
|
36
|
+
`update`, `delete`, `edit`
|
|
37
|
+
|
|
38
|
+
It accepts options
|
|
39
|
+
-only List of actions to be built
|
|
40
|
+
-except List of actions to not to be built
|
|
41
|
+
-decorator Decorator class or flag allowing/disallowing decorators
|
|
42
|
+
|
|
43
|
+
```ruby
|
|
44
|
+
# publishers_controller.rb
|
|
45
|
+
|
|
46
|
+
class PublishersController < ApplicationController
|
|
47
|
+
include Azeroth::Resourceable
|
|
48
|
+
skip_before_action :verify_authenticity_token
|
|
49
|
+
|
|
50
|
+
resource_for :publisher, only: %i[create index]
|
|
51
|
+
end
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
```ruby
|
|
55
|
+
# games_controller.rb
|
|
56
|
+
|
|
57
|
+
class GamesController < ApplicationController
|
|
58
|
+
include Azeroth::Resourceable
|
|
59
|
+
skip_before_action :verify_authenticity_token
|
|
60
|
+
|
|
61
|
+
resource_for :game, except: :delete
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def games
|
|
66
|
+
publisher.games
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def publisher
|
|
70
|
+
@publisher ||= Publisher.find(publisher_id)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def publisher_id
|
|
74
|
+
params.require(:publisher_id)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Azeroth::Decorator
|
|
80
|
+
|
|
81
|
+
[Decorators](https://www.rubydoc.info/gems/azeroth/Azeroth/Decorator) are
|
|
82
|
+
used to define how an object is exposed as json on controller responses
|
|
83
|
+
defining which and how fields will be exposed
|
|
84
|
+
|
|
85
|
+
```ruby
|
|
86
|
+
# pokemon/decorator.rb
|
|
87
|
+
|
|
88
|
+
class Pokemon::Decorator < Azeroth::Decorator
|
|
89
|
+
expose :name
|
|
90
|
+
expose :previous_form_name, as: :evolution_of, if: :evolution?
|
|
91
|
+
|
|
92
|
+
def evolution?
|
|
93
|
+
previous_form
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def previous_form_name
|
|
97
|
+
previous_form.name
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
```ruby
|
|
103
|
+
# pokemon/favorite_decorator.rb
|
|
104
|
+
|
|
105
|
+
class Pokemon::FavoriteDecorator < Pokemon::Decorator
|
|
106
|
+
expose :nickname
|
|
107
|
+
end
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
```ruby
|
|
111
|
+
# pokemon_master/decorator.rb
|
|
112
|
+
|
|
113
|
+
class PokemonMaster < ActiveRecord::Base
|
|
114
|
+
has_one :favorite_pokemon, -> { where(favorite: true) },
|
|
115
|
+
class_name: 'Pokemon'
|
|
116
|
+
has_many :pokemons
|
|
117
|
+
end
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Exposing is done through the class method
|
|
121
|
+
[expose](https://www.rubydoc.info/gems/azeroth/Azeroth/Decorator#expose-class_method)
|
|
122
|
+
which accepts several options:
|
|
123
|
+
|
|
124
|
+
-as: custom key to expose
|
|
125
|
+
-if: method/block to be called checking if an attribute should or should not be exposed
|
|
126
|
+
-decorator: flag to use or not a decorator or decorator class to be used
|
data/lib/azeroth/decorator.rb
CHANGED
|
@@ -84,6 +84,8 @@ module Azeroth
|
|
|
84
84
|
# to be called
|
|
85
85
|
# checking if an attribute should or should not
|
|
86
86
|
# be exposed
|
|
87
|
+
# @option options_hash decorator [FalseClass,TrueClass,Class]
|
|
88
|
+
# flag to use or not a decorator or decorator class to be used
|
|
87
89
|
#
|
|
88
90
|
# @return [Array<Symbol>]
|
|
89
91
|
#
|
|
@@ -104,6 +106,125 @@ module Azeroth
|
|
|
104
106
|
# end
|
|
105
107
|
# end
|
|
106
108
|
# end
|
|
109
|
+
#
|
|
110
|
+
# @example With relations
|
|
111
|
+
# # pokemon/decorator.rb
|
|
112
|
+
#
|
|
113
|
+
# class Pokemon::Decorator < Azeroth::Decorator
|
|
114
|
+
# expose :name
|
|
115
|
+
# expose :previous_form_name, as: :evolution_of, if: :evolution?
|
|
116
|
+
#
|
|
117
|
+
# def evolution?
|
|
118
|
+
# previous_form
|
|
119
|
+
# end
|
|
120
|
+
#
|
|
121
|
+
# def previous_form_name
|
|
122
|
+
# previous_form.name
|
|
123
|
+
# end
|
|
124
|
+
# end
|
|
125
|
+
#
|
|
126
|
+
# # pokemon/favorite_decorator.rb
|
|
127
|
+
#
|
|
128
|
+
# class Pokemon::FavoriteDecorator < Pokemon::Decorator
|
|
129
|
+
# expose :nickname
|
|
130
|
+
# end
|
|
131
|
+
#
|
|
132
|
+
# # pokemon_master/decorator.rb
|
|
133
|
+
#
|
|
134
|
+
# class PokemonMaster < ActiveRecord::Base
|
|
135
|
+
# has_one :favorite_pokemon, -> { where(favorite: true) },
|
|
136
|
+
# class_name: 'Pokemon'
|
|
137
|
+
# has_many :pokemons
|
|
138
|
+
# end
|
|
139
|
+
#
|
|
140
|
+
# # pokemon.rb
|
|
141
|
+
#
|
|
142
|
+
# class Pokemon < ActiveRecord::Base
|
|
143
|
+
# belongs_to :pokemon_master
|
|
144
|
+
# has_one :previous_form,
|
|
145
|
+
# class_name: 'Pokemon',
|
|
146
|
+
# foreign_key: :previous_form_id
|
|
147
|
+
# end
|
|
148
|
+
#
|
|
149
|
+
# # pokemon_master.rb
|
|
150
|
+
#
|
|
151
|
+
# class PokemonMaster::Decorator < Azeroth::Decorator
|
|
152
|
+
# expose :name
|
|
153
|
+
# expose :age
|
|
154
|
+
# expose :favorite_pokemon, decorator: Pokemon::FavoriteDecorator
|
|
155
|
+
# expose :pokemons
|
|
156
|
+
#
|
|
157
|
+
# def name
|
|
158
|
+
# [
|
|
159
|
+
# first_name,
|
|
160
|
+
# last_name
|
|
161
|
+
# ].compact.join(' ')
|
|
162
|
+
# end
|
|
163
|
+
# end
|
|
164
|
+
#
|
|
165
|
+
# # schema.rb
|
|
166
|
+
#
|
|
167
|
+
# ActiveRecord::Schema.define do
|
|
168
|
+
# self.verbose = false
|
|
169
|
+
#
|
|
170
|
+
# create_table :pokemon_masters, force: true do |t|
|
|
171
|
+
# t.string :first_name, null: false
|
|
172
|
+
# t.string :last_name
|
|
173
|
+
# t.integer :age, null: false
|
|
174
|
+
# end
|
|
175
|
+
#
|
|
176
|
+
# create_table :pokemons, force: true do |t|
|
|
177
|
+
# t.string :name, null: false
|
|
178
|
+
# t.string :nickname
|
|
179
|
+
# t.integer :pokemon_master_id
|
|
180
|
+
# t.boolean :favorite
|
|
181
|
+
# t.integer :previous_form_id
|
|
182
|
+
# t.index %i[pokemon_master_id favorite], unique: true
|
|
183
|
+
# end
|
|
184
|
+
#
|
|
185
|
+
# add_foreign_key 'pokemons', 'pokemon_masters'
|
|
186
|
+
# end
|
|
187
|
+
#
|
|
188
|
+
# # test.rb
|
|
189
|
+
#
|
|
190
|
+
# master = PokemonMaster.create(
|
|
191
|
+
# first_name: 'Ash',
|
|
192
|
+
# last_name: 'Ketchum',
|
|
193
|
+
# age: 10
|
|
194
|
+
# )
|
|
195
|
+
#
|
|
196
|
+
# master.create_favorite_pokemon(
|
|
197
|
+
# name: 'pikachu',
|
|
198
|
+
# nickname: 'Pikachu'
|
|
199
|
+
# )
|
|
200
|
+
#
|
|
201
|
+
# metapod = Pokemon.create(name: :metapod)
|
|
202
|
+
#
|
|
203
|
+
# master.pokemons.create(
|
|
204
|
+
# name: 'butterfree', previous_form: metapod
|
|
205
|
+
# )
|
|
206
|
+
# master.pokemons.create(name: 'squirtle')
|
|
207
|
+
#
|
|
208
|
+
# decorator = PokemonMaster::Decorator.new(master)
|
|
209
|
+
#
|
|
210
|
+
# decorator.as_json
|
|
211
|
+
# # returns
|
|
212
|
+
# # {
|
|
213
|
+
# # 'age' => 10,
|
|
214
|
+
# # 'name' => 'Ash Ketchum',
|
|
215
|
+
# # 'favorite_pokemon' => {
|
|
216
|
+
# # 'name' => 'pikachu',
|
|
217
|
+
# # 'nickname' => 'Pikachu'
|
|
218
|
+
# # },
|
|
219
|
+
# # 'pokemons' => [{
|
|
220
|
+
# # 'name' => 'butterfree',
|
|
221
|
+
# # 'evolution_of' => 'metapod'
|
|
222
|
+
# # }, {
|
|
223
|
+
# # 'name' => 'squirtle'
|
|
224
|
+
# # }, {
|
|
225
|
+
# # 'name' => 'pikachu'
|
|
226
|
+
# # }]
|
|
227
|
+
# # }
|
|
107
228
|
def expose(attribute, **options_hash)
|
|
108
229
|
options = Decorator::Options.new(options_hash)
|
|
109
230
|
|
|
@@ -97,9 +97,9 @@ module Azeroth
|
|
|
97
97
|
#
|
|
98
98
|
# @return [Class<Decorator>, NilClass]
|
|
99
99
|
def decorator_from_options
|
|
100
|
-
return options.decorator if options.
|
|
100
|
+
return options.decorator if options.decorator_defined?
|
|
101
101
|
|
|
102
|
-
Azeroth::DummyDecorator unless options.
|
|
102
|
+
Azeroth::DummyDecorator unless options.decorator
|
|
103
103
|
end
|
|
104
104
|
|
|
105
105
|
# @private
|
|
@@ -13,7 +13,7 @@ module Azeroth
|
|
|
13
13
|
DEFAULT_OPTIONS = {
|
|
14
14
|
as: nil,
|
|
15
15
|
if: nil,
|
|
16
|
-
decorator:
|
|
16
|
+
decorator: true
|
|
17
17
|
}.freeze
|
|
18
18
|
|
|
19
19
|
with_options DEFAULT_OPTIONS
|
|
@@ -62,8 +62,8 @@ module Azeroth
|
|
|
62
62
|
# #as_json call on value
|
|
63
63
|
#
|
|
64
64
|
# @return [TrueClass,FalseClass]
|
|
65
|
-
def
|
|
66
|
-
decorator
|
|
65
|
+
def decorator_defined?
|
|
66
|
+
decorator.is_a?(Class)
|
|
67
67
|
end
|
|
68
68
|
end
|
|
69
69
|
end
|
data/lib/azeroth/resourceable.rb
CHANGED
|
@@ -7,6 +7,10 @@ module Azeroth
|
|
|
7
7
|
# @author Darthjee
|
|
8
8
|
#
|
|
9
9
|
# Concern for building controller methods for the routes
|
|
10
|
+
#
|
|
11
|
+
# @example (see Resourceable::ClassMethods#resource_for)
|
|
12
|
+
#
|
|
13
|
+
# @see Resourceable::ClassMethods
|
|
10
14
|
module Resourceable
|
|
11
15
|
extend ActiveSupport::Concern
|
|
12
16
|
|
|
@@ -10,8 +10,13 @@ module Azeroth
|
|
|
10
10
|
# Adds resource methods for resource
|
|
11
11
|
#
|
|
12
12
|
# @param name [String, Symbol] Name of the resource
|
|
13
|
-
# @param
|
|
14
|
-
# @option
|
|
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
|
|
15
20
|
#
|
|
16
21
|
# @return [Array<MethodDefinition>] list of methods created
|
|
17
22
|
#
|
|
@@ -30,6 +35,95 @@ module Azeroth
|
|
|
30
35
|
#
|
|
31
36
|
# resource_for :document, only: %w[create index show]
|
|
32
37
|
# end
|
|
38
|
+
#
|
|
39
|
+
# @example complete example gmaes and publishers
|
|
40
|
+
# class PublishersController < ApplicationController
|
|
41
|
+
# include Azeroth::Resourceable
|
|
42
|
+
# skip_before_action :verify_authenticity_token
|
|
43
|
+
#
|
|
44
|
+
# resource_for :publisher, only: %i[create index]
|
|
45
|
+
# end
|
|
46
|
+
#
|
|
47
|
+
# class GamesController < ApplicationController
|
|
48
|
+
# include Azeroth::Resourceable
|
|
49
|
+
# skip_before_action :verify_authenticity_token
|
|
50
|
+
#
|
|
51
|
+
# resource_for :game, except: :delete
|
|
52
|
+
#
|
|
53
|
+
# private
|
|
54
|
+
#
|
|
55
|
+
# def games
|
|
56
|
+
# publisher.games
|
|
57
|
+
# end
|
|
58
|
+
#
|
|
59
|
+
# def publisher
|
|
60
|
+
# @publisher ||= Publisher.find(publisher_id)
|
|
61
|
+
# end
|
|
62
|
+
#
|
|
63
|
+
# def publisher_id
|
|
64
|
+
# params.require(:publisher_id)
|
|
65
|
+
# end
|
|
66
|
+
# end
|
|
67
|
+
#
|
|
68
|
+
# ActiveRecord::Schema.define do
|
|
69
|
+
# self.verbose = false
|
|
70
|
+
#
|
|
71
|
+
# create_table :publishers, force: true do |t|
|
|
72
|
+
# t.string :name
|
|
73
|
+
# end
|
|
74
|
+
#
|
|
75
|
+
# create_table :games, force: true do |t|
|
|
76
|
+
# t.string :name
|
|
77
|
+
# t.integer :publisher_id
|
|
78
|
+
# end
|
|
79
|
+
# end
|
|
80
|
+
#
|
|
81
|
+
# class Publisher < ActiveRecord::Base
|
|
82
|
+
# has_many :games
|
|
83
|
+
# end
|
|
84
|
+
#
|
|
85
|
+
# class Game < ActiveRecord::Base
|
|
86
|
+
# belongs_to :publisher
|
|
87
|
+
# end
|
|
88
|
+
#
|
|
89
|
+
# class Game::Decorator < Azeroth::Decorator
|
|
90
|
+
# expose :id
|
|
91
|
+
# expose :name
|
|
92
|
+
# expose :publisher, decorator: NameDecorator
|
|
93
|
+
# end
|
|
94
|
+
#
|
|
95
|
+
# @example requesting games and publishers
|
|
96
|
+
# post "/publishers.json", params: {
|
|
97
|
+
# publisher: {
|
|
98
|
+
# name: 'Nintendo'
|
|
99
|
+
# }
|
|
100
|
+
# }
|
|
101
|
+
#
|
|
102
|
+
# publisher = JSON.parse(response.body)
|
|
103
|
+
# # returns
|
|
104
|
+
# # {
|
|
105
|
+
# # 'id' => 11,
|
|
106
|
+
# # 'name' => 'Nintendo'
|
|
107
|
+
# # }
|
|
108
|
+
#
|
|
109
|
+
# publisher = Publisher.last
|
|
110
|
+
# post "/publishers/#{publisher['id']}/games.json", params: {
|
|
111
|
+
# game: {
|
|
112
|
+
# name: 'Pokemon'
|
|
113
|
+
# }
|
|
114
|
+
# }
|
|
115
|
+
#
|
|
116
|
+
# game = Game.last
|
|
117
|
+
#
|
|
118
|
+
# JSON.parse(response.body)
|
|
119
|
+
# # returns
|
|
120
|
+
# # {
|
|
121
|
+
# # id: game.id,
|
|
122
|
+
# # name: 'Pokemon',
|
|
123
|
+
# # publisher: {
|
|
124
|
+
# # name: 'Nintendo'
|
|
125
|
+
# # }
|
|
126
|
+
# }
|
|
33
127
|
def resource_for(name, **options)
|
|
34
128
|
Builder.new(
|
|
35
129
|
self, name, Azeroth::Options.new(options)
|
data/lib/azeroth/version.rb
CHANGED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class GamesController < ApplicationController
|
|
4
|
+
include Azeroth::Resourceable
|
|
5
|
+
skip_before_action :verify_authenticity_token
|
|
6
|
+
|
|
7
|
+
resource_for :game, except: :delete
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def games
|
|
12
|
+
publisher.games
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def publisher
|
|
16
|
+
@publisher ||= Publisher.find(publisher_id)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def publisher_id
|
|
20
|
+
params.require(:publisher_id)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Pokemon
|
|
4
|
+
class Decorator < Azeroth::Decorator
|
|
5
|
+
expose :name
|
|
6
|
+
expose :previous_form_name, as: :evolution_of, if: :evolution?
|
|
7
|
+
|
|
8
|
+
def evolution?
|
|
9
|
+
previous_form
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def previous_form_name
|
|
13
|
+
previous_form.name
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class PokemonMaster
|
|
4
|
+
class Decorator < Azeroth::Decorator
|
|
5
|
+
expose :name
|
|
6
|
+
expose :age
|
|
7
|
+
expose :favorite_pokemon, decorator: Pokemon::FavoriteDecorator
|
|
8
|
+
expose :pokemons
|
|
9
|
+
|
|
10
|
+
def name
|
|
11
|
+
[
|
|
12
|
+
first_name,
|
|
13
|
+
last_name
|
|
14
|
+
].compact.join(' ')
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/spec/dummy/config/routes.rb
CHANGED
|
@@ -4,4 +4,8 @@ Rails.application.routes.draw do
|
|
|
4
4
|
resources :documents
|
|
5
5
|
resources :public_documents, controller: :index_documents
|
|
6
6
|
resources :create_documents, controller: :documents_with_error
|
|
7
|
+
|
|
8
|
+
resources :publishers, only: %i[create index] do
|
|
9
|
+
resources :games, except: :delete
|
|
10
|
+
end
|
|
7
11
|
end
|
data/spec/dummy/db/schema.rb
CHANGED
|
@@ -22,4 +22,30 @@ ActiveRecord::Schema.define do
|
|
|
22
22
|
t.integer :factory_id
|
|
23
23
|
t.string :name
|
|
24
24
|
end
|
|
25
|
+
|
|
26
|
+
create_table :publishers, force: true do |t|
|
|
27
|
+
t.string :name
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
create_table :games, force: true do |t|
|
|
31
|
+
t.string :name
|
|
32
|
+
t.integer :publisher_id
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
create_table :pokemon_masters, force: true do |t|
|
|
36
|
+
t.string :first_name, null: false
|
|
37
|
+
t.string :last_name
|
|
38
|
+
t.integer :age, null: false
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
create_table :pokemons, force: true do |t|
|
|
42
|
+
t.string :name, null: false
|
|
43
|
+
t.string :nickname
|
|
44
|
+
t.integer :pokemon_master_id
|
|
45
|
+
t.boolean :favorite
|
|
46
|
+
t.integer :previous_form_id
|
|
47
|
+
t.index %i[pokemon_master_id favorite], unique: true
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
add_foreign_key 'pokemons', 'pokemon_masters'
|
|
25
51
|
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe Azeroth::Decorator do
|
|
6
|
+
describe 'readme' do
|
|
7
|
+
it 'decorates model' do
|
|
8
|
+
master = PokemonMaster.create(
|
|
9
|
+
first_name: 'Ash',
|
|
10
|
+
last_name: 'Ketchum',
|
|
11
|
+
age: 10
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
master.create_favorite_pokemon(
|
|
15
|
+
name: 'pikachu',
|
|
16
|
+
nickname: 'Pikachu'
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
metapod = Pokemon.create(name: :metapod)
|
|
20
|
+
|
|
21
|
+
master.pokemons.create(
|
|
22
|
+
name: 'butterfree', previous_form: metapod
|
|
23
|
+
)
|
|
24
|
+
master.pokemons.create(name: 'squirtle')
|
|
25
|
+
|
|
26
|
+
decorator = PokemonMaster::Decorator.new(master)
|
|
27
|
+
|
|
28
|
+
expect(decorator.as_json).to eq(
|
|
29
|
+
{
|
|
30
|
+
'age' => 10,
|
|
31
|
+
'name' => 'Ash Ketchum',
|
|
32
|
+
'favorite_pokemon' => {
|
|
33
|
+
'name' => 'pikachu',
|
|
34
|
+
'nickname' => 'Pikachu'
|
|
35
|
+
},
|
|
36
|
+
'pokemons' => [{
|
|
37
|
+
'name' => 'butterfree',
|
|
38
|
+
'evolution_of' => 'metapod'
|
|
39
|
+
}, {
|
|
40
|
+
'name' => 'squirtle'
|
|
41
|
+
}, {
|
|
42
|
+
'name' => 'pikachu'
|
|
43
|
+
}]
|
|
44
|
+
}
|
|
45
|
+
)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe GamesController, controller: true do
|
|
6
|
+
describe 'readme' do
|
|
7
|
+
describe 'POST create' do
|
|
8
|
+
it 'create game' do
|
|
9
|
+
post '/publishers.json', params: {
|
|
10
|
+
publisher: {
|
|
11
|
+
name: 'Nintendo'
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
publisher = JSON.parse(response.body)
|
|
16
|
+
expect(publisher)
|
|
17
|
+
.to eq({
|
|
18
|
+
'id' => publisher['id'],
|
|
19
|
+
'name' => 'Nintendo'
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
publisher = Publisher.last
|
|
23
|
+
post "/publishers/#{publisher['id']}/games.json", params: {
|
|
24
|
+
game: {
|
|
25
|
+
name: 'Pokemon'
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
game = Game.last
|
|
30
|
+
|
|
31
|
+
expect(JSON.parse(response.body))
|
|
32
|
+
.to eq({
|
|
33
|
+
'id' => game.id,
|
|
34
|
+
'name' => 'Pokemon',
|
|
35
|
+
'publisher' => {
|
|
36
|
+
'name' => 'Nintendo'
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -1,24 +1,65 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
describe Azeroth::Decorator do
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
4
|
+
describe 'yard' do
|
|
5
|
+
describe '#as_json' do
|
|
6
|
+
it 'simple example' do
|
|
7
|
+
object = DummyModel.new(
|
|
8
|
+
id: 100,
|
|
9
|
+
first_name: 'John',
|
|
10
|
+
last_name: 'Wick',
|
|
11
|
+
favorite_pokemon: 'Arcanine'
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
decorator = DummyModel::Decorator.new(object)
|
|
15
|
+
|
|
16
|
+
expect(decorator.as_json).to eq(
|
|
17
|
+
'name' => 'John Wick',
|
|
18
|
+
'age' => nil,
|
|
19
|
+
'pokemon' => 'Arcanine'
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'complete example' do
|
|
24
|
+
master = PokemonMaster.create(
|
|
25
|
+
first_name: 'Ash',
|
|
26
|
+
last_name: 'Ketchum',
|
|
27
|
+
age: 10
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
master.create_favorite_pokemon(
|
|
31
|
+
name: 'pikachu',
|
|
32
|
+
nickname: 'Pikachu'
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
metapod = Pokemon.create(name: :metapod)
|
|
36
|
+
|
|
37
|
+
master.pokemons.create(
|
|
38
|
+
name: 'butterfree', previous_form: metapod
|
|
39
|
+
)
|
|
40
|
+
master.pokemons.create(name: 'squirtle')
|
|
41
|
+
|
|
42
|
+
decorator = PokemonMaster::Decorator.new(master)
|
|
14
43
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
44
|
+
expect(decorator.as_json).to eq(
|
|
45
|
+
{
|
|
46
|
+
'age' => 10,
|
|
47
|
+
'name' => 'Ash Ketchum',
|
|
48
|
+
'favorite_pokemon' => {
|
|
49
|
+
'name' => 'pikachu',
|
|
50
|
+
'nickname' => 'Pikachu'
|
|
51
|
+
},
|
|
52
|
+
'pokemons' => [{
|
|
53
|
+
'name' => 'butterfree',
|
|
54
|
+
'evolution_of' => 'metapod'
|
|
55
|
+
}, {
|
|
56
|
+
'name' => 'squirtle'
|
|
57
|
+
}, {
|
|
58
|
+
'name' => 'pikachu'
|
|
59
|
+
}]
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
end
|
|
22
63
|
end
|
|
23
64
|
end
|
|
24
65
|
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe GamesController, controller: true do
|
|
6
|
+
describe 'yard' do
|
|
7
|
+
describe 'POST create' do
|
|
8
|
+
it 'create game' do
|
|
9
|
+
post '/publishers.json', params: {
|
|
10
|
+
publisher: {
|
|
11
|
+
name: 'Nintendo'
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
publisher = JSON.parse(response.body)
|
|
16
|
+
expect(publisher)
|
|
17
|
+
.to eq({
|
|
18
|
+
'id' => publisher['id'],
|
|
19
|
+
'name' => 'Nintendo'
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
publisher = Publisher.last
|
|
23
|
+
post "/publishers/#{publisher['id']}/games.json", params: {
|
|
24
|
+
game: {
|
|
25
|
+
name: 'Pokemon'
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
game = Game.last
|
|
30
|
+
|
|
31
|
+
expect(JSON.parse(response.body))
|
|
32
|
+
.to eq({
|
|
33
|
+
'id' => game.id,
|
|
34
|
+
'name' => 'Pokemon',
|
|
35
|
+
'publisher' => {
|
|
36
|
+
'name' => 'Nintendo'
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: azeroth
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.
|
|
4
|
+
version: 0.6.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Darthjee
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-05-
|
|
11
|
+
date: 2020-05-06 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -452,7 +452,9 @@ files:
|
|
|
452
452
|
- spec/dummy/app/controllers/concerns/.keep
|
|
453
453
|
- spec/dummy/app/controllers/documents_controller.rb
|
|
454
454
|
- spec/dummy/app/controllers/documents_with_error_controller.rb
|
|
455
|
+
- spec/dummy/app/controllers/games_controller.rb
|
|
455
456
|
- spec/dummy/app/controllers/index_documents_controller.rb
|
|
457
|
+
- spec/dummy/app/controllers/publishers_controller.rb
|
|
456
458
|
- spec/dummy/app/helpers/application_helper.rb
|
|
457
459
|
- spec/dummy/app/jobs/application_job.rb
|
|
458
460
|
- spec/dummy/app/mailers/application_mailer.rb
|
|
@@ -465,10 +467,19 @@ files:
|
|
|
465
467
|
- spec/dummy/app/models/dummy_model/decorator.rb
|
|
466
468
|
- spec/dummy/app/models/factory.rb
|
|
467
469
|
- spec/dummy/app/models/factory/decorator_with_product.rb
|
|
470
|
+
- spec/dummy/app/models/game.rb
|
|
471
|
+
- spec/dummy/app/models/game/decorator.rb
|
|
468
472
|
- spec/dummy/app/models/id_decorator.rb
|
|
473
|
+
- spec/dummy/app/models/name_decorator.rb
|
|
474
|
+
- spec/dummy/app/models/pokemon.rb
|
|
475
|
+
- spec/dummy/app/models/pokemon/decorator.rb
|
|
476
|
+
- spec/dummy/app/models/pokemon/favorite_decorator.rb
|
|
477
|
+
- spec/dummy/app/models/pokemon_master.rb
|
|
478
|
+
- spec/dummy/app/models/pokemon_master/decorator.rb
|
|
469
479
|
- spec/dummy/app/models/product.rb
|
|
470
480
|
- spec/dummy/app/models/product/decorator.rb
|
|
471
481
|
- spec/dummy/app/models/product/decorator_with_factory.rb
|
|
482
|
+
- spec/dummy/app/models/publisher.rb
|
|
472
483
|
- spec/dummy/app/models/user.rb
|
|
473
484
|
- spec/dummy/app/views/documents/edit.html
|
|
474
485
|
- spec/dummy/app/views/documents/index.html
|
|
@@ -519,7 +530,10 @@ files:
|
|
|
519
530
|
- spec/dummy/storage/.keep
|
|
520
531
|
- spec/dummy/tmp/.keep
|
|
521
532
|
- spec/dummy/tmp/storage/.keep
|
|
533
|
+
- spec/integration/readme/azeroth/decorator_spec.rb
|
|
534
|
+
- spec/integration/readme/controllers/games_controller_spec.rb
|
|
522
535
|
- spec/integration/yard/azeroth/decorator_spec.rb
|
|
536
|
+
- spec/integration/yard/controllers/games_controller_spec.rb
|
|
523
537
|
- spec/lib/azeroth/decorator/hash_builder_spec.rb
|
|
524
538
|
- spec/lib/azeroth/decorator/key_value_extractor_spec.rb
|
|
525
539
|
- spec/lib/azeroth/decorator_spec.rb
|
|
@@ -545,7 +559,9 @@ files:
|
|
|
545
559
|
- spec/support/factories/document.rb
|
|
546
560
|
- spec/support/factories/dummy_model.rb
|
|
547
561
|
- spec/support/factories/factory.rb
|
|
562
|
+
- spec/support/factories/game.rb
|
|
548
563
|
- spec/support/factories/product.rb
|
|
564
|
+
- spec/support/factories/publisher.rb
|
|
549
565
|
- spec/support/factories/user.rb
|
|
550
566
|
- spec/support/factory_bot.rb
|
|
551
567
|
- spec/support/matchers/add_method.rb
|
|
@@ -591,7 +607,9 @@ test_files:
|
|
|
591
607
|
- spec/dummy/app/controllers/concerns/.keep
|
|
592
608
|
- spec/dummy/app/controllers/documents_controller.rb
|
|
593
609
|
- spec/dummy/app/controllers/documents_with_error_controller.rb
|
|
610
|
+
- spec/dummy/app/controllers/games_controller.rb
|
|
594
611
|
- spec/dummy/app/controllers/index_documents_controller.rb
|
|
612
|
+
- spec/dummy/app/controllers/publishers_controller.rb
|
|
595
613
|
- spec/dummy/app/helpers/application_helper.rb
|
|
596
614
|
- spec/dummy/app/jobs/application_job.rb
|
|
597
615
|
- spec/dummy/app/mailers/application_mailer.rb
|
|
@@ -604,10 +622,19 @@ test_files:
|
|
|
604
622
|
- spec/dummy/app/models/dummy_model/decorator.rb
|
|
605
623
|
- spec/dummy/app/models/factory.rb
|
|
606
624
|
- spec/dummy/app/models/factory/decorator_with_product.rb
|
|
625
|
+
- spec/dummy/app/models/game.rb
|
|
626
|
+
- spec/dummy/app/models/game/decorator.rb
|
|
607
627
|
- spec/dummy/app/models/id_decorator.rb
|
|
628
|
+
- spec/dummy/app/models/name_decorator.rb
|
|
629
|
+
- spec/dummy/app/models/pokemon.rb
|
|
630
|
+
- spec/dummy/app/models/pokemon/decorator.rb
|
|
631
|
+
- spec/dummy/app/models/pokemon/favorite_decorator.rb
|
|
632
|
+
- spec/dummy/app/models/pokemon_master.rb
|
|
633
|
+
- spec/dummy/app/models/pokemon_master/decorator.rb
|
|
608
634
|
- spec/dummy/app/models/product.rb
|
|
609
635
|
- spec/dummy/app/models/product/decorator.rb
|
|
610
636
|
- spec/dummy/app/models/product/decorator_with_factory.rb
|
|
637
|
+
- spec/dummy/app/models/publisher.rb
|
|
611
638
|
- spec/dummy/app/models/user.rb
|
|
612
639
|
- spec/dummy/app/views/documents/edit.html
|
|
613
640
|
- spec/dummy/app/views/documents/index.html
|
|
@@ -658,7 +685,10 @@ test_files:
|
|
|
658
685
|
- spec/dummy/storage/.keep
|
|
659
686
|
- spec/dummy/tmp/.keep
|
|
660
687
|
- spec/dummy/tmp/storage/.keep
|
|
688
|
+
- spec/integration/readme/azeroth/decorator_spec.rb
|
|
689
|
+
- spec/integration/readme/controllers/games_controller_spec.rb
|
|
661
690
|
- spec/integration/yard/azeroth/decorator_spec.rb
|
|
691
|
+
- spec/integration/yard/controllers/games_controller_spec.rb
|
|
662
692
|
- spec/lib/azeroth/decorator/hash_builder_spec.rb
|
|
663
693
|
- spec/lib/azeroth/decorator/key_value_extractor_spec.rb
|
|
664
694
|
- spec/lib/azeroth/decorator_spec.rb
|
|
@@ -684,7 +714,9 @@ test_files:
|
|
|
684
714
|
- spec/support/factories/document.rb
|
|
685
715
|
- spec/support/factories/dummy_model.rb
|
|
686
716
|
- spec/support/factories/factory.rb
|
|
717
|
+
- spec/support/factories/game.rb
|
|
687
718
|
- spec/support/factories/product.rb
|
|
719
|
+
- spec/support/factories/publisher.rb
|
|
688
720
|
- spec/support/factories/user.rb
|
|
689
721
|
- spec/support/factory_bot.rb
|
|
690
722
|
- spec/support/matchers/add_method.rb
|