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.
@@ -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, app)
20
+ def initialize(method, resource, dsl_data)
21
21
  @method = method.to_s
22
22
  @resource = resource
23
23
 
24
- @apis = app.last_dsl_data[:api_args]
25
- @see = app.last_dsl_data[:see]
26
- @formats = app.last_dsl_data[:formats]
24
+ @apis = dsl_data[:api_args].map do |method, path, desc|
25
+ MethodDescription::Api.new(method, path, desc)
26
+ end
27
27
 
28
- desc = app.last_dsl_data[:description] || ''
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
- parent = @resource.controller.superclass
37
- if parent != ActionController::Base
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
- # get params from parent resource description
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 actual resource description
59
- if @resource
60
- merge_params(all_params, resource._params_ordered)
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 = @resource._errors_ordered.find_all do |err|
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, :required, :allow_nil, :validator
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 initialize(name, validator, desc_or_options = nil, options = {}, &block)
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) && options.empty?
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
- @required = if options.has_key? :required
30
- options[:required]
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
- @allow_nil = options[:allow_nil] || false
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
@@ -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, :_params_ordered, :_errors_ordered, :_formats, :_parent
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
- @_params_ordered = []
21
- @_errors_ordered = []
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
- @_errors_ordered = dsl_data[:errors]
39
- @_params_ordered = dsl_data[:params]
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
@@ -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
- attr_reader :hash_params_ordered
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
- @hash_params_ordered = []
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
 
@@ -1,3 +1,3 @@
1
1
  module Apipie
2
- VERSION = '0.0.17'
2
+ VERSION = '0.0.18'
3
3
  end
@@ -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._params_ordered.count.should == 2
48
- p = subject._params_ordered.first
49
- p.should_not be(nil)
50
- p.name.should eq(:id)
51
- p.desc.should eq("\n<p>User ID</p>\n")
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 == 3
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