apipie-rails 0.0.17 → 0.0.18
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.
- data/.gitignore +2 -0
- data/CHANGELOG +6 -0
- data/README.rst +106 -1
- data/lib/apipie-rails.rb +1 -1
- data/lib/apipie/application.rb +14 -29
- data/lib/apipie/dsl_definition.rb +226 -158
- data/lib/apipie/method_description.rb +30 -20
- data/lib/apipie/param_description.rb +98 -10
- data/lib/apipie/railtie.rb +4 -1
- data/lib/apipie/resource_description.rb +6 -5
- data/lib/apipie/validator.rb +45 -14
- data/lib/apipie/version.rb +1 -1
- data/spec/controllers/apipies_controller_spec.rb +3 -0
- data/spec/controllers/users_controller_spec.rb +13 -20
- data/spec/dummy/app/controllers/api/v1/architectures_controller.rb +13 -3
- data/spec/dummy/app/controllers/api/v2/architectures_controller.rb +1 -3
- data/spec/dummy/app/controllers/users_controller.rb +26 -3
- data/spec/lib/method_description_spec.rb +6 -5
- data/spec/lib/param_description_spec.rb +82 -6
- data/spec/lib/param_group_spec.rb +45 -0
- data/spec/lib/resource_description_spec.rb +9 -7
- metadata +18 -18
- data/.rvmrc +0 -1
- data/Gemfile.lock +0 -117
@@ -17,26 +17,33 @@ module Apipie
|
|
17
17
|
|
18
18
|
attr_reader :full_description, :method, :resource, :apis, :examples, :see, :formats
|
19
19
|
|
20
|
-
def initialize(method, resource,
|
20
|
+
def initialize(method, resource, dsl_data)
|
21
21
|
@method = method.to_s
|
22
22
|
@resource = resource
|
23
23
|
|
24
|
-
@apis =
|
25
|
-
|
26
|
-
|
24
|
+
@apis = dsl_data[:api_args].map do |method, path, desc|
|
25
|
+
MethodDescription::Api.new(method, path, desc)
|
26
|
+
end
|
27
27
|
|
28
|
-
desc =
|
28
|
+
desc = dsl_data[:description] || ''
|
29
29
|
@full_description = Apipie.markup_to_html(desc)
|
30
|
-
@errors = app.last_dsl_data[:errors]
|
31
|
-
@params_ordered = app.last_dsl_data[:params]
|
32
|
-
@examples = app.last_dsl_data[:examples]
|
33
30
|
|
31
|
+
@errors = dsl_data[:errors].map do |args|
|
32
|
+
Apipie::ErrorDescription.new(args)
|
33
|
+
end
|
34
|
+
|
35
|
+
@see = dsl_data[:see].map do |args|
|
36
|
+
Apipie::SeeDescription.new(args)
|
37
|
+
end
|
38
|
+
|
39
|
+
@formats = dsl_data[:formats]
|
40
|
+
@examples = dsl_data[:examples]
|
34
41
|
@examples += load_recorded_examples
|
35
42
|
|
36
|
-
|
37
|
-
|
38
|
-
@parent_resource = parent.controller_name
|
43
|
+
@params_ordered = dsl_data[:params].map do |args|
|
44
|
+
Apipie::ParamDescription.from_dsl_data(self, args)
|
39
45
|
end
|
46
|
+
@params_ordered = ParamDescription.unify(@params_ordered)
|
40
47
|
end
|
41
48
|
|
42
49
|
def id
|
@@ -49,15 +56,14 @@ module Apipie
|
|
49
56
|
|
50
57
|
def params_ordered
|
51
58
|
all_params = []
|
52
|
-
|
53
|
-
if @parent_resource
|
54
|
-
parent = Apipie.get_resource_description(@parent_resource)
|
55
|
-
merge_params(all_params, parent._params_ordered) if parent
|
56
|
-
end
|
59
|
+
parent = Apipie.get_resource_description(@resource.controller.superclass)
|
57
60
|
|
58
|
-
# get params from
|
59
|
-
|
60
|
-
|
61
|
+
# get params from parent resource description
|
62
|
+
[parent, @resource].compact.each do |resource|
|
63
|
+
resource_params = resource._params_args.map do |args|
|
64
|
+
Apipie::ParamDescription.from_dsl_data(self, args)
|
65
|
+
end
|
66
|
+
merge_params(all_params, resource_params)
|
61
67
|
end
|
62
68
|
|
63
69
|
merge_params(all_params, @params_ordered)
|
@@ -68,8 +74,12 @@ module Apipie
|
|
68
74
|
return @merged_errors if @merged_errors
|
69
75
|
@merged_errors = []
|
70
76
|
if @resource
|
77
|
+
resource_errors = @resource._errors_args.map do |args|
|
78
|
+
Apipie::ErrorDescription.new(args)
|
79
|
+
end
|
80
|
+
|
71
81
|
# exclude overwritten parent errors
|
72
|
-
@merged_errors =
|
82
|
+
@merged_errors = resource_errors.find_all do |err|
|
73
83
|
!@errors.any? { |e| e.code == err.code }
|
74
84
|
end
|
75
85
|
end
|
@@ -8,14 +8,24 @@ module Apipie
|
|
8
8
|
# validator - Validator::BaseValidator subclass
|
9
9
|
class ParamDescription
|
10
10
|
|
11
|
-
attr_reader :name, :desc, :
|
11
|
+
attr_reader :method_description, :name, :desc, :allow_nil, :validator, :options
|
12
12
|
|
13
|
-
attr_accessor :parent
|
13
|
+
attr_accessor :parent, :required
|
14
14
|
|
15
|
-
def
|
15
|
+
def self.from_dsl_data(method_description, args)
|
16
|
+
param_name, validator, desc_or_options, options, block = args
|
17
|
+
Apipie::ParamDescription.new(method_description,
|
18
|
+
param_name,
|
19
|
+
validator,
|
20
|
+
desc_or_options,
|
21
|
+
options,
|
22
|
+
&block)
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(method_description, name, validator, desc_or_options = nil, options = {}, &block)
|
16
26
|
|
17
|
-
if desc_or_options.is_a?(Hash)
|
18
|
-
options = desc_or_options
|
27
|
+
if desc_or_options.is_a?(Hash)
|
28
|
+
options = options.merge(desc_or_options)
|
19
29
|
elsif desc_or_options.is_a?(String)
|
20
30
|
options[:desc] = desc_or_options
|
21
31
|
elsif !desc_or_options.nil?
|
@@ -24,19 +34,27 @@ module Apipie
|
|
24
34
|
|
25
35
|
options.symbolize_keys!
|
26
36
|
|
37
|
+
# we save options to know what was passed in DSL
|
38
|
+
@options = options
|
39
|
+
|
40
|
+
@method_description = method_description
|
27
41
|
@name = name
|
28
|
-
@desc = Apipie.markup_to_html(options[:desc] || '')
|
29
|
-
@
|
30
|
-
|
42
|
+
@desc = Apipie.markup_to_html(@options[:desc] || '')
|
43
|
+
@parent = @options[:parent]
|
44
|
+
@required = if @options.has_key? :required
|
45
|
+
@options[:required]
|
31
46
|
else
|
32
47
|
Apipie.configuration.required_by_default?
|
33
48
|
end
|
34
|
-
|
49
|
+
|
50
|
+
@allow_nil = @options[:allow_nil] || false
|
51
|
+
|
52
|
+
action_awareness
|
35
53
|
|
36
54
|
@validator = nil
|
37
55
|
unless validator.nil?
|
38
56
|
@validator =
|
39
|
-
Validator::BaseValidator.find(self, validator, options, block)
|
57
|
+
Validator::BaseValidator.find(self, validator, @options, block)
|
40
58
|
raise "Validator not found." unless validator
|
41
59
|
end
|
42
60
|
end
|
@@ -91,6 +109,76 @@ module Apipie
|
|
91
109
|
end
|
92
110
|
end
|
93
111
|
|
112
|
+
def merge_with(other_param_desc)
|
113
|
+
if self.validator && other_param_desc.validator
|
114
|
+
self.validator.merge_with(other_param_desc.validator)
|
115
|
+
else
|
116
|
+
self.validator ||= other_param_desc.validator
|
117
|
+
end
|
118
|
+
self
|
119
|
+
end
|
120
|
+
|
121
|
+
# merge param descripsiont. Allows defining hash params on more places
|
122
|
+
# (e.g. in param_groups). For example:
|
123
|
+
#
|
124
|
+
# def_param_group :user do
|
125
|
+
# param :user, Hash do
|
126
|
+
# param :name, String
|
127
|
+
# end
|
128
|
+
# end
|
129
|
+
#
|
130
|
+
# param_group :user
|
131
|
+
# param :user, Hash do
|
132
|
+
# param :password, String
|
133
|
+
# end
|
134
|
+
def self.unify(params)
|
135
|
+
ordering = params.map(&:name)
|
136
|
+
params.group_by(&:name).map do |name, param_descs|
|
137
|
+
param_descs.reduce(&:merge_with)
|
138
|
+
end.sort_by { |param| ordering.index(param.name) }
|
139
|
+
end
|
140
|
+
|
141
|
+
# action awareness is being inherited from ancestors (in terms of
|
142
|
+
# nested params)
|
143
|
+
def action_aware?
|
144
|
+
if @options.has_key?(:action_aware)
|
145
|
+
return @options[:action_aware]
|
146
|
+
elsif @parent
|
147
|
+
@parent.action_aware?
|
148
|
+
else
|
149
|
+
false
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def as_action
|
154
|
+
if @options[:param_group] && @options[:param_group][:options] &&
|
155
|
+
@options[:param_group][:options][:as]
|
156
|
+
@options[:param_group][:options][:as].to_s
|
157
|
+
elsif @parent
|
158
|
+
@parent.as_action
|
159
|
+
else
|
160
|
+
@method_description.method
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# makes modification that are based on the action that the param
|
165
|
+
# is defined for. Typical for required and allow_nil variations in
|
166
|
+
# crate/update actions.
|
167
|
+
def action_awareness
|
168
|
+
if action_aware?
|
169
|
+
if !@options.has_key?(:allow_nil)
|
170
|
+
if @required
|
171
|
+
@allow_nil = false
|
172
|
+
else
|
173
|
+
@allow_nil = true
|
174
|
+
end
|
175
|
+
end
|
176
|
+
if as_action != "create"
|
177
|
+
@required = false
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
94
182
|
end
|
95
183
|
|
96
184
|
end
|
data/lib/apipie/railtie.rb
CHANGED
@@ -2,7 +2,10 @@ module Apipie
|
|
2
2
|
class Railtie < Rails::Railtie
|
3
3
|
initializer 'apipie.controller_additions' do
|
4
4
|
ActiveSupport.on_load :action_controller do
|
5
|
-
extend Apipie::DSL
|
5
|
+
extend Apipie::DSL::Base
|
6
|
+
extend Apipie::DSL::Common
|
7
|
+
extend Apipie::DSL::Action
|
8
|
+
extend Apipie::DSL::Param
|
6
9
|
end
|
7
10
|
end
|
8
11
|
end
|
@@ -12,13 +12,13 @@ module Apipie
|
|
12
12
|
class ResourceDescription
|
13
13
|
|
14
14
|
attr_reader :controller, :_short_description, :_full_description, :_methods, :_id,
|
15
|
-
:_path, :_name, :
|
15
|
+
:_path, :_name, :_params_args, :_errors_args, :_formats, :_parent
|
16
16
|
|
17
17
|
def initialize(controller, resource_name, dsl_data = nil, version = nil, &block)
|
18
18
|
|
19
19
|
@_methods = ActiveSupport::OrderedHash.new
|
20
|
-
@
|
21
|
-
@
|
20
|
+
@_params_args = []
|
21
|
+
@_errors_args = []
|
22
22
|
|
23
23
|
@controller = controller
|
24
24
|
@_id = resource_name
|
@@ -35,8 +35,9 @@ module Apipie
|
|
35
35
|
@_short_description = dsl_data[:short_description]
|
36
36
|
@_path = dsl_data[:path] || ""
|
37
37
|
@_formats = dsl_data[:formats]
|
38
|
-
@
|
39
|
-
@
|
38
|
+
@_errors_args = dsl_data[:errors]
|
39
|
+
@_params_args = dsl_data[:params]
|
40
|
+
|
40
41
|
if dsl_data[:app_info]
|
41
42
|
Apipie.configuration.app_info[_version] = dsl_data[:app_info]
|
42
43
|
end
|
data/lib/apipie/validator.rb
CHANGED
@@ -66,6 +66,10 @@ module Apipie
|
|
66
66
|
'string'
|
67
67
|
end
|
68
68
|
|
69
|
+
def merge_with(other_validator)
|
70
|
+
raise NotImplementedError, "Dont know how to merge #{self.inspect} with #{other_validator.inspect}"
|
71
|
+
end
|
72
|
+
|
69
73
|
end
|
70
74
|
|
71
75
|
# validate arguments type
|
@@ -169,20 +173,33 @@ module Apipie
|
|
169
173
|
end
|
170
174
|
|
171
175
|
class HashValidator < BaseValidator
|
172
|
-
|
173
|
-
|
176
|
+
include Apipie::DSL::Base
|
177
|
+
include Apipie::DSL::Param
|
174
178
|
|
175
179
|
def self.build(param_description, argument, options, block)
|
176
|
-
self.new(param_description, block) if block.is_a?(Proc) && block.arity <= 0 && argument == Hash
|
180
|
+
self.new(param_description, block, options[:param_group]) if block.is_a?(Proc) && block.arity <= 0 && argument == Hash
|
177
181
|
end
|
178
182
|
|
179
|
-
def initialize(param_description, argument)
|
183
|
+
def initialize(param_description, argument, param_group)
|
180
184
|
super(param_description)
|
181
185
|
@proc = argument
|
182
|
-
@
|
183
|
-
@hash_params = {}
|
184
|
-
|
186
|
+
@param_group = param_group
|
185
187
|
self.instance_exec(&@proc)
|
188
|
+
# specifying action_aware on Hash influences the child params,
|
189
|
+
# not the hash param itself: assuming it's required when
|
190
|
+
# updating as well
|
191
|
+
if param_description.options[:action_aware] && param_description.options[:required]
|
192
|
+
param_description.required = true
|
193
|
+
end
|
194
|
+
prepare_hash_params
|
195
|
+
end
|
196
|
+
|
197
|
+
def hash_params_ordered
|
198
|
+
@hash_params_ordered ||= _apipie_dsl_data[:params].map do |args|
|
199
|
+
options = args.find { |arg| arg.is_a? Hash }
|
200
|
+
options[:parent] = self.param_description
|
201
|
+
Apipie::ParamDescription.from_dsl_data(param_description.method_description, args)
|
202
|
+
end
|
186
203
|
end
|
187
204
|
|
188
205
|
def validate(value)
|
@@ -198,16 +215,30 @@ module Apipie
|
|
198
215
|
"Must be a Hash"
|
199
216
|
end
|
200
217
|
|
201
|
-
def param(param_name, validator, desc_or_options = nil, options = {}, &block)
|
202
|
-
param_description = Apipie::ParamDescription.new(param_name, validator, desc_or_options, options, &block)
|
203
|
-
param_description.parent = self.param_description
|
204
|
-
@hash_params_ordered << param_description
|
205
|
-
@hash_params[param_name.to_sym] = param_description
|
206
|
-
end
|
207
|
-
|
208
218
|
def expected_type
|
209
219
|
'hash'
|
210
220
|
end
|
221
|
+
|
222
|
+
# where the group definition should be looked up when no scope
|
223
|
+
# given. This is expected to return a controller.
|
224
|
+
def _default_param_group_scope
|
225
|
+
@param_group && @param_group[:scope]
|
226
|
+
end
|
227
|
+
|
228
|
+
def merge_with(other_validator)
|
229
|
+
if other_validator.is_a? HashValidator
|
230
|
+
@hash_params_ordered = ParamDescription.unify(self.hash_params_ordered + other_validator.hash_params_ordered)
|
231
|
+
prepare_hash_params
|
232
|
+
else
|
233
|
+
super
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def prepare_hash_params
|
238
|
+
@hash_params = hash_params_ordered.reduce({}) do |h, param|
|
239
|
+
h.update(param.name.to_sym => param)
|
240
|
+
end
|
241
|
+
end
|
211
242
|
end
|
212
243
|
|
213
244
|
|
data/lib/apipie/version.rb
CHANGED
@@ -110,10 +110,13 @@ describe Apipie::ApipiesController do
|
|
110
110
|
|
111
111
|
Apipie.configuration.use_cache = true
|
112
112
|
Apipie.configuration.cache_dir = cache_dir
|
113
|
+
@orig_version = Apipie.configuration.default_version
|
113
114
|
Apipie.configuration.default_version = 'v1'
|
114
115
|
end
|
115
116
|
|
116
117
|
after do
|
118
|
+
Apipie.configuration.use_cache = false
|
119
|
+
Apipie.configuration.default_version = @orig_version
|
117
120
|
# FileUtils.rm_r(cache_dir) if File.exists?(cache_dir)
|
118
121
|
end
|
119
122
|
|
@@ -20,6 +20,8 @@ end
|
|
20
20
|
|
21
21
|
describe UsersController do
|
22
22
|
|
23
|
+
let(:dsl_data) { ActionController::Base.send(:_apipie_dsl_data_init) }
|
24
|
+
|
23
25
|
describe "resource description" do
|
24
26
|
subject do
|
25
27
|
Apipie.get_resource_description(UsersController, Apipie.configuration.default_version)
|
@@ -27,10 +29,10 @@ describe UsersController do
|
|
27
29
|
|
28
30
|
it "should contain all resource methods" do
|
29
31
|
methods = subject._methods
|
30
|
-
methods.count.should == 5
|
31
32
|
methods.keys.should include(:show)
|
32
33
|
methods.keys.should include(:index)
|
33
34
|
methods.keys.should include(:create)
|
35
|
+
methods.keys.should include(:update)
|
34
36
|
methods.keys.should include(:two_urls)
|
35
37
|
end
|
36
38
|
|
@@ -44,20 +46,11 @@ describe UsersController do
|
|
44
46
|
end
|
45
47
|
|
46
48
|
it "should contain params defined on resource level" do
|
47
|
-
subject.
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
p.required.should eq(false)
|
53
|
-
p.validator.class.should eq(Apipie::Validator::IntegerValidator)
|
54
|
-
|
55
|
-
p = subject._params_ordered.second
|
56
|
-
p.should_not be(nil)
|
57
|
-
p.name.should eq(:resource_param)
|
58
|
-
p.desc.should eq("\n<p>Param description for all methods</p>\n")
|
59
|
-
p.required.should eq(false)
|
60
|
-
p.validator.class.should eq(Apipie::Validator::HashValidator)
|
49
|
+
subject._params_args.count.should == 2
|
50
|
+
name, type, options = subject._params_args.first
|
51
|
+
name.should == :id
|
52
|
+
type.should == Fixnum
|
53
|
+
options.should == {:required=>false, :desc=>"User ID"}
|
61
54
|
end
|
62
55
|
end
|
63
56
|
|
@@ -162,7 +155,7 @@ describe UsersController do
|
|
162
155
|
param.count.should == 1
|
163
156
|
param.first.validator.class.should eq(Apipie::Validator::HashValidator)
|
164
157
|
hash_params = param.first.validator.hash_params_ordered
|
165
|
-
hash_params.count.should ==
|
158
|
+
hash_params.count.should == 4
|
166
159
|
hash_params[0].name == :name
|
167
160
|
hash_params[1].name == :pass
|
168
161
|
hash_params[2].name == :membership
|
@@ -425,10 +418,10 @@ EOS2
|
|
425
418
|
end
|
426
419
|
|
427
420
|
it "skips the listed actions from the documentation" do
|
428
|
-
Apipie.define_method_description(UsersController, :ignore)
|
421
|
+
Apipie.define_method_description(UsersController, :ignore, dsl_data)
|
429
422
|
Apipie.get_method_description(UsersController, :ignore).should be_nil
|
430
423
|
|
431
|
-
Apipie.define_method_description(UsersController, :dont_ignore)
|
424
|
+
Apipie.define_method_description(UsersController, :dont_ignore, dsl_data)
|
432
425
|
Apipie.get_method_description(UsersController, :dont_ignore).should_not be_nil
|
433
426
|
end
|
434
427
|
end
|
@@ -439,9 +432,9 @@ EOS2
|
|
439
432
|
end
|
440
433
|
|
441
434
|
it "skips the listed controller from the documentation" do
|
442
|
-
Apipie.define_method_description(IgnoredController, :ignore)
|
435
|
+
Apipie.define_method_description(IgnoredController, :ignore, dsl_data)
|
443
436
|
Apipie.get_method_description(IgnoredController, :ignore).should be_nil
|
444
|
-
Apipie.define_method_description(IgnoredController, :ignore)
|
437
|
+
Apipie.define_method_description(IgnoredController, :ignore, dsl_data)
|
445
438
|
Apipie.get_method_description(IgnoredController, :ignore).should be_nil
|
446
439
|
end
|
447
440
|
end
|