wsdsl 0.2.0 → 0.2.1

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Web Service DSL
2
2
 
3
- WSDSL is a simple DSL allowind developers to simply describe and
3
+ WSDSL is a simple DSL allowing developers to simply describe and
4
4
  document their web APIS. For instance:
5
5
 
6
6
 
@@ -87,6 +87,57 @@ Or a more complex example:
87
87
  end
88
88
 
89
89
 
90
+ ## JSON APIs
91
+
92
+ This library was designed with XML responses in mind and JSON support
93
+ was added later on which explains why some response methods are aliases.
94
+ Consider the following JSON response:
95
+
96
+ { people: [
97
+ {
98
+ id : 1,
99
+ online : false,
100
+ created_at : 123123123123,
101
+ team : {
102
+ id : 1231,
103
+ score : 123.32
104
+ }
105
+ },
106
+ {
107
+ id : 2,
108
+ online : true,
109
+ created_at : 123123123123,
110
+ team: {
111
+ id : 1233,
112
+ score : 1.32
113
+ }
114
+ },
115
+ ] }
116
+
117
+ It would be described as follows:
118
+
119
+ describe_service "json_list" do |service|
120
+ service.formats :json
121
+ service.response do |response|
122
+ response.array :people do |node|
123
+ node.integer :id
124
+ node.boolean :online
125
+ node.datetime :created_at
126
+ node.object :team do |team|
127
+ team.integer :id
128
+ team.float :score
129
+ end
130
+ end
131
+ end
132
+ end
133
+
134
+ Nodes/elements can also use some meta attributes. Currently the
135
+ following meta attributes are available:
136
+
137
+ * key (refers to an attribute name that is key to this object)
138
+ * type (refers to the type of object described, valuable when using JSON
139
+ cross OO based apps.
140
+
90
141
  ## Test suite
91
142
 
92
143
  This library comes with a test suite requiring Ruby 1.9.2
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.2.1
data/lib/response.rb CHANGED
@@ -13,6 +13,20 @@ class WSDSL
13
13
  @elements = []
14
14
  end
15
15
 
16
+ alias :nodes :elements
17
+
18
+ # Shortcut to automatically create a typed node.
19
+ # Very useful when describing a JSON response.
20
+ #
21
+ # @param [String, Symbol] name the name of the element.
22
+ # @param [Hash] opts the element options.
23
+ # @see Element#array
24
+ def array(name, opts={})
25
+ el = element(opts.merge(:name => name))
26
+ yield el if block_given?
27
+ el
28
+ end
29
+
16
30
  # Defines a new element and yields the content of an optional block
17
31
  # Each new element is then stored in the elements array.
18
32
  #
@@ -32,6 +46,7 @@ class WSDSL
32
46
  el = Element.new(opts[:name], opts[:type])
33
47
  yield(el) if block_given?
34
48
  @elements << el
49
+ el
35
50
  end
36
51
 
37
52
  # Returns a response element object based on its name
@@ -57,10 +72,17 @@ class WSDSL
57
72
  # @api public
58
73
  attr_reader :type
59
74
 
75
+ # The optional lookup key of an object
76
+ attr_reader :key
77
+
60
78
  # @return [Array<WSDSL::Response::Element::Attribute>] An array of attributes
61
79
  # @api public
62
80
  attr_reader :attributes
63
81
 
82
+ # @return [Array<WSDSL::Response::Element::MetaAttribute>] An array of meta attributes
83
+ # @api public
84
+ attr_reader :meta_attributes
85
+
64
86
  # @return [Array] An array of vectors/arrays
65
87
  # @api public
66
88
  attr_reader :vectors
@@ -72,6 +94,12 @@ class WSDSL
72
94
  # @return [NilClass, Array<WSDSL::Response::Element>] The optional nested elements
73
95
  attr_reader :elements
74
96
 
97
+ # Alias to use a JSON/JS jargon instead of XML.
98
+ alias :properties :attributes
99
+
100
+ # Alias to use a JSON/JS jargon instead of XML.
101
+ alias :objects :elements
102
+
75
103
  # param [String, Symbol] name The name of the element
76
104
  # param [String, Symbol] type The optional type of the element
77
105
  # @api public
@@ -82,7 +110,9 @@ class WSDSL
82
110
  @name = name
83
111
  @type = type
84
112
  @attributes = []
113
+ @meta_attributes = []
85
114
  @vectors = []
115
+ @key = nil
86
116
  # we don't need to initialize the nested elements, by default they should be nil
87
117
  end
88
118
 
@@ -115,6 +145,29 @@ class WSDSL
115
145
  @attributes
116
146
  end
117
147
 
148
+ # sets a new meta attribute and returns the entire list of meta attributes
149
+ #
150
+ # @param [Hash] opts An element's attribute options
151
+ # @option opts [String, Symbol] attribute_name The name of the attribute, the value being the type
152
+ # @option opts [String, Symbol] :mock An optional mock value used by service related tools
153
+ #
154
+ # @example Creation of a response attribute called 'best_lap_time'
155
+ # service.response do |response|
156
+ # response.element(:name => "my_stats", :type => 'Leaderboard') do |e|
157
+ # e.meta_attribute "id" => :key
158
+ # end
159
+ # end
160
+ #
161
+ # @return [Array<WSDSL::Response::MetaAttribute>]
162
+ # @api public
163
+ def meta_attribute(opts)
164
+ raise ArgumentError unless opts.is_a?(Hash)
165
+ # extract the documentation part and add it where it belongs
166
+ new_attribute = MetaAttribute.new(opts)
167
+ @meta_attributes << new_attribute
168
+ @meta_attributes
169
+ end
170
+
118
171
  # Defines an array aka vector of elements.
119
172
  #
120
173
  # @param [Hash] opts A hash representing the array information, usually a name and a type.
@@ -167,11 +220,88 @@ class WSDSL
167
220
  #
168
221
  # @return [Array<WSDSL::Response::Element>]
169
222
  # @api public
170
- def element(opts={})
223
+ def element(opts={}, &block)
171
224
  el = Element.new(opts[:name], opts[:type])
172
- yield(el) if block_given?
225
+ block.call(el) if block_given?
173
226
  @elements ||= []
174
227
  @elements << el
228
+ el
229
+ end
230
+
231
+ # Shortcut to create a new element.
232
+ #
233
+ # @param [Symbol, String] name the name of the element.
234
+ # @param [Hash] opts the options for the newly created element.
235
+ def object(name, opts={}, &block)
236
+ element(opts.merge(:name => name), &block)
237
+ end
238
+
239
+ # Getter/setter for the key meta attribute.
240
+ # A key name can be used to lookup an object by a primary key for instance.
241
+ #
242
+ # @param [Symbol, String] name the name of the key attribute.
243
+ # @param [Hash] opts the options attached with the key.
244
+ def key(name=nil, opts={})
245
+ meta_attribute_getter_setter(:key, name, opts)
246
+ end
247
+
248
+ # Getter/setter for the type meta attribute.
249
+ #
250
+ # @param [Symbol, String] name the name of the type attribute.
251
+ # @param [Hash] opts the options attached with the key.
252
+ def type(name=nil, opts={})
253
+ meta_attribute_getter_setter(:type, name, opts)
254
+ end
255
+
256
+ # Shortcut to create a string attribute
257
+ #
258
+ # @param [Symbol, String] name the name of the attribute.
259
+ # @param [Hash] opts the attribute options.
260
+ def string(name=nil, opts={})
261
+ attribute(opts.merge(:name => name, :type => :string))
262
+ end
263
+
264
+ # Shortcut to create a string attribute
265
+ #
266
+ # @param [Symbol, String] name the name of the attribute.
267
+ # @param [Hash] opts the attribute options.
268
+ def integer(name=nil, opts={})
269
+ attribute({name => :integer}.merge(opts))
270
+ end
271
+
272
+ # Shortcut to create a string attribute
273
+ #
274
+ # @param [Symbol, String] name the name of the attribute.
275
+ # @param [Hash] opts the attribute options.
276
+ def float(name=nil, opts={})
277
+ attribute({name => :float}.merge(opts))
278
+ end
279
+
280
+ # Shortcut to create a string attribute
281
+ #
282
+ # @param [Symbol, String] name the name of the attribute.
283
+ # @param [Hash] opts the attribute options.
284
+ def boolean(name=nil, opts={})
285
+ attribute({name => :boolean}.merge(opts))
286
+ end
287
+
288
+ # Shortcut to create a string attribute
289
+ #
290
+ # @param [Symbol, String] name the name of the attribute.
291
+ # @param [Hash] opts the attribute options.
292
+ def datetime(name=nil, opts={})
293
+ attribute({name => :datetime}.merge(opts))
294
+ end
295
+
296
+ private
297
+
298
+ # Create a meta element attribute
299
+ def meta_attribute_getter_setter(type, name, opts)
300
+ if name
301
+ meta_attribute({name => type}.merge(opts))
302
+ else
303
+ meta_attributes.find{|att| att.type == type}
304
+ end
175
305
  end
176
306
 
177
307
  # Response element's attribute class
@@ -181,6 +311,7 @@ class WSDSL
181
311
  # @return [String, #to_s] The attribute's name.
182
312
  # @api public
183
313
  attr_reader :name
314
+ alias :value :name
184
315
 
185
316
  # @return [Symbol, String, #to_s] The attribute's type such as boolean, string etc..
186
317
  # @api public
@@ -223,6 +354,11 @@ class WSDSL
223
354
  end
224
355
  end
225
356
 
357
+ # Response's meta attribute meant to set some extra
358
+ # attributes which are not part of the response per se.
359
+ class MetaAttribute < Attribute
360
+ end
361
+
226
362
  # Array of objects inside an element
227
363
  # @api public
228
364
  class Vector
data/lib/wsdsl.rb CHANGED
@@ -354,6 +354,7 @@ module Kernel
354
354
  service = WSDSL.new(url)
355
355
  yield service
356
356
  WSList.add(service)
357
+ service
357
358
  end
358
359
 
359
360
  end
@@ -0,0 +1,92 @@
1
+ require File.expand_path("spec_helper", File.dirname(__FILE__))
2
+
3
+ describe "WSDSL JSON response description" do
4
+
5
+ # JSON response example
6
+ =begin
7
+ { vouchers: [
8
+ {
9
+ id : 1,
10
+ redeemed : false,
11
+ created_at : 123123123123,
12
+ option: {
13
+ id : 1231,
14
+ price: 123.32
15
+ }
16
+ },
17
+ {
18
+ id : 2,
19
+ redeemed : true,
20
+ created_at : 123123123123,
21
+ option: {
22
+ id : 1233,
23
+ price: 1.32
24
+ }
25
+ },
26
+ ] }
27
+ =end
28
+
29
+ before :all do
30
+ @service = describe_service "json_list" do |service|
31
+ service.formats :json
32
+ service.response do |response|
33
+ response.array :vouchers do |node|
34
+ node.key :id
35
+ node.type :Voucher
36
+ node.integer :id, :doc => "Identifier"
37
+ node.boolean :redeemed
38
+ node.datetime :created_at
39
+ node.object :option do |option|
40
+ option.integer :id
41
+ option.integer :deal_id, :mock => 1
42
+ option.float :price
43
+ end
44
+ end
45
+ end
46
+ end
47
+ @response = @service.response
48
+ @root_node = @response.nodes.find{|n| n.name == :vouchers}
49
+
50
+ end
51
+
52
+ it "should handle the json root node" do
53
+ @root_node.should_not be_nil
54
+ end
55
+
56
+ it "should handle a node property list" do
57
+ props = @root_node.properties
58
+ props.should_not be_empty
59
+ {:id => :integer, :redeemed => :boolean, :created_at => :datetime}.each do |key, type|
60
+ prop = props.find{|prop| prop.name == key}
61
+ prop.should_not be_nil
62
+ prop.type.should == type
63
+ end
64
+ end
65
+
66
+ it "should handle a nested object with properties" do
67
+ @root_node.objects.should_not be_nil
68
+ option = @root_node.objects.find{|o| o.name == :option}
69
+ option.should_not be_nil
70
+ {:id => :integer, :deal_id => :integer, :price => :float}.each do |key, type|
71
+ prop = option.properties.find{|prop| prop.name == key}
72
+ if prop.nil?
73
+ puts option.properties.inspect
74
+ puts [key, type].inspect
75
+ end
76
+ prop.should_not be_nil
77
+ prop.type.should == type
78
+ end
79
+ end
80
+
81
+ it "should allow some meta attributes" do
82
+ atts = @root_node.meta_attributes
83
+ atts.should_not be_nil
84
+ {:key => :id, :type => :Voucher}.each do |type, value|
85
+ meta = atts.find{|att| att.type == type}
86
+ puts [type, atts].inspect if meta.nil?
87
+ meta.should_not be_nil
88
+ meta.value.should == value
89
+ end
90
+ end
91
+
92
+ end
data/spec/wsdsl_spec.rb CHANGED
@@ -60,8 +60,8 @@ describe WSDSL do
60
60
  end
61
61
 
62
62
  it "should have a default action" do
63
- service = WSDSL.new('spec_test.xml')
64
- service.action.should == 'list'
63
+ service = WSDSL.new('spec_test.xml')
64
+ service.action.should == 'list'
65
65
  end
66
66
 
67
67
  it "should route to show when an id is the last passed param" do
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.2.0"
8
+ s.version = "0.2.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Matt Aimonetti"]
12
- s.date = %q{2011-05-19}
11
+ s.authors = [%q{Matt Aimonetti}]
12
+ s.date = %q{2011-09-02}
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 = [
@@ -32,6 +32,7 @@ Gem::Specification.new do |s|
32
32
  "lib/wsdsl.rb",
33
33
  "spec/hello_world_controller.rb",
34
34
  "spec/hello_world_service.rb",
35
+ "spec/json_response_description_spec.rb",
35
36
  "spec/params_verification_spec.rb",
36
37
  "spec/preferences_service.rb",
37
38
  "spec/spec_helper.rb",
@@ -41,20 +42,10 @@ Gem::Specification.new do |s|
41
42
  "wsdsl.gemspec"
42
43
  ]
43
44
  s.homepage = %q{http://github.com/mattetti/wsdsl}
44
- s.licenses = ["MIT"]
45
- s.require_paths = ["lib"]
46
- s.rubygems_version = %q{1.7.2}
45
+ s.licenses = [%q{MIT}]
46
+ s.require_paths = [%q{lib}]
47
+ s.rubygems_version = %q{1.8.6}
47
48
  s.summary = %q{Web Service DSL}
48
- s.test_files = [
49
- "spec/hello_world_controller.rb",
50
- "spec/hello_world_service.rb",
51
- "spec/params_verification_spec.rb",
52
- "spec/preferences_service.rb",
53
- "spec/spec_helper.rb",
54
- "spec/test_services.rb",
55
- "spec/wsdsl_sinatra_ext_spec.rb",
56
- "spec/wsdsl_spec.rb"
57
- ]
58
49
 
59
50
  if s.respond_to? :specification_version then
60
51
  s.specification_version = 3
metadata CHANGED
@@ -1,28 +1,24 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: wsdsl
3
- version: !ruby/object:Gem::Version
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
4
5
  prerelease:
5
- version: 0.2.0
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Matt Aimonetti
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
-
13
- date: 2011-05-19 00:00:00 Z
12
+ date: 2011-09-02 00:00:00.000000000Z
14
13
  dependencies: []
15
-
16
14
  description: A Ruby DSL describing Web Services without implementation details.
17
15
  email: mattaimonetti@gmail.com
18
16
  executables: []
19
-
20
17
  extensions: []
21
-
22
- extra_rdoc_files:
18
+ extra_rdoc_files:
23
19
  - LICENSE
24
20
  - README.md
25
- files:
21
+ files:
26
22
  - LICENSE
27
23
  - README.md
28
24
  - Rakefile
@@ -38,6 +34,7 @@ files:
38
34
  - lib/wsdsl.rb
39
35
  - spec/hello_world_controller.rb
40
36
  - spec/hello_world_service.rb
37
+ - spec/json_response_description_spec.rb
41
38
  - spec/params_verification_spec.rb
42
39
  - spec/preferences_service.rb
43
40
  - spec/spec_helper.rb
@@ -46,38 +43,28 @@ files:
46
43
  - spec/wsdsl_spec.rb
47
44
  - wsdsl.gemspec
48
45
  homepage: http://github.com/mattetti/wsdsl
49
- licenses:
46
+ licenses:
50
47
  - MIT
51
48
  post_install_message:
52
49
  rdoc_options: []
53
-
54
- require_paths:
50
+ require_paths:
55
51
  - lib
56
- required_ruby_version: !ruby/object:Gem::Requirement
52
+ required_ruby_version: !ruby/object:Gem::Requirement
57
53
  none: false
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: "0"
62
- required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
59
  none: false
64
- requirements:
65
- - - ">="
66
- - !ruby/object:Gem::Version
67
- version: "0"
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
68
64
  requirements: []
69
-
70
65
  rubyforge_project:
71
- rubygems_version: 1.7.2
66
+ rubygems_version: 1.8.6
72
67
  signing_key:
73
68
  specification_version: 3
74
69
  summary: Web Service DSL
75
- test_files:
76
- - spec/hello_world_controller.rb
77
- - spec/hello_world_service.rb
78
- - spec/params_verification_spec.rb
79
- - spec/preferences_service.rb
80
- - spec/spec_helper.rb
81
- - spec/test_services.rb
82
- - spec/wsdsl_sinatra_ext_spec.rb
83
- - spec/wsdsl_spec.rb
70
+ test_files: []