mws-connect 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +19 -0
- data/.sublime-project +19 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +111 -0
- data/Rakefile +1 -0
- data/lib/mws.rb +34 -0
- data/lib/mws/apis.rb +6 -0
- data/lib/mws/apis/feeds.rb +20 -0
- data/lib/mws/apis/feeds/api.rb +103 -0
- data/lib/mws/apis/feeds/distance.rb +23 -0
- data/lib/mws/apis/feeds/feed.rb +114 -0
- data/lib/mws/apis/feeds/image_listing.rb +44 -0
- data/lib/mws/apis/feeds/inventory.rb +77 -0
- data/lib/mws/apis/feeds/measurement.rb +32 -0
- data/lib/mws/apis/feeds/money.rb +31 -0
- data/lib/mws/apis/feeds/price_listing.rb +48 -0
- data/lib/mws/apis/feeds/product.rb +173 -0
- data/lib/mws/apis/feeds/sale_price.rb +31 -0
- data/lib/mws/apis/feeds/shipping.rb +160 -0
- data/lib/mws/apis/feeds/submission_info.rb +45 -0
- data/lib/mws/apis/feeds/submission_result.rb +87 -0
- data/lib/mws/apis/feeds/transaction.rb +37 -0
- data/lib/mws/apis/feeds/weight.rb +19 -0
- data/lib/mws/apis/orders.rb +23 -0
- data/lib/mws/connection.rb +84 -0
- data/lib/mws/enum.rb +81 -0
- data/lib/mws/errors.rb +32 -0
- data/lib/mws/query.rb +45 -0
- data/lib/mws/serializer.rb +81 -0
- data/lib/mws/signer.rb +20 -0
- data/lib/mws/utils.rb +50 -0
- data/mws.gemspec +25 -0
- data/scripts/catalog-workflow +136 -0
- data/spec/mws/apis/feeds/api_spec.rb +229 -0
- data/spec/mws/apis/feeds/distance_spec.rb +43 -0
- data/spec/mws/apis/feeds/feed_spec.rb +92 -0
- data/spec/mws/apis/feeds/image_listing_spec.rb +109 -0
- data/spec/mws/apis/feeds/inventory_spec.rb +135 -0
- data/spec/mws/apis/feeds/measurement_spec.rb +84 -0
- data/spec/mws/apis/feeds/money_spec.rb +43 -0
- data/spec/mws/apis/feeds/price_listing_spec.rb +90 -0
- data/spec/mws/apis/feeds/product_spec.rb +264 -0
- data/spec/mws/apis/feeds/shipping_spec.rb +78 -0
- data/spec/mws/apis/feeds/submission_info_spec.rb +111 -0
- data/spec/mws/apis/feeds/submission_result_spec.rb +157 -0
- data/spec/mws/apis/feeds/transaction_spec.rb +64 -0
- data/spec/mws/apis/feeds/weight_spec.rb +43 -0
- data/spec/mws/apis/orders_spec.rb +9 -0
- data/spec/mws/connection_spec.rb +331 -0
- data/spec/mws/enum_spec.rb +166 -0
- data/spec/mws/query_spec.rb +104 -0
- data/spec/mws/serializer_spec.rb +187 -0
- data/spec/mws/signer_spec.rb +67 -0
- data/spec/mws/utils_spec.rb +147 -0
- data/spec/spec_helper.rb +10 -0
- metadata +220 -0
data/.gitignore
ADDED
data/.sublime-project
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
{
|
2
|
+
"folders": [
|
3
|
+
{
|
4
|
+
"path": ".",
|
5
|
+
"folder_exclude_patterns": [
|
6
|
+
"pkg",
|
7
|
+
"coverage"
|
8
|
+
],
|
9
|
+
"file_exclude_patterns": [
|
10
|
+
"*.sublime-project*",
|
11
|
+
".gitignore"
|
12
|
+
]
|
13
|
+
}
|
14
|
+
],
|
15
|
+
"settings": {
|
16
|
+
"tab_size": 2,
|
17
|
+
"translate_tabs_to_spaces": true
|
18
|
+
}
|
19
|
+
}
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Sean M. Duncan
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
# Mws
|
2
|
+
|
3
|
+
The goal of this gem is to facilities interactions with the Amazon Marketplace Web Services from Ruby clients.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'mws'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install mws
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Create Mws connection:
|
22
|
+
|
23
|
+
require 'mws'
|
24
|
+
|
25
|
+
mws = Mws.connect(
|
26
|
+
merchant: 'XXXXXXXXXXXXXX',
|
27
|
+
access: 'XXXXXXXXXXXXXXXXXXXXX',
|
28
|
+
secret: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
|
29
|
+
)
|
30
|
+
|
31
|
+
Access the Feeds Api:
|
32
|
+
|
33
|
+
feeds_api = mws.feeds
|
34
|
+
|
35
|
+
Access the Feeds Api wrappers:
|
36
|
+
|
37
|
+
products_api = mws.feeds.products
|
38
|
+
prices_api = mws.feeds.prices
|
39
|
+
images_api = mws.feeds.images
|
40
|
+
inventory_api = mws.feeds.inventory
|
41
|
+
|
42
|
+
Example: Add product details:
|
43
|
+
|
44
|
+
sku = '12345678'
|
45
|
+
product = Mws::Product sku {
|
46
|
+
upc '123435566654'
|
47
|
+
tax_code 'GEN_TAX_CODE'
|
48
|
+
name 'Some Product'
|
49
|
+
brand 'Some Brand'
|
50
|
+
msrp 19.99, 'USD'
|
51
|
+
manufacturer 'Some Manufacturer'
|
52
|
+
category :ce
|
53
|
+
details {
|
54
|
+
cable_or_adapter {
|
55
|
+
cable_length as_distance 5, :feet
|
56
|
+
}
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
submission_id = mws.feeds.products.add(product)
|
61
|
+
|
62
|
+
Example: Adding product images:
|
63
|
+
|
64
|
+
image_submission_id = mws.feeds.images.add(
|
65
|
+
Mws::ImageListing(sku, 'http://url.to.product.iamges/main.jpg', 'Main'),
|
66
|
+
Mws::ImageListing(sku, 'http://url.to.product.iamges/pt1.jpg', 'PT1')
|
67
|
+
)
|
68
|
+
|
69
|
+
Example: Setting product pricing:
|
70
|
+
|
71
|
+
price_submission_id = mws.feeds.prices.add(
|
72
|
+
Mws::PriceListing(sku, 14.99).on_sale(12.99, Time.now, 3.months.from_now)
|
73
|
+
)
|
74
|
+
|
75
|
+
Example: Overriding product shipping:
|
76
|
+
|
77
|
+
sku = '12345678'
|
78
|
+
shipping_submission_id = mws.feeds.shipping.add(
|
79
|
+
Mws::Shipping sku {
|
80
|
+
replace 'UPS Ground', 4.99
|
81
|
+
adjust '2nd-Day Air', 7.00
|
82
|
+
}
|
83
|
+
)
|
84
|
+
|
85
|
+
Example: Setting product inventory:
|
86
|
+
|
87
|
+
inventory_submission_id = mws.feeds.inventory.add(
|
88
|
+
Mws::Inventory(sku, quantity: 10, fulfillment_type: :mfn)
|
89
|
+
)
|
90
|
+
|
91
|
+
Example: Check the processing status of a feed:
|
92
|
+
|
93
|
+
mws.feeds.list(id: submission_id).each do | info |
|
94
|
+
puts "SubmissionId: #{info.id} Status: #{info.status}"
|
95
|
+
puts "Complete!" if [:cancelled, :done].include? info.status
|
96
|
+
end
|
97
|
+
|
98
|
+
Example: Get the results for a submission:
|
99
|
+
|
100
|
+
result = mws.feeds.get(submission_id)
|
101
|
+
puts "Submission: #{result.transaction_id} - #{result.status}"
|
102
|
+
|
103
|
+
_For an example of putting it all together check out the 'scripts/catalog-workflow'_
|
104
|
+
|
105
|
+
## Contributing
|
106
|
+
|
107
|
+
1. Fork it
|
108
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
109
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
110
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
111
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/lib/mws.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'openssl'
|
3
|
+
|
4
|
+
module Mws
|
5
|
+
|
6
|
+
autoload :Apis, 'mws/apis'
|
7
|
+
autoload :Connection, 'mws/connection'
|
8
|
+
autoload :Enum, 'mws/enum'
|
9
|
+
autoload :EnumEntry, 'mws/enum'
|
10
|
+
autoload :Errors, 'mws/errors'
|
11
|
+
autoload :Query, 'mws/query'
|
12
|
+
autoload :Serializer, 'mws/serializer'
|
13
|
+
autoload :Signer, 'mws/signer'
|
14
|
+
autoload :Utils, 'mws/utils'
|
15
|
+
|
16
|
+
# The current version of this ruby gem
|
17
|
+
VERSION = '0.0.1'
|
18
|
+
|
19
|
+
Utils.alias self, Apis::Feeds,
|
20
|
+
:Distance,
|
21
|
+
:Feed,
|
22
|
+
:ImageListing,
|
23
|
+
:Inventory,
|
24
|
+
:Money,
|
25
|
+
:PriceListing,
|
26
|
+
:Product,
|
27
|
+
:Shipping,
|
28
|
+
:Weight
|
29
|
+
|
30
|
+
def self.connect(options)
|
31
|
+
Connection.new options
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/lib/mws/apis.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Mws::Apis::Feeds
|
2
|
+
|
3
|
+
autoload :Api, 'mws/apis/feeds/api'
|
4
|
+
autoload :Distance, 'mws/apis/feeds/distance'
|
5
|
+
autoload :Feed, 'mws/apis/feeds/feed'
|
6
|
+
autoload :ImageListing, 'mws/apis/feeds/image_listing'
|
7
|
+
autoload :Inventory, 'mws/apis/feeds/inventory'
|
8
|
+
autoload :Measurement, 'mws/apis/feeds/measurement'
|
9
|
+
autoload :Money, 'mws/apis/feeds/money'
|
10
|
+
autoload :PriceListing, 'mws/apis/feeds/price_listing'
|
11
|
+
autoload :Product, 'mws/apis/feeds/product'
|
12
|
+
autoload :SalePrice, 'mws/apis/feeds/sale_price'
|
13
|
+
autoload :Shipping, 'mws/apis/feeds/shipping'
|
14
|
+
autoload :SubmissionInfo, 'mws/apis/feeds/submission_info'
|
15
|
+
autoload :SubmissionResult, 'mws/apis/feeds/submission_result'
|
16
|
+
autoload :TargetedApi, 'mws/apis/feeds/api'
|
17
|
+
autoload :Transaction, 'mws/apis/feeds/transaction'
|
18
|
+
autoload :Weight, 'mws/apis/feeds/weight'
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module Mws::Apis::Feeds
|
2
|
+
|
3
|
+
class Api
|
4
|
+
|
5
|
+
attr_reader :products, :images, :prices, :shipping, :inventory
|
6
|
+
|
7
|
+
def initialize(connection, defaults={})
|
8
|
+
raise Mws::Errors::ValidationError, 'A connection is required.' if connection.nil?
|
9
|
+
@connection = connection
|
10
|
+
defaults[:version] ||= '2009-01-01'
|
11
|
+
@defaults = defaults
|
12
|
+
|
13
|
+
@products = self.for :product
|
14
|
+
@images = self.for :image
|
15
|
+
@prices = self.for :price
|
16
|
+
@shipping = self.for :override
|
17
|
+
@inventory = self.for :inventory
|
18
|
+
end
|
19
|
+
|
20
|
+
def get(id)
|
21
|
+
node = @connection.get '/', { feed_submission_id: id }, @defaults.merge(
|
22
|
+
action: 'GetFeedSubmissionResult',
|
23
|
+
xpath: 'AmazonEnvelope/Message'
|
24
|
+
)
|
25
|
+
SubmissionResult.from_xml node
|
26
|
+
end
|
27
|
+
|
28
|
+
def submit(body, params)
|
29
|
+
params[:feed_type] = Feed::Type.for(params[:feed_type]).val
|
30
|
+
doc = @connection.post '/', params, body, @defaults.merge(action: 'SubmitFeed')
|
31
|
+
SubmissionInfo.from_xml doc.xpath('FeedSubmissionInfo').first
|
32
|
+
end
|
33
|
+
|
34
|
+
def cancel(options={})
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
def list(params={})
|
39
|
+
params[:feed_submission_id] ||= params.delete(:ids) || [ params.delete(:id) ].flatten.compact
|
40
|
+
doc = @connection.get('/', params, @defaults.merge(action: 'GetFeedSubmissionList'))
|
41
|
+
doc.xpath('FeedSubmissionInfo').map do | node |
|
42
|
+
SubmissionInfo.from_xml node
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def count()
|
47
|
+
@connection.get('/', {}, @defaults.merge(action: 'GetFeedSubmissionCount')).xpath('Count').first.text.to_i
|
48
|
+
end
|
49
|
+
|
50
|
+
def for(type)
|
51
|
+
TargetedApi.new self, @connection.merchant, type
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
class TargetedApi
|
57
|
+
|
58
|
+
def initialize(feeds, merchant, type)
|
59
|
+
@feeds = feeds
|
60
|
+
@merchant = merchant
|
61
|
+
@message_type = Feed::Message::Type.for(type)
|
62
|
+
@feed_type = Feed::Type.for(type)
|
63
|
+
end
|
64
|
+
|
65
|
+
def add(*resources)
|
66
|
+
submit resources, :update, true
|
67
|
+
end
|
68
|
+
|
69
|
+
def update(*resources)
|
70
|
+
submit resources, :update
|
71
|
+
end
|
72
|
+
|
73
|
+
def patch(*resources)
|
74
|
+
raise 'Operation Type not supported.' unless @feed_type == Feed::Type.PRODUCT
|
75
|
+
submit resources, :partial_update
|
76
|
+
end
|
77
|
+
|
78
|
+
def delete(*resources)
|
79
|
+
submit resources, :delete
|
80
|
+
end
|
81
|
+
|
82
|
+
def submit(resources, def_operation_type=nil, purge_and_replace=false)
|
83
|
+
messages = []
|
84
|
+
feed = Feed.new @merchant, @message_type do
|
85
|
+
resources.each do | resource |
|
86
|
+
operation_type = def_operation_type
|
87
|
+
if resource.respond_to?(:operation_type) and resource.operation_type
|
88
|
+
operation_type = resource.operation_type
|
89
|
+
end
|
90
|
+
messages << message(resource, operation_type)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
Transaction.new @feeds.submit(feed.to_xml, feed_type: @feed_type, purge_and_replace: purge_and_replace) do
|
94
|
+
messages.each do | message |
|
95
|
+
item message.id, message.resource.sku, message.operation_type,
|
96
|
+
message.resource.respond_to?(:type) ? message.resource.type : nil
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Mws::Apis::Feeds
|
2
|
+
|
3
|
+
class Distance < Measurement
|
4
|
+
|
5
|
+
Unit = Mws::Enum.for(
|
6
|
+
inches: 'inches',
|
7
|
+
feet: 'feet',
|
8
|
+
meters: 'meters',
|
9
|
+
decimeters: 'decimeters',
|
10
|
+
centimeters:'centimeters',
|
11
|
+
millimeters:'millimeters',
|
12
|
+
micrometers: 'micrometers',
|
13
|
+
nanometers: 'nanometers',
|
14
|
+
picometers: 'picometers'
|
15
|
+
)
|
16
|
+
|
17
|
+
def initialize(amount, unit=nil)
|
18
|
+
super amount, unit || :feet
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module Mws::Apis::Feeds
|
4
|
+
|
5
|
+
class Feed
|
6
|
+
|
7
|
+
Type = Mws::Enum.for(
|
8
|
+
product: '_POST_PRODUCT_DATA_',
|
9
|
+
product_relationship: '_POST_PRODUCT_RELATIONSHIP_DATA_',
|
10
|
+
item: '_POST_ITEM_DATA_',
|
11
|
+
override: '_POST_PRODUCT_OVERRIDES_DATA_',
|
12
|
+
image: '_POST_PRODUCT_IMAGE_DATA_',
|
13
|
+
price: '_POST_PRODUCT_PRICING_DATA_',
|
14
|
+
inventory: '_POST_INVENTORY_AVAILABILITY_DATA_',
|
15
|
+
order_acknowledgement: '_POST_ORDER_ACKNOWLEDGEMENT_DATA_',
|
16
|
+
order_fufillment: '_POST_ORDER_FULFILLMENT_DATA_',
|
17
|
+
fulfillment_order_request: '_POST_FULFILLMENT_ORDER_REQUEST_DATA_',
|
18
|
+
fulfillment_order_cancellation: '_POST_FULFILLMENT_ORDER_CANCELLATION_REQUEST_DATA'
|
19
|
+
)
|
20
|
+
|
21
|
+
attr_reader :merchant, :purge_and_replace
|
22
|
+
|
23
|
+
Mws::Enum.sym_reader self, :message_type
|
24
|
+
|
25
|
+
def initialize(merchant, message_type, purge_and_replace=false, &block)
|
26
|
+
@merchant = merchant
|
27
|
+
raise Mws::Errors::ValidationError, 'Merchant identifier is required.' if @merchant.nil?
|
28
|
+
@message_type = Message::Type.for(message_type)
|
29
|
+
raise Mws::Errors::ValidationError, 'A valid message type is required.' if @message_type.nil?
|
30
|
+
@purge_and_replace = purge_and_replace
|
31
|
+
@messages = []
|
32
|
+
Builder.new(self, @messages).instance_eval &block if block_given?
|
33
|
+
end
|
34
|
+
|
35
|
+
def messages
|
36
|
+
@messages.dup
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_xml
|
40
|
+
Nokogiri::XML::Builder.new do | xml |
|
41
|
+
xml.AmazonEnvelope('xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:noNamespaceSchemaLocation' => 'amznenvelope.xsd') {
|
42
|
+
xml.Header {
|
43
|
+
xml.DocumentVersion '1.01'
|
44
|
+
xml.MerchantIdentifier @merchant
|
45
|
+
}
|
46
|
+
xml.MessageType @message_type.val
|
47
|
+
xml.PurgeAndReplace @purge_and_replace
|
48
|
+
@messages.each do | message |
|
49
|
+
message.to_xml xml
|
50
|
+
end
|
51
|
+
}
|
52
|
+
end.to_xml
|
53
|
+
end
|
54
|
+
|
55
|
+
class Builder
|
56
|
+
|
57
|
+
def initialize(feed, messages)
|
58
|
+
@feed = feed
|
59
|
+
@messages = messages
|
60
|
+
end
|
61
|
+
|
62
|
+
def message(resource, operation_type=nil)
|
63
|
+
(@messages << Message.new(@messages.length + 1, @feed.message_type, resource, operation_type)).last
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
class Message
|
69
|
+
|
70
|
+
Type = Mws::Enum.for(
|
71
|
+
fufillment_center: 'FulfillmentCenter',
|
72
|
+
inventory: 'Inventory',
|
73
|
+
listings: 'Listings',
|
74
|
+
order_acknowledgement: 'OrderAcknowledgement',
|
75
|
+
order_adjustment: 'OrderAdjustment',
|
76
|
+
order_fulfillment: 'OrderFulfillment',
|
77
|
+
override: 'Override',
|
78
|
+
price: 'Price',
|
79
|
+
processing_report: 'ProcessingReport',
|
80
|
+
product: 'Product',
|
81
|
+
image: 'ProductImage',
|
82
|
+
relationship: 'Relationship',
|
83
|
+
settlement_report: 'SettlementReport'
|
84
|
+
)
|
85
|
+
|
86
|
+
OperationType = Mws::Enum.for(
|
87
|
+
update: 'Update',
|
88
|
+
delete: 'Delete',
|
89
|
+
partial_update: 'PartialUpdate'
|
90
|
+
)
|
91
|
+
|
92
|
+
attr_reader :id, :resource
|
93
|
+
|
94
|
+
Mws::Enum.sym_reader self, :type, :operation_type
|
95
|
+
|
96
|
+
def initialize(id, type, resource, operation_type)
|
97
|
+
@id = id
|
98
|
+
@type = Type.for(type)
|
99
|
+
@resource = resource
|
100
|
+
@operation_type = OperationType.for(operation_type) || OperationType.UPDATE
|
101
|
+
end
|
102
|
+
|
103
|
+
def to_xml(parent)
|
104
|
+
Mws::Serializer.tree 'Message', parent do | xml |
|
105
|
+
xml.MessageID @id
|
106
|
+
xml.OperationType @operation_type.val
|
107
|
+
@resource.to_xml @type.val, xml
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|