wildcard-pair 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/wildcard-pair.rb +5 -0
- data/lib/wildcard-pair/Article.rb +90 -0
- data/lib/wildcard-pair/ArticleCard.rb +84 -0
- data/lib/wildcard-pair/Color.rb +41 -0
- data/lib/wildcard-pair/Media.rb +4 -0
- data/lib/wildcard-pair/Media/Image.rb +46 -0
- data/lib/wildcard-pair/Media/Video.rb +70 -0
- data/lib/wildcard-pair/Offer.rb +102 -0
- data/lib/wildcard-pair/Price.rb +44 -0
- data/lib/wildcard-pair/Product.rb +132 -0
- data/lib/wildcard-pair/ProductCard.rb +117 -0
- data/lib/wildcard-pair/ProductSearchCard.rb +89 -0
- data/lib/wildcard-pair/ProductSearchResult.rb +54 -0
- data/lib/wildcard-pair/Rating.rb +47 -0
- data/lib/wildcard-pair/Review.rb +105 -0
- data/lib/wildcard-pair/ReviewCard.rb +82 -0
- data/lib/wildcard-pair/VideoCard.rb +84 -0
- data/lib/wildcard-pair/hash_mappable.rb +18 -0
- data/lib/wildcard-pair/util/extract_metatags.rb +99 -0
- metadata +124 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
|
2
|
+
require_relative 'hash_mappable.rb'
|
3
|
+
require 'active_model'
|
4
|
+
|
5
|
+
module WildcardPair
|
6
|
+
class Price
|
7
|
+
include ActiveModel::Validations
|
8
|
+
include ActiveModel::Serializers::JSON
|
9
|
+
include WildcardPair::HashMappable
|
10
|
+
|
11
|
+
attr_accessor :price, :currency
|
12
|
+
|
13
|
+
validates :price, presence: true, numericality: {greater_than_or_equal_to: 0}
|
14
|
+
|
15
|
+
def initialize(attributes = {})
|
16
|
+
|
17
|
+
#let's set currency to USD by default
|
18
|
+
@currency = "USD"
|
19
|
+
|
20
|
+
attributes.each do |name, value|
|
21
|
+
send("#{name}=", value)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def attributes
|
26
|
+
instance_values
|
27
|
+
end
|
28
|
+
|
29
|
+
#exclude validation fields in the JSON output
|
30
|
+
def as_json(options={})
|
31
|
+
super(options.merge({:except => [:errors, :validation_context]}))
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
def to_json(options = {})
|
36
|
+
if self.valid?
|
37
|
+
super(options)
|
38
|
+
else
|
39
|
+
raise "Price is not valid - please remedy the following errors:" << self.errors.messages.to_s
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
#!/usr/bin/env ruby -wKU
|
2
|
+
|
3
|
+
require 'active_model'
|
4
|
+
require_relative 'hash_mappable.rb'
|
5
|
+
|
6
|
+
module WildcardPair
|
7
|
+
class Product
|
8
|
+
|
9
|
+
include ActiveModel::Validations
|
10
|
+
include ActiveModel::Serializers::JSON
|
11
|
+
include WildcardPair::HashMappable
|
12
|
+
|
13
|
+
attr_accessor :name, :merchant, :brand, :description, :gender, :rating, :rating_scale, :rating_count, :sizes, :model, :app_link_ios, :app_link_android
|
14
|
+
attr_reader :colors, :images, :related_items, :referenced_items, :options
|
15
|
+
|
16
|
+
validates :name, presence: true
|
17
|
+
validates :description, presence: true
|
18
|
+
validates :gender, allow_nil: true, inclusion: {in: %w(male female unisex) }
|
19
|
+
|
20
|
+
validate :validateColors
|
21
|
+
validate :validateImages
|
22
|
+
|
23
|
+
def initialize(attributes = {})
|
24
|
+
attributes.each do |name, value|
|
25
|
+
send("#{name}=", value)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def attributes
|
30
|
+
instance_values
|
31
|
+
end
|
32
|
+
|
33
|
+
def metatags=(metatags)
|
34
|
+
if metatags.nil? || !metatags.is_a?(Hash)
|
35
|
+
return
|
36
|
+
end
|
37
|
+
|
38
|
+
#see what you can set based on metatags
|
39
|
+
self.name=metatags['title']
|
40
|
+
self.description=metatags['description']
|
41
|
+
self.images=metatags['image_url']
|
42
|
+
self.app_link_ios=metatags['applink_ios']
|
43
|
+
self.app_link_android=metatags['applink_android']
|
44
|
+
end
|
45
|
+
|
46
|
+
def colors=(colors)
|
47
|
+
@colors ||= Array.new
|
48
|
+
|
49
|
+
if colors.is_a?(Array)
|
50
|
+
colors.each do |color|
|
51
|
+
@colors << map_hash(color, Color.new)
|
52
|
+
end
|
53
|
+
elsif colors.is_a?(Color)
|
54
|
+
@colors << colors
|
55
|
+
else
|
56
|
+
@colors << map_hash(colors, Color.new)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def images=(images)
|
61
|
+
@images ||= Array.new
|
62
|
+
|
63
|
+
if images.is_a?(Array)
|
64
|
+
@images = images
|
65
|
+
else
|
66
|
+
@images << images
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def related_items=(related_items)
|
71
|
+
@related_items ||= Array.new
|
72
|
+
|
73
|
+
if related_items.is_a?(Array)
|
74
|
+
@related_items = related_items
|
75
|
+
else
|
76
|
+
@related_items << related_items
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def referenced_items=(referenced_items)
|
81
|
+
@referenced_items ||= Array.new
|
82
|
+
|
83
|
+
if referenced_items.is_a?(Array)
|
84
|
+
@referenced_items = referenced_items
|
85
|
+
else
|
86
|
+
@referenced_items << referenced_items
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def options=(options)
|
91
|
+
@options ||= Array.new
|
92
|
+
|
93
|
+
if options.is_a?(Array)
|
94
|
+
@options = options
|
95
|
+
else
|
96
|
+
@options << options
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def validateColors
|
101
|
+
if (!@colors.nil? && @colors.any?)
|
102
|
+
@colors.each do |color|
|
103
|
+
if (!color.is_a?(Color) || !color.valid?)
|
104
|
+
errors.add(:colors, "At least one of the colors is an invalid color object")
|
105
|
+
return
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def validateImages
|
112
|
+
if @images.nil? || (@images.is_a?(Array) && !@images.any?)
|
113
|
+
errors.add(:images, 'A product image is required')
|
114
|
+
return
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
#exclude validation fields in the JSON output
|
119
|
+
def as_json(options={})
|
120
|
+
super(options.merge({:except => [:errors, :validation_context]}))
|
121
|
+
end
|
122
|
+
|
123
|
+
def to_json(options={})
|
124
|
+
if self.valid?
|
125
|
+
super(options)
|
126
|
+
else
|
127
|
+
raise "Product is not valid - please remedy the following errors:" << self.errors.messages.to_s
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
#!/usr/bin/env ruby -wKU
|
2
|
+
|
3
|
+
require 'active_model'
|
4
|
+
require_relative 'hash_mappable.rb'
|
5
|
+
|
6
|
+
module WildcardPair
|
7
|
+
class ProductCard
|
8
|
+
private
|
9
|
+
|
10
|
+
attr_accessor :offers, :product, :card_type, :pair_version
|
11
|
+
|
12
|
+
public
|
13
|
+
|
14
|
+
include ActiveModel::Validations
|
15
|
+
include ActiveModel::Serializers::JSON
|
16
|
+
include WildcardPair::HashMappable
|
17
|
+
|
18
|
+
attr_accessor :web_url
|
19
|
+
attr_reader :offers, :card_type, :pair_version, :product
|
20
|
+
|
21
|
+
validates :web_url, presence: true
|
22
|
+
validate :validateOffers
|
23
|
+
validate :validateProduct
|
24
|
+
|
25
|
+
def initialize(attributes = {})
|
26
|
+
attributes.each do |name, value|
|
27
|
+
send("#{name}=", value)
|
28
|
+
end
|
29
|
+
|
30
|
+
@card_type = 'product'
|
31
|
+
|
32
|
+
if !Gem.loaded_specs['wildcard-pair'].nil?
|
33
|
+
@pair_version = Gem.loaded_specs['wildcard-pair'].version.to_s
|
34
|
+
else
|
35
|
+
@pair_version = "unknown"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def attributes
|
40
|
+
instance_values
|
41
|
+
end
|
42
|
+
|
43
|
+
def populate_from_metatags(web_url)
|
44
|
+
@web_url=web_url
|
45
|
+
metatags = WildcardPair::ExtractMetaTags.extract(@web_url)
|
46
|
+
|
47
|
+
##now that we've extracted metatags, create a Product and Offer object with it
|
48
|
+
self.product=WildcardPair::Product.new metatags: metatags
|
49
|
+
self.offers=WildcardPair::Offer.new metatags: metatags
|
50
|
+
end
|
51
|
+
|
52
|
+
def offers=(offers)
|
53
|
+
@offers ||= Array.new
|
54
|
+
|
55
|
+
if offers.is_a?(Array)
|
56
|
+
offers.each do |offer|
|
57
|
+
@offers << map_hash(offer, Offer.new)
|
58
|
+
end
|
59
|
+
elsif offers.is_a?(Offer)
|
60
|
+
@offers << offers
|
61
|
+
else
|
62
|
+
@offers << map_hash(offers, Offer.new)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def product=(product)
|
67
|
+
@product = map_hash(product, WildcardPair::Product.new)
|
68
|
+
end
|
69
|
+
|
70
|
+
def validateOffers
|
71
|
+
if @offers.nil? || (@offers.is_a?(Array) && !@offers.any?)
|
72
|
+
errors.add(:offers, 'At least one offer is required')
|
73
|
+
return
|
74
|
+
end
|
75
|
+
|
76
|
+
@offers.each do |offer|
|
77
|
+
if !offer.is_a?(Offer)
|
78
|
+
errors.add(:offers, "At least one of the offers is invalid")
|
79
|
+
elsif !offer.valid?
|
80
|
+
offer.errors.each do |error, msg|
|
81
|
+
errors["offer[%s]" % error] = msg
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def validateProduct
|
88
|
+
if @product.nil? || !@product.is_a?(Product)
|
89
|
+
errors.add(:product, "A product is required")
|
90
|
+
return
|
91
|
+
end
|
92
|
+
|
93
|
+
if !@product.nil?
|
94
|
+
if !@product.valid?
|
95
|
+
@product.errors.each do |error, msg|
|
96
|
+
errors["product[%s]" % error] = msg
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
#exclude validation fields in the JSON output
|
103
|
+
def as_json(options={})
|
104
|
+
super(options.merge({:except => [:errors, :validation_context]}))
|
105
|
+
end
|
106
|
+
|
107
|
+
def to_json(options={})
|
108
|
+
if self.valid?
|
109
|
+
super(options)
|
110
|
+
else
|
111
|
+
raise "Product Card is not valid - please remedy the following errors:" << self.errors.messages.to_s
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
@@ -0,0 +1,89 @@
|
|
1
|
+
#ProductCard
|
2
|
+
#!/usr/bin/env ruby -wKU
|
3
|
+
|
4
|
+
require 'active_model'
|
5
|
+
require_relative 'hash_mappable.rb'
|
6
|
+
|
7
|
+
module WildcardPair
|
8
|
+
class ProductSearchCard
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
attr_accessor :products, :card_type, :pair_version
|
13
|
+
|
14
|
+
public
|
15
|
+
|
16
|
+
include ActiveModel::Validations
|
17
|
+
include ActiveModel::Serializers::JSON
|
18
|
+
include WildcardPair::HashMappable
|
19
|
+
|
20
|
+
attr_accessor :total_results
|
21
|
+
|
22
|
+
attr_reader :products, :card_type, :pair_version
|
23
|
+
|
24
|
+
validates :total_results, presence: true, numericality: {only_integer: true, greater_than_or_equal_to: 0}
|
25
|
+
validate :validateSearchResults
|
26
|
+
|
27
|
+
def initialize(attributes = {})
|
28
|
+
attributes.each do |name, value|
|
29
|
+
send("#{name}=", value)
|
30
|
+
end
|
31
|
+
|
32
|
+
@card_type = 'product_search'
|
33
|
+
|
34
|
+
if !Gem.loaded_specs['wildcard-pair'].nil?
|
35
|
+
@pair_version = Gem.loaded_specs['wildcard-pair'].version.to_s
|
36
|
+
else
|
37
|
+
@pair_version = "unknown"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def attributes
|
42
|
+
instance_values
|
43
|
+
end
|
44
|
+
|
45
|
+
def products=(products)
|
46
|
+
@products ||= Array.new
|
47
|
+
|
48
|
+
if products.is_a?(Array)
|
49
|
+
products.each do |product|
|
50
|
+
@products << map_hash(product, ProductSearchResult.new)
|
51
|
+
end
|
52
|
+
elsif products.is_a?(ProductSearchResult)
|
53
|
+
@products << products
|
54
|
+
else
|
55
|
+
@products << map_hash(products, ProductSearchResult.new)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def validateSearchResults
|
60
|
+
if @products.nil?
|
61
|
+
errors.add(:products, "Products can be empty, but must exist")
|
62
|
+
return
|
63
|
+
end
|
64
|
+
|
65
|
+
@products.each do |product|
|
66
|
+
if (!product.is_a?(ProductSearchResult) || !product.valid?)
|
67
|
+
errors.add(:products, "One of the products in the search result is invalid")
|
68
|
+
return
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
#exclude validation fields in the JSON output
|
75
|
+
def as_json(options={})
|
76
|
+
super(options.merge({:except => [:errors, :validation_context]}))
|
77
|
+
end
|
78
|
+
|
79
|
+
def to_json(options={})
|
80
|
+
if self.valid?
|
81
|
+
super(options)
|
82
|
+
else
|
83
|
+
raise "Product Search Card is not valid - please remedy below errors:" << self.errors.messages.to_s
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'active_model'
|
2
|
+
require_relative 'hash_mappable.rb'
|
3
|
+
|
4
|
+
module WildcardPair
|
5
|
+
class ProductSearchResult
|
6
|
+
include ActiveModel::Validations
|
7
|
+
include ActiveModel::Serializers::JSON
|
8
|
+
include WildcardPair::HashMappable
|
9
|
+
|
10
|
+
attr_accessor :name, :price, :product_card_address, :image_url
|
11
|
+
|
12
|
+
validates :name, presence: true
|
13
|
+
validates :price, presence: true
|
14
|
+
validates :product_card_address, presence: true
|
15
|
+
validates :image_url, presence: true
|
16
|
+
|
17
|
+
validate :validatePrice
|
18
|
+
|
19
|
+
def initialize(attributes = {})
|
20
|
+
attributes.each do |name, value|
|
21
|
+
send("#{name}=", value)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def attributes
|
26
|
+
instance_values
|
27
|
+
end
|
28
|
+
|
29
|
+
def price=(price)
|
30
|
+
@price = map_hash(price, WildcardPair::Price.new)
|
31
|
+
end
|
32
|
+
|
33
|
+
def validatePrice
|
34
|
+
if @price.nil? || !@price.is_a?(Price) || !@price.valid?
|
35
|
+
errors.add(:price, 'Price does not exist or is invalid')
|
36
|
+
return
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
#exclude validation fields in the JSON output
|
41
|
+
def as_json(options={})
|
42
|
+
super(options.merge({:except => [:errors, :validation_context]}))
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_json(options={})
|
46
|
+
if self.valid?
|
47
|
+
super(options)
|
48
|
+
else
|
49
|
+
raise "ProductSearchResult is not valid - please remedy the following errors:" << self.errors.messages.to_s
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
#!/usr/bin/env ruby -wKU
|
2
|
+
|
3
|
+
require 'active_model'
|
4
|
+
require_relative 'hash_mappable.rb'
|
5
|
+
|
6
|
+
module WildcardPair
|
7
|
+
class Rating
|
8
|
+
|
9
|
+
include ActiveModel::Validations
|
10
|
+
include ActiveModel::Serializers::JSON
|
11
|
+
include WildcardPair::HashMappable
|
12
|
+
|
13
|
+
# required fields
|
14
|
+
attr_accessor :rating, :minimum_rating, :maximum_rating
|
15
|
+
# optional fields
|
16
|
+
attr_accessor :number_of_ratings
|
17
|
+
|
18
|
+
validates :rating, presence: true, numericality: {greater_than_or_equal_to: 0}
|
19
|
+
validates :minimum_rating, presence: true, numericality: {greater_than_or_equal_to: 0}
|
20
|
+
validates :maximum_rating, presence: true, numericality: {greater_than_or_equal_to: 0}
|
21
|
+
validates :number_of_ratings, allow_nil: true, numericality: {only_integer: true, greater_than_or_equal_to: 0}
|
22
|
+
|
23
|
+
def initialize(attributes = {})
|
24
|
+
attributes.each do |name, value|
|
25
|
+
send("#{name}=", value)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def attributes
|
30
|
+
instance_values
|
31
|
+
end
|
32
|
+
|
33
|
+
#exclude validation fields in the JSON output
|
34
|
+
def as_json(options={})
|
35
|
+
super(options.merge({:except => [:errors, :validation_context]}))
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_json(options={})
|
39
|
+
if self.valid?
|
40
|
+
super(options)
|
41
|
+
else
|
42
|
+
raise "Video is not valid - please remedy the following errors:" << self.errors.messages.to_s
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|