dustbag 0.0.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.
Files changed (138) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +92 -0
  4. data/lib/dustbag.rb +47 -0
  5. data/lib/dustbag/accessories.rb +7 -0
  6. data/lib/dustbag/accessory.rb +6 -0
  7. data/lib/dustbag/arguments.rb +8 -0
  8. data/lib/dustbag/availability_attributes.rb +9 -0
  9. data/lib/dustbag/browse_node.rb +15 -0
  10. data/lib/dustbag/browse_nodes.rb +7 -0
  11. data/lib/dustbag/common.rb +7 -0
  12. data/lib/dustbag/customer_reviews.rb +11 -0
  13. data/lib/dustbag/dimension.rb +13 -0
  14. data/lib/dustbag/dimensions.rb +10 -0
  15. data/lib/dustbag/editorial_review.rb +11 -0
  16. data/lib/dustbag/editorial_reviews.rb +7 -0
  17. data/lib/dustbag/http_headers.rb +8 -0
  18. data/lib/dustbag/image.rb +5 -0
  19. data/lib/dustbag/image_set.rb +9 -0
  20. data/lib/dustbag/image_sets.rb +7 -0
  21. data/lib/dustbag/item.rb +21 -0
  22. data/lib/dustbag/item_attributes.rb +79 -0
  23. data/lib/dustbag/item_link.rb +9 -0
  24. data/lib/dustbag/item_links.rb +7 -0
  25. data/lib/dustbag/item_search_request.rb +7 -0
  26. data/lib/dustbag/item_search_response.rb +8 -0
  27. data/lib/dustbag/items.rb +14 -0
  28. data/lib/dustbag/language.rb +7 -0
  29. data/lib/dustbag/languages.rb +7 -0
  30. data/lib/dustbag/offer.rb +52 -0
  31. data/lib/dustbag/offer_summary.rb +12 -0
  32. data/lib/dustbag/offers.rb +7 -0
  33. data/lib/dustbag/operation_request.rb +13 -0
  34. data/lib/dustbag/parser.rb +26 -0
  35. data/lib/dustbag/parser/collection_node.rb +37 -0
  36. data/lib/dustbag/parser/map_collection_node.rb +19 -0
  37. data/lib/dustbag/parser/node.rb +112 -0
  38. data/lib/dustbag/price.rb +13 -0
  39. data/lib/dustbag/request.rb +11 -0
  40. data/lib/dustbag/similar_product.rb +6 -0
  41. data/lib/dustbag/similar_products.rb +7 -0
  42. data/lib/dustbag/simple_product.rb +9 -0
  43. data/lib/dustbag/variation_attribute.rb +7 -0
  44. data/lib/dustbag/variation_attributes.rb +7 -0
  45. data/lib/dustbag/variation_summary.rb +13 -0
  46. data/lib/dustbag/variations.rb +18 -0
  47. data/lib/dustbag/version.rb +3 -0
  48. data/spec/dustbag/accessories_spec.rb +9 -0
  49. data/spec/dustbag/accessory_spec.rb +10 -0
  50. data/spec/dustbag/arguments_spec.rb +9 -0
  51. data/spec/dustbag/availability_attributes_spec.rb +21 -0
  52. data/spec/dustbag/browse_node_spec.rb +33 -0
  53. data/spec/dustbag/browse_nodes_spec.rb +9 -0
  54. data/spec/dustbag/customer_reviews_spec.rb +17 -0
  55. data/spec/dustbag/dimension_spec.rb +17 -0
  56. data/spec/dustbag/dimensions_spec.rb +29 -0
  57. data/spec/dustbag/editorial_review_spec.rb +21 -0
  58. data/spec/dustbag/editorial_reviews_spec.rb +9 -0
  59. data/spec/dustbag/http_headers_spec.rb +11 -0
  60. data/spec/dustbag/image_set_spec.rb +13 -0
  61. data/spec/dustbag/image_sets_spec.rb +9 -0
  62. data/spec/dustbag/image_spec.rb +9 -0
  63. data/spec/dustbag/item_attributes_spec.rb +188 -0
  64. data/spec/dustbag/item_link_spec.rb +17 -0
  65. data/spec/dustbag/item_links_spec.rb +9 -0
  66. data/spec/dustbag/item_search_request_spec.rb +21 -0
  67. data/spec/dustbag/item_search_response_spec.rb +13 -0
  68. data/spec/dustbag/item_spec.rb +110 -0
  69. data/spec/dustbag/items_spec.rb +25 -0
  70. data/spec/dustbag/language_spec.rb +17 -0
  71. data/spec/dustbag/languages_spec.rb +9 -0
  72. data/spec/dustbag/offer_spec.rb +43 -0
  73. data/spec/dustbag/offer_summary_spec.rb +30 -0
  74. data/spec/dustbag/offers_spec.rb +9 -0
  75. data/spec/dustbag/operation_request_spec.rb +27 -0
  76. data/spec/dustbag/parser_spec.rb +23 -0
  77. data/spec/dustbag/price_spec.rb +18 -0
  78. data/spec/dustbag/request_spec.rb +25 -0
  79. data/spec/dustbag/similar_product_spec.rb +18 -0
  80. data/spec/dustbag/similar_products_spec.rb +9 -0
  81. data/spec/dustbag/variation_attribute_spec.rb +17 -0
  82. data/spec/dustbag/variation_attributes_spec.rb +9 -0
  83. data/spec/dustbag/variation_summary_spec.rb +19 -0
  84. data/spec/dustbag/variations_spec.rb +22 -0
  85. data/spec/fixtures/accessories.xml +23 -0
  86. data/spec/fixtures/accessory.xml +4 -0
  87. data/spec/fixtures/arguments.xml +11 -0
  88. data/spec/fixtures/availability_attributes.xml +5 -0
  89. data/spec/fixtures/book_item_attributes.xml +61 -0
  90. data/spec/fixtures/browse_node.xml +23 -0
  91. data/spec/fixtures/browse_nodes.xml +25 -0
  92. data/spec/fixtures/customer_reviews.xml +5 -0
  93. data/spec/fixtures/dimension.xml +1 -0
  94. data/spec/fixtures/dimensions.xml +6 -0
  95. data/spec/fixtures/editorial_review.xml +5 -0
  96. data/spec/fixtures/editorial_reviews.xml +7 -0
  97. data/spec/fixtures/http_headers.xml +3 -0
  98. data/spec/fixtures/image.xml +5 -0
  99. data/spec/fixtures/image_set.xml +32 -0
  100. data/spec/fixtures/image_sets.xml +34 -0
  101. data/spec/fixtures/invalid_request.xml +8 -0
  102. data/spec/fixtures/item.xml +40 -0
  103. data/spec/fixtures/item_attributes.xml +58 -0
  104. data/spec/fixtures/item_large.xml +500 -0
  105. data/spec/fixtures/item_link.xml +4 -0
  106. data/spec/fixtures/item_links.xml +30 -0
  107. data/spec/fixtures/item_medium.xml +123 -0
  108. data/spec/fixtures/item_search_request.xml +5 -0
  109. data/spec/fixtures/item_search_response.xml +433 -0
  110. data/spec/fixtures/item_small.xml +40 -0
  111. data/spec/fixtures/item_with_accessories.xml +122 -0
  112. data/spec/fixtures/item_with_variation_attributes.xml +264 -0
  113. data/spec/fixtures/item_with_variations.xml +1016 -0
  114. data/spec/fixtures/items.xml +411 -0
  115. data/spec/fixtures/language.xml +4 -0
  116. data/spec/fixtures/languages.xml +6 -0
  117. data/spec/fixtures/movie_item_attributes.xml +30 -0
  118. data/spec/fixtures/offer.xml +26 -0
  119. data/spec/fixtures/offer_summary.xml +11 -0
  120. data/spec/fixtures/offers.xml +31 -0
  121. data/spec/fixtures/operation_request.xml +18 -0
  122. data/spec/fixtures/price.xml +5 -0
  123. data/spec/fixtures/request.xml +8 -0
  124. data/spec/fixtures/root_browse_node.xml +11 -0
  125. data/spec/fixtures/similar_product.xml +4 -0
  126. data/spec/fixtures/similar_products.xml +18 -0
  127. data/spec/fixtures/variation_attribute.xml +4 -0
  128. data/spec/fixtures/variation_attributes.xml +6 -0
  129. data/spec/fixtures/variation_summary.xml +12 -0
  130. data/spec/fixtures/variations.xml +1000 -0
  131. data/spec/shared_examples/collection_node.rb +15 -0
  132. data/spec/shared_examples/common_response.rb +7 -0
  133. data/spec/shared_examples/map_collection_node.rb +13 -0
  134. data/spec/shared_examples/node.rb +9 -0
  135. data/spec/shared_examples/node_context.rb +6 -0
  136. data/spec/shared_examples/simple_product.rb +4 -0
  137. data/spec/spec_helper.rb +16 -0
  138. metadata +356 -0
@@ -0,0 +1,9 @@
1
+ module Dustbag
2
+ class ItemLink
3
+ include Parser::Node
4
+
5
+ text_attributes :description
6
+
7
+ text_attributes url: 'URL'
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ module Dustbag
2
+ class ItemLinks
3
+ include Parser::CollectionNode
4
+
5
+ member_name 'ItemLink'
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Dustbag
2
+ class ItemSearchRequest
3
+ include Parser::Node
4
+
5
+ text_attributes :keywords, :response_group, :search_index
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ module Dustbag
2
+ class ItemSearchResponse
3
+ include Parser::Node
4
+ include Common
5
+
6
+ children :items
7
+ end
8
+ end
@@ -0,0 +1,14 @@
1
+ module Dustbag
2
+ class Items
3
+ include Parser::Node
4
+ include Parser::CollectionNode
5
+
6
+ member_name 'Item'
7
+
8
+ text_attributes :more_search_results_url
9
+
10
+ numeric_attributes :total_results, :total_pages
11
+
12
+ children :request
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ module Dustbag
2
+ class Language
3
+ include Parser::Node
4
+
5
+ text_attributes :name, :type
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Dustbag
2
+ class Languages
3
+ include Parser::CollectionNode
4
+
5
+ member_name 'Language'
6
+ end
7
+ end
@@ -0,0 +1,52 @@
1
+ module Dustbag
2
+ class Offer
3
+ include Parser::Node
4
+
5
+ def condition
6
+ offer_attrs = subnode('OfferAttributes')
7
+ condition = offer_attrs && offer_attrs.locate('Condition').first
8
+ condition && condition.text
9
+ end
10
+
11
+ def id
12
+ id = offer_listing && offer_listing.locate('OfferListingId').first
13
+ id && id.text
14
+ end
15
+
16
+ def price
17
+ price = offer_listing && offer_listing.locate('Price').first
18
+ Price.parse(price)
19
+ end
20
+
21
+ def amount_saved
22
+ savings = offer_listing && offer_listing.locate('AmountSaved').first
23
+ Price.parse(savings)
24
+ end
25
+
26
+ def availability
27
+ availability = offer_listing && offer_listing.locate('Availability').first
28
+ availability && availability.text
29
+ end
30
+
31
+ def eligible_for_super_saver_shipping?
32
+ eligible = offer_listing && offer_listing.locate('IsEligibleForSuperSaverShipping').first
33
+ eligible && eligible.text == '1'
34
+ end
35
+
36
+ def eligible_for_prime?
37
+ eligible = offer_listing && offer_listing.locate('IsEligibleForPrime').first
38
+ eligible && eligible.text == '1'
39
+ end
40
+
41
+ def availability_attributes
42
+ availability = offer_listing && offer_listing.locate('AvailabilityAttributes').first
43
+ AvailabilityAttributes.new(availability)
44
+ end
45
+
46
+ private
47
+
48
+ def offer_listing
49
+ subnode('OfferListing')
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,12 @@
1
+ module Dustbag
2
+ class OfferSummary
3
+ include Parser::Node
4
+
5
+ numeric_attributes :total_new, :total_used, :total_collectible,
6
+ :total_refurbished
7
+
8
+ def lowest_new_price
9
+ Price.parse(subnode('LowestNewPrice'))
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ module Dustbag
2
+ class Offers
3
+ include Parser::CollectionNode
4
+
5
+ member_name 'Offer'
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ module Dustbag
2
+ class OperationRequest
3
+ include Parser::Node
4
+
5
+ text_attributes :request_id, :request_processing_time
6
+
7
+ children :arguments
8
+
9
+ child name: :http_headers,
10
+ node: 'HTTPHeaders',
11
+ class: HttpHeaders
12
+ end
13
+ end
@@ -0,0 +1,26 @@
1
+ module Dustbag
2
+ module Parser
3
+ extend self
4
+
5
+ class Error < RuntimeError; end
6
+
7
+ def parse(body)
8
+ document = Ox.parse(body)
9
+
10
+ raise Error.new('Not a Ox::Document') unless document.is_a?(Ox::Document)
11
+
12
+ response_type = document.root.name
13
+
14
+ case response_type
15
+ when 'ItemSearchResponse'
16
+ ItemSearchResponse.new(document.root)
17
+ else
18
+ raise Error.new(response_type + ' is not implemented!')
19
+ end
20
+ end
21
+
22
+ autoload :CollectionNode, 'dustbag/parser/collection_node'
23
+ autoload :MapCollectionNode, 'dustbag/parser/map_collection_node'
24
+ autoload :Node, 'dustbag/parser/node'
25
+ end
26
+ end
@@ -0,0 +1,37 @@
1
+ module Dustbag
2
+ module Parser
3
+ module CollectionNode
4
+ include Enumerable
5
+ include Node
6
+
7
+ extend Forwardable
8
+
9
+ def_delegators :collection, :each, :size, :empty?
10
+
11
+ def self.included(base)
12
+ base.extend(ClassMethods)
13
+ end
14
+
15
+ def collection
16
+ members = node && node.locate(member_name) || []
17
+ @collection ||= members.map do |member|
18
+ member_class.new(member)
19
+ end
20
+ end
21
+
22
+ def member_name
23
+ self.class.member_name
24
+ end
25
+
26
+ def member_class
27
+ Dustbag.const_get(member_name)
28
+ end
29
+
30
+ module ClassMethods
31
+ def member_name(name = nil)
32
+ @member_name ||= name
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,19 @@
1
+ module Dustbag
2
+ module Parser
3
+ module MapCollectionNode
4
+ extend Forwardable
5
+
6
+ def_delegators(:collection, :[], :keys, :values)
7
+
8
+ private
9
+
10
+ def collection
11
+ members = node && node.locate(member_name) || []
12
+ @collection ||= members.inject({}) do |acc, val|
13
+ acc[val['Name']] = val['Value']
14
+ acc
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,112 @@
1
+ module Dustbag
2
+ module Parser
3
+ module Node
4
+ attr_reader :node, :subnodes
5
+ extend Forwardable
6
+
7
+ def_delegators :node, :value, :text, :attributes
8
+
9
+ def self.included(base)
10
+ base.extend(ClassMethods)
11
+ end
12
+
13
+ def initialize(node)
14
+ @node = node
15
+ @subnodes = {}
16
+ end
17
+
18
+ def subnode_text(subnode_name)
19
+ subnode = subnode(subnode_name)
20
+ subnode && subnode.text
21
+ end
22
+
23
+ def subnode(subnode_name)
24
+ subnodes[subnode_name] ||= node.locate(subnode_name).first
25
+ end
26
+
27
+ def repeated_subnodes(subnode_name)
28
+ subnodes[subnode_name] ||= node.locate(subnode_name)
29
+ end
30
+
31
+ def repeated_subnodes_text(subnode_name)
32
+ repeated_subnodes(subnode_name).map(&:text)
33
+ end
34
+
35
+ module ClassMethods
36
+ def text_attributes(*attrs)
37
+ attrs.each do |attr|
38
+ node_name = xml_node_name(attr)
39
+
40
+ if attr.is_a?(Hash)
41
+ attr.each do |key, value|
42
+ define_method(key) do
43
+ subnode_text(value)
44
+ end
45
+ end
46
+ else
47
+ define_method(attr) do
48
+ subnode_text(node_name)
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ def numeric_attributes(*attrs)
55
+ attrs.each do |attr|
56
+ node_name = xml_node_name(attr)
57
+
58
+ if attr.is_a?(Hash)
59
+ attr.each do |key, value|
60
+ define_method(key) do
61
+ subnode_text(value).to_i
62
+ end
63
+ end
64
+ else
65
+ define_method(attr) do
66
+ subnode_text(node_name).to_i
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ def children(*attrs)
73
+ attrs.each do |attr|
74
+
75
+ if attr.is_a?(Hash)
76
+ attr.each do |key, value|
77
+ node_name = xml_node_name(key)
78
+ define_method(key) do
79
+ value.new(subnode(node_name))
80
+ end
81
+ end
82
+ else
83
+ node_name = xml_node_name(attr)
84
+ define_method(attr) do
85
+ Dustbag.const_get(node_name).new(subnode(node_name))
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ def child(name)
92
+ if name.is_a? Hash
93
+ define_method(name[:name]) do
94
+ (name[:class] || Dustbag.const_get(name[:node])).new(subnode(name[:node]))
95
+ end
96
+ else
97
+ node_name = xml_node_name(attr)
98
+ define_method(name) do
99
+ Dustbag.const_get(node_name).new(subnode(node_name))
100
+ end
101
+ end
102
+ end
103
+
104
+ private
105
+
106
+ def xml_node_name(attr)
107
+ attr.to_s.split('_').map(&:capitalize).join('')
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,13 @@
1
+ module Dustbag
2
+ module Price
3
+ extend self
4
+
5
+ def parse(xml_node)
6
+ xml_node && begin
7
+ amount = xml_node.locate('Amount').first
8
+ currency = xml_node.locate('Currency').first
9
+ Money.new(amount && amount.text, currency && currency.text)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ module Dustbag
2
+ class Request
3
+ include Parser::Node
4
+
5
+ children :item_search_request
6
+
7
+ def valid?
8
+ subnode_text('IsValid') == 'True'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ module Dustbag
2
+ class SimilarProduct
3
+ include Parser::Node
4
+ include SimpleProduct
5
+ end
6
+ end
@@ -0,0 +1,7 @@
1
+ module Dustbag
2
+ class SimilarProducts
3
+ include Parser::CollectionNode
4
+
5
+ member_name 'SimilarProduct'
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ module Dustbag
2
+ module SimpleProduct
3
+ include Parser::Node
4
+
5
+ text_attributes asin: 'ASIN'
6
+
7
+ text_attributes :title
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ module Dustbag
2
+ class VariationAttribute
3
+ include Parser::Node
4
+
5
+ text_attributes :name, :value
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Dustbag
2
+ class VariationAttributes
3
+ include Parser::CollectionNode
4
+
5
+ member_name 'VariationAttribute'
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ module Dustbag
2
+ class VariationSummary
3
+ include Parser::Node
4
+
5
+ def lowest_price
6
+ Price.parse(subnode('LowestPrice'))
7
+ end
8
+
9
+ def highest_price
10
+ Price.parse(subnode('HighestPrice'))
11
+ end
12
+ end
13
+ end