azeroth 0.10.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +3 -3
- data/Dockerfile +1 -1
- data/README.md +43 -30
- data/azeroth.gemspec +8 -7
- data/config/check_specs.yml +1 -0
- data/lib/azeroth/decorator/class_methods.rb +249 -0
- data/lib/azeroth/decorator/hash_builder.rb +3 -1
- data/lib/azeroth/decorator/key_value_extractor.rb +3 -8
- data/lib/azeroth/decorator/method_builder.rb +23 -7
- data/lib/azeroth/decorator/options.rb +3 -1
- data/lib/azeroth/decorator.rb +30 -188
- data/lib/azeroth/params_builder.rb +11 -8
- data/lib/azeroth/request_handler/index.rb +7 -33
- data/lib/azeroth/request_handler/pagination.rb +53 -0
- data/lib/azeroth/request_handler.rb +8 -7
- data/lib/azeroth/resource_builder.rb +9 -10
- data/lib/azeroth/resourceable/builder.rb +15 -11
- data/lib/azeroth/routes_builder.rb +8 -10
- data/lib/azeroth/version.rb +1 -1
- data/spec/controllers/documents_with_error_controller_spec.rb +3 -1
- data/spec/dummy/app/models/website/decorator.rb +11 -0
- data/spec/dummy/app/models/website/with_location.rb +21 -0
- data/spec/dummy/app/models/website.rb +4 -0
- data/spec/dummy/config/environments/development.rb +1 -0
- data/spec/dummy/db/schema.rb +5 -1
- data/spec/integration/yard/azeroth/decorator_spec.rb +15 -0
- data/spec/lib/azeroth/decorator/key_value_extractor_spec.rb +3 -1
- data/spec/lib/azeroth/decorator/method_builder_spec.rb +61 -2
- data/spec/lib/azeroth/decorator_spec.rb +96 -3
- data/spec/lib/azeroth/params_builder_spec.rb +3 -1
- data/spec/lib/azeroth/request_handler/pagination_spec.rb +133 -0
- data/spec/lib/azeroth/resource_builder_spec.rb +3 -1
- data/spec/lib/azeroth/routes_builder_spec.rb +3 -1
- metadata +41 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c8e0229917b320108b25371d2c30ca48f83663288d50d2e767b8cf45c037c95
|
4
|
+
data.tar.gz: 2e6fe774d10fa5b5ca3f22c0b4deac4828a28480ebd3ebb1cce370c84c0f359c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b517e33573aa729a94fee810f0f4cea17a39533359332017e1dea8a3d80c74aacaac1010754739d8ba312d42353c57bb93d0c172aa640453450383ea1ff99328
|
7
|
+
data.tar.gz: 7bdfbfce3bdc6f40c2c82ea904a5778b5d0e7cc037f4fbf73f2e7d5fe8a449b7dacbac41f55523afea298bea5de998cc5d442e395fbf4949e555775aeabccff4
|
data/.circleci/config.yml
CHANGED
@@ -22,7 +22,7 @@ workflows:
|
|
22
22
|
jobs:
|
23
23
|
test:
|
24
24
|
docker:
|
25
|
-
- image: darthjee/circleci_rails_gems:1.
|
25
|
+
- image: darthjee/circleci_rails_gems:1.2.0
|
26
26
|
environment:
|
27
27
|
PROJECT: azeroth
|
28
28
|
steps:
|
@@ -41,7 +41,7 @@ jobs:
|
|
41
41
|
command: cc-test-reporter after-build --exit-code $?
|
42
42
|
checks:
|
43
43
|
docker:
|
44
|
-
- image: darthjee/circleci_rails_gems:1.
|
44
|
+
- image: darthjee/circleci_rails_gems:1.2.0
|
45
45
|
environment:
|
46
46
|
PROJECT: azeroth
|
47
47
|
steps:
|
@@ -66,7 +66,7 @@ jobs:
|
|
66
66
|
command: check_specs
|
67
67
|
build-and-release:
|
68
68
|
docker:
|
69
|
-
- image: darthjee/circleci_rails_gems:1.
|
69
|
+
- image: darthjee/circleci_rails_gems:1.2.0
|
70
70
|
environment:
|
71
71
|
PROJECT: azeroth
|
72
72
|
steps:
|
data/Dockerfile
CHANGED
data/README.md
CHANGED
@@ -11,7 +11,7 @@ Azeroth
|
|
11
11
|
|
12
12
|
Yard Documentation
|
13
13
|
-------------------
|
14
|
-
[https://www.rubydoc.info/gems/azeroth/
|
14
|
+
[https://www.rubydoc.info/gems/azeroth/1.1.0](https://www.rubydoc.info/gems/azeroth/1.1.0)
|
15
15
|
|
16
16
|
Azeroth has been designed making the coding of controllers easier
|
17
17
|
as routes in controllers are usually copy, paste and replace of same
|
@@ -25,6 +25,10 @@ does not perform database operations
|
|
25
25
|
Future versions will enable `html` rendering to also perform
|
26
26
|
database operations.
|
27
27
|
|
28
|
+
Current Release: [1.1.0](https://github.com/darthjee/azeroth/tree/1.1.0)
|
29
|
+
|
30
|
+
[Next release](https://github.com/darthjee/azeroth/compare/1.1.0...master)
|
31
|
+
|
28
32
|
Installation
|
29
33
|
---------------
|
30
34
|
|
@@ -131,12 +135,50 @@ It accepts options
|
|
131
135
|
end
|
132
136
|
```
|
133
137
|
|
138
|
+
```ruby
|
139
|
+
class PaginatedDocumentsController < ApplicationController
|
140
|
+
include Azeroth::Resourceable
|
141
|
+
|
142
|
+
resource_for :document, only: 'index', paginated: true
|
143
|
+
end
|
144
|
+
|
145
|
+
30.times { create(:document) }
|
146
|
+
|
147
|
+
get '/paginated_documents.json'
|
148
|
+
|
149
|
+
# returns Array with 20 first documents
|
150
|
+
# returns in the headers pagination headers
|
151
|
+
# {
|
152
|
+
# 'pages' => 2,
|
153
|
+
# 'per_page' => 20,
|
154
|
+
# 'page' => 1
|
155
|
+
# }
|
156
|
+
|
157
|
+
get '/paginated_documents.json?page=2'
|
158
|
+
|
159
|
+
# returns Array with 10 next documents
|
160
|
+
# returns in the headers pagination headers
|
161
|
+
# {
|
162
|
+
# 'pages' => 2,
|
163
|
+
# 'per_page' => 20,
|
164
|
+
# 'page' => 2
|
165
|
+
# }
|
166
|
+
```
|
167
|
+
|
134
168
|
## Azeroth::Decorator
|
135
169
|
|
136
170
|
[Decorators](https://www.rubydoc.info/gems/azeroth/Azeroth/Decorator) are
|
137
171
|
used to define how an object is exposed as json on controller responses
|
138
172
|
defining which and how fields will be exposed
|
139
173
|
|
174
|
+
Exposing options:
|
175
|
+
|
176
|
+
- as: custom key to expose the value as
|
177
|
+
- if: method/block to be called checking if an attribute should or should not be exposed
|
178
|
+
- decorator: flag to use or not a decorator or decorator class to be used
|
179
|
+
- reader: Flag indicating if a reader to access the attribute should be created. usefull if you want method_missing to take over
|
180
|
+
- override: Flag indicating if an existing method should be overriden. This is useful when a method acessor was included from another module
|
181
|
+
|
140
182
|
```ruby
|
141
183
|
# pokemon/decorator.rb
|
142
184
|
|
@@ -172,35 +214,6 @@ defining which and how fields will be exposed
|
|
172
214
|
end
|
173
215
|
```
|
174
216
|
|
175
|
-
```ruby
|
176
|
-
class PaginatedDocumentsController < ApplicationController
|
177
|
-
include Azeroth::Resourceable
|
178
|
-
|
179
|
-
resource_for :document, only: 'index', paginated: true
|
180
|
-
end
|
181
|
-
|
182
|
-
30.times { create(:document) }
|
183
|
-
|
184
|
-
get '/paginated_documents.json'
|
185
|
-
|
186
|
-
# returns Array with 20 first documents
|
187
|
-
# returns in the headers pagination headers
|
188
|
-
{
|
189
|
-
'pages' => 2,
|
190
|
-
'per_page' => 20,
|
191
|
-
'page' => 1
|
192
|
-
}
|
193
|
-
|
194
|
-
get '/paginated_documents.json?page=2'
|
195
|
-
|
196
|
-
# returns Array with 10 next documents
|
197
|
-
# returns in the headers pagination headers
|
198
|
-
{
|
199
|
-
'pages' => 2,
|
200
|
-
'per_page' => 20,
|
201
|
-
'page' => 2
|
202
|
-
}
|
203
|
-
```
|
204
217
|
Exposing is done through the class method
|
205
218
|
[expose](https://www.rubydoc.info/gems/azeroth/Azeroth/Decorator#expose-class_method)
|
206
219
|
which accepts several options:
|
data/azeroth.gemspec
CHANGED
@@ -18,20 +18,20 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
19
|
gem.require_paths = ['lib']
|
20
20
|
|
21
|
-
gem.add_runtime_dependency 'activesupport', '~>
|
21
|
+
gem.add_runtime_dependency 'activesupport', '~> 7.0.x'
|
22
22
|
gem.add_runtime_dependency 'darthjee-active_ext', '>= 1.3.2'
|
23
23
|
gem.add_runtime_dependency 'jace', '>= 0.1.1'
|
24
|
-
gem.add_runtime_dependency 'sinclair', '>=
|
24
|
+
gem.add_runtime_dependency 'sinclair', '>= 2.0.0'
|
25
25
|
|
26
|
-
gem.add_development_dependency 'actionpack', '
|
27
|
-
gem.add_development_dependency 'activerecord', '
|
28
|
-
gem.add_development_dependency 'bundler', '~> 2.
|
26
|
+
gem.add_development_dependency 'actionpack', '7.0.4.3'
|
27
|
+
gem.add_development_dependency 'activerecord', '7.0.4.3'
|
28
|
+
gem.add_development_dependency 'bundler', '~> 2.4.8'
|
29
29
|
gem.add_development_dependency 'factory_bot', '6.2.1'
|
30
30
|
gem.add_development_dependency 'minitest', '5.16.2'
|
31
|
-
gem.add_development_dependency 'nokogiri', '1.13.
|
31
|
+
gem.add_development_dependency 'nokogiri', '1.13.8'
|
32
32
|
gem.add_development_dependency 'pry', '0.14.1'
|
33
33
|
gem.add_development_dependency 'pry-nav', '1.0.0'
|
34
|
-
gem.add_development_dependency 'rails', '
|
34
|
+
gem.add_development_dependency 'rails', '7.0.4.3'
|
35
35
|
gem.add_development_dependency 'rails-controller-testing', '1.0.5'
|
36
36
|
gem.add_development_dependency 'rake', '13.0.6'
|
37
37
|
gem.add_development_dependency 'reek', '6.0.3'
|
@@ -47,6 +47,7 @@ Gem::Specification.new do |gem|
|
|
47
47
|
gem.add_development_dependency 'rubycritic', '4.7.0'
|
48
48
|
gem.add_development_dependency 'shoulda-matchers', '4.3.0'
|
49
49
|
gem.add_development_dependency 'simplecov', '0.21.2'
|
50
|
+
gem.add_development_dependency 'sprockets-rails', '3.4.2'
|
50
51
|
gem.add_development_dependency 'sqlite3', '1.4.2'
|
51
52
|
gem.add_development_dependency 'tzinfo-data', '~> 1.2022.1'
|
52
53
|
gem.add_development_dependency 'yard', '0.9.27'
|
data/config/check_specs.yml
CHANGED
@@ -0,0 +1,249 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Azeroth
|
4
|
+
class Decorator
|
5
|
+
# @api private
|
6
|
+
# @author Darthjee
|
7
|
+
#
|
8
|
+
# Class methods added by {Decorator}
|
9
|
+
#
|
10
|
+
# @see ClassMethods#expose
|
11
|
+
module ClassMethods
|
12
|
+
# @api private
|
13
|
+
#
|
14
|
+
# All attributes exposed
|
15
|
+
#
|
16
|
+
# @return [Hash<Symbol,Hash>]
|
17
|
+
def attributes_map
|
18
|
+
@attributes_map ||= build_attributes_map
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
# @api private
|
24
|
+
# @private
|
25
|
+
#
|
26
|
+
# Initialize attributes to be exposed map
|
27
|
+
#
|
28
|
+
# When the class inherity from another
|
29
|
+
# decorator, the new class should expose the
|
30
|
+
# same attributes.
|
31
|
+
#
|
32
|
+
# @return [Hash<Symbol,Hash>]
|
33
|
+
def build_attributes_map
|
34
|
+
superclass.try(:attributes_map).dup || {}
|
35
|
+
end
|
36
|
+
|
37
|
+
# @visibility public
|
38
|
+
# @api (see Decorator.expose)
|
39
|
+
# @private
|
40
|
+
#
|
41
|
+
# Expose attributes on json decorated
|
42
|
+
#
|
43
|
+
# @param (see Decorator.expose)
|
44
|
+
# @option (see Decorator.expose)
|
45
|
+
#
|
46
|
+
# @return (see Decorator.expose)
|
47
|
+
#
|
48
|
+
# @example Simple usage
|
49
|
+
# class DummyModel
|
50
|
+
# include ActiveModel::Model
|
51
|
+
#
|
52
|
+
# attr_accessor :id, :first_name, :last_name, :age,
|
53
|
+
# :favorite_pokemon
|
54
|
+
#
|
55
|
+
# class Decorator < Azeroth::Decorator
|
56
|
+
# expose :name
|
57
|
+
# expose :age
|
58
|
+
# expose :favorite_pokemon, as: :pokemon
|
59
|
+
#
|
60
|
+
# def name
|
61
|
+
# [object.first_name, object.last_name].join(' ')
|
62
|
+
# end
|
63
|
+
# end
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
# @example With relations
|
67
|
+
# # pokemon/decorator.rb
|
68
|
+
#
|
69
|
+
# class Pokemon::Decorator < Azeroth::Decorator
|
70
|
+
# expose :name
|
71
|
+
# expose :previous_form_name, as: :evolution_of, if: :evolution?
|
72
|
+
#
|
73
|
+
# def evolution?
|
74
|
+
# previous_form
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# def previous_form_name
|
78
|
+
# previous_form.name
|
79
|
+
# end
|
80
|
+
# end
|
81
|
+
#
|
82
|
+
# # pokemon/favorite_decorator.rb
|
83
|
+
#
|
84
|
+
# class Pokemon::FavoriteDecorator < Pokemon::Decorator
|
85
|
+
# expose :nickname
|
86
|
+
# end
|
87
|
+
#
|
88
|
+
# # pokemon_master/decorator.rb
|
89
|
+
#
|
90
|
+
# class PokemonMaster < ActiveRecord::Base
|
91
|
+
# has_one :favorite_pokemon, -> { where(favorite: true) },
|
92
|
+
# class_name: 'Pokemon'
|
93
|
+
# has_many :pokemons
|
94
|
+
# end
|
95
|
+
#
|
96
|
+
# # pokemon.rb
|
97
|
+
#
|
98
|
+
# class Pokemon < ActiveRecord::Base
|
99
|
+
# belongs_to :pokemon_master
|
100
|
+
# has_one :previous_form,
|
101
|
+
# class_name: 'Pokemon',
|
102
|
+
# foreign_key: :previous_form_id
|
103
|
+
# end
|
104
|
+
#
|
105
|
+
# # pokemon_master.rb
|
106
|
+
#
|
107
|
+
# class PokemonMaster::Decorator < Azeroth::Decorator
|
108
|
+
# expose :name
|
109
|
+
# expose :age
|
110
|
+
# expose :favorite_pokemon, decorator: Pokemon::FavoriteDecorator
|
111
|
+
# expose :pokemons
|
112
|
+
#
|
113
|
+
# def name
|
114
|
+
# [
|
115
|
+
# first_name,
|
116
|
+
# last_name
|
117
|
+
# ].compact.join(' ')
|
118
|
+
# end
|
119
|
+
# end
|
120
|
+
#
|
121
|
+
# # schema.rb
|
122
|
+
#
|
123
|
+
# ActiveRecord::Schema.define do
|
124
|
+
# self.verbose = false
|
125
|
+
#
|
126
|
+
# create_table :pokemon_masters, force: true do |t|
|
127
|
+
# t.string :first_name, null: false
|
128
|
+
# t.string :last_name
|
129
|
+
# t.integer :age, null: false
|
130
|
+
# end
|
131
|
+
#
|
132
|
+
# create_table :pokemons, force: true do |t|
|
133
|
+
# t.string :name, null: false
|
134
|
+
# t.string :nickname
|
135
|
+
# t.integer :pokemon_master_id
|
136
|
+
# t.boolean :favorite
|
137
|
+
# t.integer :previous_form_id
|
138
|
+
# t.index %i[pokemon_master_id favorite], unique: true
|
139
|
+
# end
|
140
|
+
#
|
141
|
+
# add_foreign_key 'pokemons', 'pokemon_masters'
|
142
|
+
# end
|
143
|
+
#
|
144
|
+
# # test.rb
|
145
|
+
#
|
146
|
+
# master = PokemonMaster.create(
|
147
|
+
# first_name: 'Ash',
|
148
|
+
# last_name: 'Ketchum',
|
149
|
+
# age: 10
|
150
|
+
# )
|
151
|
+
#
|
152
|
+
# master.create_favorite_pokemon(
|
153
|
+
# name: 'pikachu',
|
154
|
+
# nickname: 'Pikachu'
|
155
|
+
# )
|
156
|
+
#
|
157
|
+
# metapod = Pokemon.create(name: :metapod)
|
158
|
+
#
|
159
|
+
# master.pokemons.create(
|
160
|
+
# name: 'butterfree', previous_form: metapod
|
161
|
+
# )
|
162
|
+
# master.pokemons.create(name: 'squirtle')
|
163
|
+
#
|
164
|
+
# decorator = PokemonMaster::Decorator.new(master)
|
165
|
+
#
|
166
|
+
# decorator.as_json
|
167
|
+
# # returns
|
168
|
+
# # {
|
169
|
+
# # 'age' => 10,
|
170
|
+
# # 'name' => 'Ash Ketchum',
|
171
|
+
# # 'favorite_pokemon' => {
|
172
|
+
# # 'name' => 'pikachu',
|
173
|
+
# # 'nickname' => 'Pikachu'
|
174
|
+
# # },
|
175
|
+
# # 'pokemons' => [{
|
176
|
+
# # 'name' => 'butterfree',
|
177
|
+
# # 'evolution_of' => 'metapod'
|
178
|
+
# # }, {
|
179
|
+
# # 'name' => 'squirtle'
|
180
|
+
# # }, {
|
181
|
+
# # 'name' => 'pikachu'
|
182
|
+
# # }]
|
183
|
+
# # }
|
184
|
+
#
|
185
|
+
# @example With method building options
|
186
|
+
# ActiveRecord::Schema.define do
|
187
|
+
# self.verbose = false
|
188
|
+
#
|
189
|
+
# create_table :websites, force: true do |t|
|
190
|
+
# t.string :domain, null: false
|
191
|
+
# t.integer :port, limit: 2, unsigned: true
|
192
|
+
# t.string :protocol, limit: 5
|
193
|
+
# end
|
194
|
+
# end
|
195
|
+
#
|
196
|
+
# class Website < ActiveRecord::Base
|
197
|
+
# end
|
198
|
+
#
|
199
|
+
# class Website < ActiveRecord::Base
|
200
|
+
# module WithLocation
|
201
|
+
# def location
|
202
|
+
# "#{protocol}://#{domain}:#{port}"
|
203
|
+
# end
|
204
|
+
#
|
205
|
+
# def protocol
|
206
|
+
# website.protocol || '*'
|
207
|
+
# end
|
208
|
+
#
|
209
|
+
# def domain
|
210
|
+
# website.domain || '*'
|
211
|
+
# end
|
212
|
+
#
|
213
|
+
# def port
|
214
|
+
# website.port || '*'
|
215
|
+
# end
|
216
|
+
# end
|
217
|
+
# end
|
218
|
+
#
|
219
|
+
# class Website < ActiveRecord::Base
|
220
|
+
# class Decorator < Azeroth::Decorator
|
221
|
+
# include WithLocation
|
222
|
+
#
|
223
|
+
# expose :location, override: false
|
224
|
+
#
|
225
|
+
# alias website object
|
226
|
+
# end
|
227
|
+
# end
|
228
|
+
#
|
229
|
+
# website = Website.create(
|
230
|
+
# protocol: :http,
|
231
|
+
# domain: 'google.com'
|
232
|
+
# )
|
233
|
+
#
|
234
|
+
# decorator = Website::Decorator.new(website)
|
235
|
+
#
|
236
|
+
# decorator.as_json
|
237
|
+
#
|
238
|
+
# # returns
|
239
|
+
# # { 'location' => 'http://google.com:*' }
|
240
|
+
def expose(attribute, **options_hash)
|
241
|
+
options = Decorator::Options.new(options_hash)
|
242
|
+
|
243
|
+
MethodBuilder.build_reader(self, attribute, options)
|
244
|
+
|
245
|
+
attributes_map[attribute] = options
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
@@ -25,7 +25,9 @@ module Azeroth
|
|
25
25
|
# @return [Hash]
|
26
26
|
def as_json
|
27
27
|
attributes_map.inject({}) do |hash, (method, options)|
|
28
|
-
new_hash = KeyValueExtractor.new(
|
28
|
+
new_hash = KeyValueExtractor.new(
|
29
|
+
decorator: decorator, attribute: method, options: options
|
30
|
+
).as_json
|
29
31
|
hash.merge!(new_hash)
|
30
32
|
end
|
31
33
|
end
|
@@ -11,18 +11,14 @@ module Azeroth
|
|
11
11
|
#
|
12
12
|
# A decorator is infered for the value / attribute
|
13
13
|
# or used from the options given
|
14
|
-
class KeyValueExtractor
|
14
|
+
class KeyValueExtractor < Sinclair::Model
|
15
|
+
initialize_with(:decorator, :attribute, :options)
|
15
16
|
# @param decorator [Decorator] decorator object
|
16
17
|
# @param attribute [Symbol] attribute to be used on output hash
|
17
18
|
# @param options [Decorator::Options] decoration options
|
18
19
|
# @option options if [Proc,Symbol] conditional to be
|
19
20
|
# checked when exposing field
|
20
21
|
# (see {Decorator::Options#if})
|
21
|
-
def initialize(decorator, attribute, options)
|
22
|
-
@decorator = decorator
|
23
|
-
@attribute = attribute
|
24
|
-
@options = options
|
25
|
-
end
|
26
22
|
|
27
23
|
# Return hash for attribute
|
28
24
|
#
|
@@ -38,9 +34,8 @@ module Azeroth
|
|
38
34
|
}
|
39
35
|
end
|
40
36
|
|
41
|
-
|
37
|
+
private
|
42
38
|
|
43
|
-
attr_reader :decorator, :attribute, :options
|
44
39
|
# @method decorator
|
45
40
|
# @api private
|
46
41
|
# @private
|
@@ -7,20 +7,36 @@ module Azeroth
|
|
7
7
|
# Responsible for building readers for attributes
|
8
8
|
# @api private
|
9
9
|
class MethodBuilder < Sinclair
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
10
|
+
class << self
|
11
|
+
# Builds reader
|
12
|
+
#
|
13
|
+
# reaader delegate method calls to @object
|
14
|
+
#
|
15
|
+
# @return [Array<Sinclair::MethodDefinition>]
|
16
|
+
def build_reader(klass, attribute, options)
|
17
|
+
new(klass, options).build_reader(attribute)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(klass, options)
|
22
|
+
super(klass)
|
23
|
+
@options = options
|
17
24
|
end
|
18
25
|
|
19
26
|
# (see MethodBuilder.build_reader)
|
20
27
|
def build_reader(attribute)
|
28
|
+
return if skip_creation?(attribute)
|
29
|
+
|
21
30
|
add_method(attribute, "@object.#{attribute}")
|
22
31
|
build
|
23
32
|
end
|
33
|
+
|
34
|
+
def skip_creation?(attribute)
|
35
|
+
return true unless options.reader
|
36
|
+
return false unless klass.method_defined?(attribute)
|
37
|
+
|
38
|
+
!options.override
|
39
|
+
end
|
24
40
|
end
|
25
41
|
end
|
26
42
|
end
|