wsdsl 0.2.1 → 0.3.0
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/VERSION +1 -1
- data/lib/response.rb +35 -93
- data/lib/ws_list.rb +11 -1
- data/lib/wsdsl.rb +43 -11
- data/spec/test_services.rb +1 -1
- data/spec/wsdsl_spec.rb +72 -56
- data/wsdsl.gemspec +2 -2
- metadata +2 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/lib/response.rb
CHANGED
@@ -9,22 +9,30 @@ class WSDSL
|
|
9
9
|
# @api public
|
10
10
|
attr_reader :elements
|
11
11
|
|
12
|
+
# The list of all the arays inside the response
|
13
|
+
#
|
14
|
+
# @return [Array<WSDSL::Response::Array>]
|
15
|
+
attr_reader :arrays
|
16
|
+
|
12
17
|
def initialize
|
13
18
|
@elements = []
|
19
|
+
@arrays = []
|
14
20
|
end
|
15
21
|
|
16
|
-
|
22
|
+
def nodes
|
23
|
+
elements + arrays
|
24
|
+
end
|
17
25
|
|
18
|
-
# Shortcut to automatically create a
|
19
|
-
#
|
26
|
+
# Shortcut to automatically create a node of array type.
|
27
|
+
# Useful when describing a JSON response.
|
20
28
|
#
|
21
29
|
# @param [String, Symbol] name the name of the element.
|
22
30
|
# @param [Hash] opts the element options.
|
23
|
-
# @see
|
24
|
-
def array(name,
|
25
|
-
|
26
|
-
yield
|
27
|
-
|
31
|
+
# @see Vector#initialize
|
32
|
+
def array(name, type=nil)
|
33
|
+
vector = Vector.new(name, type)
|
34
|
+
yield(vector) if block_given?
|
35
|
+
@arrays << vector
|
28
36
|
end
|
29
37
|
|
30
38
|
# Defines a new element and yields the content of an optional block
|
@@ -170,27 +178,27 @@ class WSDSL
|
|
170
178
|
|
171
179
|
# Defines an array aka vector of elements.
|
172
180
|
#
|
173
|
-
# @param [
|
174
|
-
# @
|
175
|
-
#
|
181
|
+
# @param [String, Symbol] name The name of the array element.
|
182
|
+
# @param [String, Symbol] type Optional type information, useful to store the represented
|
183
|
+
# object types for instance.
|
176
184
|
#
|
177
185
|
# @param [Proc] &block
|
178
186
|
# A block to execute against the newly created array.
|
179
187
|
#
|
180
188
|
# @example Defining an element array called 'player_creation_rating'
|
181
|
-
# element.array
|
189
|
+
# element.array 'player_creation_rating', 'PlayerCreationRating' do |a|
|
182
190
|
# a.attribute :comments => :string
|
183
191
|
# a.attribute :player_id => :integer
|
184
192
|
# a.attribute :rating => :integer
|
185
193
|
# a.attribute :username => :string
|
186
194
|
# end
|
187
195
|
# @yield [Vector] the newly created array/vector instance
|
188
|
-
# @see
|
196
|
+
# @see Element#initialize
|
189
197
|
#
|
190
|
-
# @return [Array<WSDSL::Response::
|
198
|
+
# @return [Array<WSDSL::Response::Vector>]
|
191
199
|
# @api public
|
192
|
-
def array(
|
193
|
-
vector = Vector.new(
|
200
|
+
def array(name, type=nil)
|
201
|
+
vector = Vector.new(name, type)
|
194
202
|
yield(vector) if block_given?
|
195
203
|
@vectors << vector
|
196
204
|
end
|
@@ -198,8 +206,8 @@ class WSDSL
|
|
198
206
|
# Returns the arrays/vectors contained in the response.
|
199
207
|
# This is an alias to access @vectors
|
200
208
|
# @see @vectors
|
201
|
-
#
|
202
|
-
# @return [Array<WSDSL::Response::
|
209
|
+
#
|
210
|
+
# @return [Array<WSDSL::Response::Vector>]
|
203
211
|
# @api public
|
204
212
|
def arrays
|
205
213
|
@vectors
|
@@ -220,9 +228,9 @@ class WSDSL
|
|
220
228
|
#
|
221
229
|
# @return [Array<WSDSL::Response::Element>]
|
222
230
|
# @api public
|
223
|
-
def element(opts={}
|
231
|
+
def element(opts={})
|
224
232
|
el = Element.new(opts[:name], opts[:type])
|
225
|
-
|
233
|
+
yield(el) if block_given?
|
226
234
|
@elements ||= []
|
227
235
|
@elements << el
|
228
236
|
el
|
@@ -300,7 +308,8 @@ class WSDSL
|
|
300
308
|
if name
|
301
309
|
meta_attribute({name => type}.merge(opts))
|
302
310
|
else
|
303
|
-
|
311
|
+
# with a fallback to the @type ivar
|
312
|
+
meta_attributes.find{|att| att.type == type} || @type
|
304
313
|
end
|
305
314
|
end
|
306
315
|
|
@@ -359,79 +368,12 @@ class WSDSL
|
|
359
368
|
class MetaAttribute < Attribute
|
360
369
|
end
|
361
370
|
|
362
|
-
# Array of objects inside an element
|
363
|
-
# @api public
|
364
|
-
class Vector
|
365
|
-
|
366
|
-
# @api public
|
367
|
-
attr_reader :name
|
368
|
-
|
369
|
-
# @api public
|
370
|
-
attr_reader :obj_type
|
371
|
-
|
372
|
-
# @api public
|
373
|
-
attr_accessor :attributes
|
374
|
-
|
375
|
-
# A vector can have nested elements.
|
376
|
-
# This value is nil by default.
|
377
|
-
#
|
378
|
-
# @return [NilClass, Array<WSDSL::Response::Element>]
|
379
|
-
# @see #element
|
380
|
-
# @api public
|
381
|
-
attr_reader :elements
|
382
|
-
|
383
|
-
# Initialize a Vector object, think about it as an array of objects of a certain type.
|
384
|
-
# It is recommended to passthe type argument as a string so the constant doesn't need to be resolved.
|
385
|
-
# In other words, if you say you are creating a vector of Foo objects, the Foo class doesn't need to be
|
386
|
-
# loaded yet. That makes service parsing easier and avoids dependency challenges.
|
387
|
-
#
|
388
|
-
# @param [Hash] opts A hash representing the vector information, usually a name and a type, both as strings
|
389
|
-
# @option opts [String] :name The array's name
|
390
|
-
# @option opts [Symbol, String] :type The type of the objects inside the array
|
391
|
-
#
|
392
|
-
# @example
|
393
|
-
# Vector.new(:name => 'player_creation_rating', :type => 'PlayerCreationRating')
|
394
|
-
#
|
395
|
-
# @api public
|
396
|
-
def initialize(opts)
|
397
|
-
@name = opts[:name]
|
398
|
-
@obj_type = opts[:type]
|
399
|
-
@attributes = []
|
400
|
-
end
|
401
|
-
|
402
|
-
# Sets a vector attribute
|
403
|
-
#
|
404
|
-
# @param (see Attribute#initialize)
|
405
|
-
# @api public
|
406
|
-
def attribute(opts)
|
407
|
-
raise ArgumentError unless opts.is_a?(Hash)
|
408
|
-
@attributes << Attribute.new(opts)
|
409
|
-
end
|
410
|
-
|
411
|
-
# Defines a new element and yields the content of an optional block
|
412
|
-
# Each new element is then stored in the elements array.
|
413
|
-
#
|
414
|
-
# @param [Hash] opts Options used to define the element
|
415
|
-
# @option opts [String, Symbol] :name The element name
|
416
|
-
# @option opts [String, Symbol] :type The optional type
|
417
|
-
#
|
418
|
-
# @yield [WSDSL::Response::Element] the newly created element
|
419
|
-
# @example create an element called 'my_stats'.
|
420
|
-
# service.response do |response|
|
421
|
-
# response.element(:name => "my_stats", :type => 'Leaderboard')
|
422
|
-
# end
|
423
|
-
#
|
424
|
-
# @return [Array<WSDSL::Response::Element>]
|
425
|
-
# @api public
|
426
|
-
def element(opts={})
|
427
|
-
el = Element.new(opts[:name], opts[:type])
|
428
|
-
yield(el) if block_given?
|
429
|
-
@elements ||= []
|
430
|
-
@elements << el
|
431
|
-
end
|
432
|
-
|
433
|
-
end # of Vector
|
434
371
|
end # of Element
|
435
372
|
|
373
|
+
# Array of objects
|
374
|
+
# @api public
|
375
|
+
class Vector < Element
|
376
|
+
end # of Vector
|
377
|
+
|
436
378
|
end # of Response
|
437
379
|
end
|
data/lib/ws_list.rb
CHANGED
@@ -34,7 +34,7 @@ module WSList
|
|
34
34
|
# @return [WSDSL] The found service.
|
35
35
|
#
|
36
36
|
# @api public
|
37
|
-
def
|
37
|
+
def named(name)
|
38
38
|
service = all.find{|service| service.name == name}
|
39
39
|
if service.nil?
|
40
40
|
raise UnknownService, "Service named #{name} isn't available"
|
@@ -42,6 +42,16 @@ module WSList
|
|
42
42
|
service
|
43
43
|
end
|
44
44
|
end
|
45
|
+
|
46
|
+
# Returns a service based on its url
|
47
|
+
#
|
48
|
+
# @param [String] url The url of the service you are looking for.
|
49
|
+
# @return [Nil, WSDSL] The found service.
|
50
|
+
#
|
51
|
+
# @api public
|
52
|
+
def [](url)
|
53
|
+
@list.find{|service| service.url == url}
|
54
|
+
end
|
45
55
|
|
46
56
|
|
47
57
|
end
|
data/lib/wsdsl.rb
CHANGED
@@ -25,9 +25,11 @@ require File.expand_path('ws_list', File.dirname(__FILE__))
|
|
25
25
|
# | |_ Namespaced params (array containing nested optional and required rules)
|
26
26
|
# |__ response (instance of WSDSL::Response)
|
27
27
|
# | |_ elements (array of elements with each element having a name, type, attributes and vectors
|
28
|
-
# |
|
29
|
-
# |
|
30
|
-
# |
|
28
|
+
# | | | |_ attributes (array of WSDSL::Response::Attribute, each attribute has a name, a type, a doc and some extra options)
|
29
|
+
# | | |_ vectors (array of WSDSL::Response::Vector), each vector has a name, obj_type, & an array of attributes
|
30
|
+
# | | |_ attributes (array of WSDSL::Response::Attribute, each attribute has a name, a type and a doc)
|
31
|
+
# | |_ arrays (like elements but represent an array of objects)
|
32
|
+
# |
|
31
33
|
# |__ doc (instance of WSDSL::Documentation)
|
32
34
|
# | | | |_ overal) description
|
33
35
|
# | | |_ examples (array of examples as strings)
|
@@ -123,14 +125,16 @@ class WSDSL
|
|
123
125
|
@defined_params = WSDSL::Params.new
|
124
126
|
@doc = WSDSL::Documentation.new
|
125
127
|
@response = WSDSL::Response.new
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
128
|
+
if WSDSL.use_controller_dispatch
|
129
|
+
@name = extract_service_root_name(url)
|
130
|
+
if WSDSL.use_pluralized_controllers
|
131
|
+
base_name = ExtlibCopy::Inflection.pluralize(ExtlibCopy::Inflection.singular(name))
|
132
|
+
@controller_name = "#{ExtlibCopy.classify(base_name)}Controller"
|
133
|
+
else
|
134
|
+
@controller_name = "#{ExtlibCopy.classify(name)}Controller"
|
135
|
+
end
|
136
|
+
@action = extract_service_action(url)
|
132
137
|
end
|
133
|
-
@action = extract_service_action(url)
|
134
138
|
@verb = :get
|
135
139
|
@formats = []
|
136
140
|
@version = '0.1'
|
@@ -159,6 +163,27 @@ class WSDSL
|
|
159
163
|
@pluralized_controllers = val
|
160
164
|
end
|
161
165
|
|
166
|
+
# Checks the WSDSL flag to see if controller are used to dispatch requests.
|
167
|
+
# This allows apps to use this DSL but route to controller/actions.
|
168
|
+
#
|
169
|
+
# @return [Boolean] The updated value, default to false
|
170
|
+
# @api public
|
171
|
+
# @since 0.3.0
|
172
|
+
def self.use_controller_dispatch
|
173
|
+
@controller_dispatch
|
174
|
+
end
|
175
|
+
|
176
|
+
# Sets a WSDSL global flag so the controller settings can be generated
|
177
|
+
# Setting this flag will automatically set the controller/action names.
|
178
|
+
# @param [Boolean] True if the controllers are pluralized, False otherwise.
|
179
|
+
#
|
180
|
+
# @return [Boolean] The updated value
|
181
|
+
# @api public
|
182
|
+
# @since 0.1.1
|
183
|
+
def self.use_controller_dispatch=(val)
|
184
|
+
@controller_dispatch = val
|
185
|
+
end
|
186
|
+
|
162
187
|
# Offers a way to dispatch the service at runtime
|
163
188
|
# Basically, it dispatches the request to the defined controller/action
|
164
189
|
# The full request cycle looks like that:
|
@@ -196,7 +221,14 @@ class WSDSL
|
|
196
221
|
end
|
197
222
|
end
|
198
223
|
alias :param :params
|
199
|
-
|
224
|
+
|
225
|
+
# Returns true if the DSL defined any params
|
226
|
+
#
|
227
|
+
# @return [Boolean]
|
228
|
+
def params?
|
229
|
+
!(required_rules.empty? && optional_rules.empty? && nested_params.empty?)
|
230
|
+
end
|
231
|
+
|
200
232
|
# Returns an array of required param rules
|
201
233
|
#
|
202
234
|
# @return [Array<WSDSL::Params::Rule>] Only the required param rules
|
data/spec/test_services.rb
CHANGED
@@ -32,7 +32,7 @@ describe_service "services/test.xml" do |service|
|
|
32
32
|
e.attribute :is_accepted => :boolean, :doc => "is accepted doc"
|
33
33
|
e.attribute :name => :string, :doc => "name doc"
|
34
34
|
|
35
|
-
e.array :
|
35
|
+
e.array :player_creation_rating, 'PlayerCreationRating' do |a|
|
36
36
|
a.attribute :comments => :string, :doc => "comments doc"
|
37
37
|
a.attribute :player_id => :integer, :doc => "player_id doc"
|
38
38
|
a.attribute :rating => :integer, :doc => "rating doc"
|
data/spec/wsdsl_spec.rb
CHANGED
@@ -35,68 +35,84 @@ describe WSDSL do
|
|
35
35
|
it "should have direct access to the nested params" do
|
36
36
|
@service.nested_params.should == @service.params.namespaced_params
|
37
37
|
end
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
it "should support restful routes based on the HTTP verb" do
|
54
|
-
service = WSList.all.find{|s| s.url == "services.xml"}
|
55
|
-
service.should_not be_nil
|
56
|
-
service.http_verb.should == :put
|
57
|
-
service.action.should_not be_nil
|
58
|
-
service.controller_name.should == 'ServicesController'
|
59
|
-
service.action.should == 'update'
|
60
|
-
end
|
38
|
+
|
39
|
+
describe "With controller dispatch on" do
|
40
|
+
before :all do
|
41
|
+
@original_services = WSList.all.dup
|
42
|
+
WSList.all.clear
|
43
|
+
WSDSL.use_controller_dispatch = true
|
44
|
+
load File.expand_path('test_services.rb', File.dirname(__FILE__))
|
45
|
+
@c_service = WSList.all.find{|s| s.url == 'services/test.xml'}
|
46
|
+
@c_service.should_not be_nil
|
47
|
+
end
|
48
|
+
after :all do
|
49
|
+
WSDSL.use_controller_dispatch = false
|
50
|
+
WSList.all.replace @original_services
|
51
|
+
end
|
61
52
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
53
|
+
it "should set the controller accordingly" do
|
54
|
+
@c_service.controller_name.should_not be_nil
|
55
|
+
@c_service.controller_name.should == 'ServicesController'
|
56
|
+
service = WSDSL.new("preferences.xml")
|
57
|
+
service.name.should == 'preferences'
|
58
|
+
ExtlibCopy.classify('preferences').should == 'Preferences'
|
59
|
+
service.controller_name.should == 'PreferencesController'
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should set the action accordingly" do
|
63
|
+
@c_service.action.should_not be_nil
|
64
|
+
@c_service.action.should == 'test'
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should support restful routes based on the HTTP verb" do
|
68
|
+
service = WSList.all.find{|s| s.url == "services.xml"}
|
69
|
+
service.should_not be_nil
|
70
|
+
service.http_verb.should == :put
|
71
|
+
service.action.should_not be_nil
|
72
|
+
service.controller_name.should == 'ServicesController'
|
73
|
+
service.action.should == 'update'
|
74
|
+
end
|
66
75
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
76
|
+
it "should have a default action" do
|
77
|
+
service = WSDSL.new('spec_test.xml')
|
78
|
+
service.action.should == 'list'
|
79
|
+
end
|
71
80
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
end
|
81
|
+
it "should route to show when an id is the last passed param" do
|
82
|
+
service = WSDSL.new("players/:id.xml")
|
83
|
+
service.action.should == 'show'
|
84
|
+
end
|
77
85
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
86
|
+
it "should support some extra attributes" do
|
87
|
+
service = WSDSL.new("players/:id.xml")
|
88
|
+
service.extra[:custom_name] = 'fooBar'
|
89
|
+
service.extra[:custom_name].should == 'fooBar'
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should respect the global controller pluralization flag" do
|
93
|
+
WSDSL.use_pluralized_controllers = true
|
94
|
+
service = WSDSL.new("player/:id.xml")
|
95
|
+
service.controller_name.should == "PlayersController"
|
96
|
+
service = WSDSL.new("players/:id.xml")
|
97
|
+
service.controller_name.should == "PlayersController"
|
98
|
+
WSDSL.use_pluralized_controllers = false
|
99
|
+
service = WSDSL.new("player/:id.xml")
|
100
|
+
service.controller_name.should == "PlayerController"
|
101
|
+
end
|
88
102
|
|
89
103
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
104
|
+
it "should let overwrite the controller name and action after initialization" do
|
105
|
+
describe_service "players/:id.xml" do |service|
|
106
|
+
service.controller_name = "CustomController"
|
107
|
+
service.action = "foo"
|
108
|
+
end
|
109
|
+
service = WSList.all.find{|s| s.url == "players/:id.xml"}
|
110
|
+
service.controller_name.should == "CustomController"
|
111
|
+
service.action.should == "foo"
|
112
|
+
end
|
98
113
|
end
|
99
114
|
|
115
|
+
|
100
116
|
describe WSDSL::Params do
|
101
117
|
|
102
118
|
before(:all) do
|
@@ -203,8 +219,8 @@ The most common way to use this service looks like that:
|
|
203
219
|
it "should have documentation for a response element array" do
|
204
220
|
element = @service.response.elements.first
|
205
221
|
element.arrays.should_not be_empty
|
206
|
-
element.arrays.first.name.should ==
|
207
|
-
element.arrays.first.
|
222
|
+
element.arrays.first.name.should == :player_creation_rating
|
223
|
+
element.arrays.first.type.should == "PlayerCreationRating"
|
208
224
|
element.arrays.first.attributes.should_not be_empty
|
209
225
|
end
|
210
226
|
|
data/wsdsl.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{wsdsl}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = [%q{Matt Aimonetti}]
|
12
|
-
s.date = %q{2011-09-
|
12
|
+
s.date = %q{2011-09-09}
|
13
13
|
s.description = %q{A Ruby DSL describing Web Services without implementation details.}
|
14
14
|
s.email = %q{mattaimonetti@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wsdsl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-09-
|
12
|
+
date: 2011-09-09 00:00:00.000000000Z
|
13
13
|
dependencies: []
|
14
14
|
description: A Ruby DSL describing Web Services without implementation details.
|
15
15
|
email: mattaimonetti@gmail.com
|