yml_builder 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/yml_builder/categories.rb +13 -5
- data/lib/yml_builder/common.rb +5 -4
- data/lib/yml_builder/common_offer.rb +81 -66
- data/lib/yml_builder/currencies.rb +36 -30
- data/lib/yml_builder/offer_simple.rb +20 -20
- data/lib/yml_builder/offer_vendor_model.rb +16 -16
- data/lib/yml_builder/offers.rb +23 -10
- data/lib/yml_builder/shop.rb +37 -33
- data/lib/yml_builder/stats.rb +7 -4
- data/lib/yml_builder/version.rb +2 -1
- data/lib/yml_builder/yml.rb +26 -19
- data/test/example_4_huge_items_spec.rb +53 -0
- data/test/test_yml.yml +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c467842b66355a23a26354a37d682f6b51f92978
|
4
|
+
data.tar.gz: 985bb3a8e9b5b1506d42f46eacf5dac26198d20c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd9d5578dd5ee634250de1dfe75a69aceb910a0698fdf2872f343c291ef9bc6657836ab4cdbccdc9843c4b2d48023ab2f2c26ad212fc1c10c21fe5ac2e7c07cf
|
7
|
+
data.tar.gz: bc985ba000bf496bdf2623b6aa307a557b85204adbc3932137069c8225fb786ebd9e2d5cd9eee657860441758f41ea36517a50b13331773d56042fae906441da
|
data/CHANGELOG.md
CHANGED
@@ -9,11 +9,13 @@ module YmlBuilder
|
|
9
9
|
# price.categories.filter = [1, 3, 4, 5]
|
10
10
|
attr_reader :filter
|
11
11
|
|
12
|
+
|
12
13
|
def initialize(stats)
|
13
14
|
@stats = stats
|
14
15
|
init_class
|
15
16
|
end
|
16
17
|
|
18
|
+
|
17
19
|
# Метод добавляет категорию Интернет-магазина в прайс-лист с учетом выставленных в значении filter настроек.
|
18
20
|
#
|
19
21
|
# @param [Hash] opts параметры категорий Интернет-магазина
|
@@ -32,11 +34,12 @@ module YmlBuilder
|
|
32
34
|
raise "Ошибка: не указан 'id' для добавления категории" if opts[:id].nil?
|
33
35
|
raise "Ошибка: не указан 'name' для добавления категории" if opts[:name].nil?
|
34
36
|
@params[opts[:id]] = { parent_id: opts[:parent_id], name: opts[:name] }
|
35
|
-
@params
|
37
|
+
@params = Hash[@params.sort_by { |id, data| id }]
|
36
38
|
@stats.add(:categories, 1)
|
37
39
|
true
|
38
40
|
end
|
39
41
|
|
42
|
+
|
40
43
|
# Метод проверяет необходимость добавления категории или товара в прайс-лист
|
41
44
|
# с учетом выставленных в значении filter настроек.
|
42
45
|
#
|
@@ -46,6 +49,7 @@ module YmlBuilder
|
|
46
49
|
@filter.count == 0 ? true : @filter.include?(id)
|
47
50
|
end
|
48
51
|
|
52
|
+
|
49
53
|
# Метод позволяет огарничить формирование прайс-листа только категориями, указанными в данном поле
|
50
54
|
# Filter может принимать значения nil или [], тогда считается, что допустимо включение в прайс-лист
|
51
55
|
# всех товаров.
|
@@ -57,6 +61,7 @@ module YmlBuilder
|
|
57
61
|
@filter = allow || Array.new
|
58
62
|
end
|
59
63
|
|
64
|
+
|
60
65
|
# Метод формирует фрагмент YML файла каталога Яндекс.Маркет, содержащий список категорий
|
61
66
|
#
|
62
67
|
# @param [Integer] ident отступ от левого края в символах
|
@@ -80,6 +85,7 @@ module YmlBuilder
|
|
80
85
|
out.join("\n")
|
81
86
|
end
|
82
87
|
|
88
|
+
|
83
89
|
# Метод возвращает true, если категория, передаваемая в качестве параметра, уже добавлена в прайс-лист
|
84
90
|
#
|
85
91
|
# @param [Object] id идентификатор категории
|
@@ -88,12 +94,14 @@ module YmlBuilder
|
|
88
94
|
@params[id].nil? ? false : true
|
89
95
|
end
|
90
96
|
|
97
|
+
|
91
98
|
private
|
92
99
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
100
|
+
|
101
|
+
def init_class
|
102
|
+
@params = Hash.new
|
103
|
+
self.filter = nil
|
104
|
+
end
|
97
105
|
|
98
106
|
end
|
99
107
|
end
|
data/lib/yml_builder/common.rb
CHANGED
@@ -3,12 +3,13 @@ module YmlBuilder # :nodoc:
|
|
3
3
|
|
4
4
|
def self.encode_special_chars(out)
|
5
5
|
return out.to_s.gsub(/[\"\&\>\<\']/, '"' => '"',
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
'&' => '&',
|
7
|
+
'>' => '>',
|
8
|
+
'<' => '<',
|
9
|
+
"'" => ''')
|
10
10
|
end
|
11
11
|
|
12
|
+
|
12
13
|
def self.convert_key(key)
|
13
14
|
return 'currencyId' if key == :currency_id
|
14
15
|
return 'categoryId' if key == :category_id
|
@@ -20,10 +20,12 @@ module YmlBuilder
|
|
20
20
|
# Список обязательных полей для данного типа оффера
|
21
21
|
attr_accessor :mandatories
|
22
22
|
|
23
|
+
|
23
24
|
def initialize
|
24
25
|
init_class
|
25
26
|
end
|
26
27
|
|
28
|
+
|
27
29
|
# Метод добавляет ссылку на фотографию товара в конец списка, и ограничивает список 10-ю фотографиями
|
28
30
|
# @param [String] url ссылка на фотографию товара
|
29
31
|
# @example Примеры использования
|
@@ -33,9 +35,10 @@ module YmlBuilder
|
|
33
35
|
@picture << url
|
34
36
|
@picture.uniq!
|
35
37
|
warn "Предупреждение: число картинок превышает 10 (offer_id=#{@id}). Сокращаем до 10" if @picture.count > 10
|
36
|
-
@picture = @picture[0,9]
|
38
|
+
@picture = @picture[0, 9]
|
37
39
|
end
|
38
40
|
|
41
|
+
|
39
42
|
# Метод добавляет ссылку на фотографию товара в начало списка, и ограничивает список 10-ю фотографиями
|
40
43
|
# @param [String] url ссылка на фотографию товара (на основную фотографию)
|
41
44
|
# @example Примеры использования
|
@@ -45,9 +48,10 @@ module YmlBuilder
|
|
45
48
|
@picture.unshift(url)
|
46
49
|
@picture.uniq!
|
47
50
|
warn "Предупреждение: число картинок превышает 10 (offer_id=#{@id}). Сокращаем до 10" if @picture.count > 10
|
48
|
-
@picture = @picture[0,9]
|
51
|
+
@picture = @picture[0, 9]
|
49
52
|
end
|
50
53
|
|
54
|
+
|
51
55
|
# Метод добавляет характеристики товара (для секции 'param')
|
52
56
|
#
|
53
57
|
# @param [String] name наименование параметра, например "Количество товара"
|
@@ -58,9 +62,10 @@ module YmlBuilder
|
|
58
62
|
# offer.add_param(name: "Количество", unit: "шт.", value: 100)
|
59
63
|
# offer.add_param(name: "Обложка", value: "мягкая")
|
60
64
|
def add_param(name:, unit: nil, value:)
|
61
|
-
@meta[name] = { unit: unit, value: value}
|
65
|
+
@meta[name] = { unit: unit, value: value }
|
62
66
|
end
|
63
67
|
|
68
|
+
|
64
69
|
# Метод формирует фрагмент YML файла каталога Яндекс.Маркет для одного товара
|
65
70
|
#
|
66
71
|
# @param [Integer] ident отступ от левого края в символах
|
@@ -85,89 +90,99 @@ module YmlBuilder
|
|
85
90
|
out.join("\n")
|
86
91
|
end
|
87
92
|
|
93
|
+
|
88
94
|
private
|
89
95
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
96
|
+
|
97
|
+
def method_missing(method_sym, *arguments, &block)
|
98
|
+
if @params.include?(method_sym.to_s.gsub(/=$/, '').to_sym)
|
99
|
+
processing_method(method_sym, arguments.first)
|
100
|
+
else
|
101
|
+
super
|
102
|
+
end
|
95
103
|
end
|
96
|
-
end
|
97
104
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
105
|
+
|
106
|
+
def processing_method(method_sym, value)
|
107
|
+
if method_sym.to_s.match(/=$/)
|
108
|
+
key = method_sym.to_s.gsub(/=$/, '')
|
109
|
+
warn "Предупреждение: url не должен превышать 512 символов" if key == 'url' && value.length > 512
|
110
|
+
warn "Предупреждение: price не может быть равен нулю (offer_id #{@id})" if key == 'price' && value.to_f == 0
|
111
|
+
warn "Предупреждение: weight не может быть равен нулю (offer_id #{@id})" if key == 'weight' && value.to_f == 0
|
112
|
+
@params[key.to_sym] = value
|
113
|
+
else
|
114
|
+
@params[method_sym.to_s.gsub(/=$/, '').to_sym]
|
115
|
+
end
|
107
116
|
end
|
108
|
-
end
|
109
117
|
|
110
|
-
def header_line
|
111
|
-
out = Array.new
|
112
|
-
out << "id=#{@id.to_s.inspect}"
|
113
|
-
out << "type=#{@type.to_s.inspect}" if @type != 'simple'
|
114
|
-
out << "available=\"#{@available.inspect}\""
|
115
|
-
out << "bid=#{@bid.inspect}" unless @bid.nil?
|
116
|
-
"<offer #{out.join (' ')}>"
|
117
|
-
end
|
118
118
|
|
119
|
-
|
120
|
-
|
121
|
-
|
119
|
+
def header_line
|
120
|
+
out = Array.new
|
121
|
+
out << "id=#{@id.to_s.inspect}"
|
122
|
+
out << "type=#{@type.to_s.inspect}" if @type != 'simple'
|
123
|
+
out << "available=\"#{@available.inspect}\""
|
124
|
+
out << "bid=#{@bid.inspect}" unless @bid.nil?
|
125
|
+
"<offer #{out.join (' ')}>"
|
126
|
+
end
|
127
|
+
|
122
128
|
|
123
|
-
|
124
|
-
|
125
|
-
"<param name=#{::YmlBuilder::Common.encode_special_chars(name.to_s).inspect}>#{::YmlBuilder::Common.encode_special_chars(data[:value].to_s)}</param>"
|
126
|
-
else
|
127
|
-
"<param name=#{::YmlBuilder::Common.encode_special_chars(name.to_s).inspect} unit=#{::YmlBuilder::Common.encode_special_chars(data[:unit]).inspect}>#{::YmlBuilder::Common.encode_special_chars(data[:value].to_s)}</param>"
|
129
|
+
def footer_line
|
130
|
+
'</offer>'
|
128
131
|
end
|
129
|
-
end
|
130
132
|
|
131
|
-
def to_yml_subsections(key)
|
132
|
-
out = Array.new
|
133
133
|
|
134
|
-
|
135
|
-
|
136
|
-
|
134
|
+
def param_line(name, data)
|
135
|
+
if data[:unit].nil?
|
136
|
+
"<param name=#{::YmlBuilder::Common.encode_special_chars(name.to_s).inspect}>#{::YmlBuilder::Common.encode_special_chars(data[:value].to_s)}</param>"
|
137
|
+
else
|
138
|
+
"<param name=#{::YmlBuilder::Common.encode_special_chars(name.to_s).inspect} unit=#{::YmlBuilder::Common.encode_special_chars(data[:unit]).inspect}>#{::YmlBuilder::Common.encode_special_chars(data[:value].to_s)}</param>"
|
137
139
|
end
|
138
|
-
|
139
|
-
|
140
|
-
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
def to_yml_subsections(key)
|
144
|
+
out = Array.new
|
145
|
+
|
146
|
+
if key == :picture
|
147
|
+
@picture.each do |url|
|
148
|
+
out << " <picture>#{url}</picture>"
|
149
|
+
end
|
150
|
+
else
|
151
|
+
@meta.each do |name, data|
|
152
|
+
out << " #{param_line(name, data)}"
|
153
|
+
end
|
141
154
|
end
|
155
|
+
|
156
|
+
out
|
142
157
|
end
|
143
158
|
|
144
|
-
out
|
145
|
-
end
|
146
159
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
160
|
+
def to_yml_mandatories(key, value)
|
161
|
+
raise "Ошибка секции 'offer': не заполнено обязательное значение #{key.to_s.inspect}" if (value.nil? || value.to_s == '')
|
162
|
+
key_xml = ::YmlBuilder::Common.convert_key(key)
|
163
|
+
" <#{key_xml}>#{::YmlBuilder::Common.encode_special_chars(value)}</#{key_xml}>"
|
164
|
+
end
|
152
165
|
|
153
|
-
def to_yml_optional(key, value)
|
154
|
-
return nil if value.nil?
|
155
|
-
key_xml = ::YmlBuilder::Common.convert_key(key)
|
156
|
-
" <#{key_xml}>#{::YmlBuilder::Common.encode_special_chars(value)}</#{key_xml}>"
|
157
|
-
end
|
158
166
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
167
|
+
def to_yml_optional(key, value)
|
168
|
+
return nil if value.nil?
|
169
|
+
key_xml = ::YmlBuilder::Common.convert_key(key)
|
170
|
+
" <#{key_xml}>#{::YmlBuilder::Common.encode_special_chars(value)}</#{key_xml}>"
|
171
|
+
end
|
163
172
|
|
164
|
-
@id = 0
|
165
|
-
@type = 'unknown'
|
166
|
-
@available = false
|
167
|
-
@bid = nil
|
168
173
|
|
169
|
-
|
170
|
-
|
174
|
+
def init_class
|
175
|
+
@params = Hash.new
|
176
|
+
@meta = Hash.new
|
177
|
+
@picture = Array.new
|
178
|
+
|
179
|
+
@id = 0
|
180
|
+
@type = 'unknown'
|
181
|
+
@available = false
|
182
|
+
@bid = nil
|
183
|
+
|
184
|
+
@mandatories = Array.new
|
185
|
+
end
|
171
186
|
|
172
187
|
end
|
173
188
|
end
|
@@ -5,6 +5,7 @@ module YmlBuilder
|
|
5
5
|
init_class
|
6
6
|
end
|
7
7
|
|
8
|
+
|
8
9
|
# Метод формирует фрагмент YML файла каталога Яндекс.Маркет, содержащий список валют
|
9
10
|
#
|
10
11
|
# @param [Integer] ident отступ от левого края в символах
|
@@ -25,45 +26,50 @@ module YmlBuilder
|
|
25
26
|
out.join("\n")
|
26
27
|
end
|
27
28
|
|
29
|
+
|
28
30
|
private
|
29
31
|
|
30
|
-
def valid?(method_sym, allow, value)
|
31
|
-
return true if value.to_s.match(/^\s*[+-]?((\d+_?)*\d+(\.(\d+_?)*\d+)?|\.(\d+_?)*\d+)(\s*|([eE][+-]?(\d+_?)*\d+)\s*)$/)
|
32
|
-
return true if allow.include?(value)
|
33
|
-
warn "Предупреждение: значение валюты #{method_sym.to_s.upcase} может быть цифрой или значением из #{allow.inspect}"
|
34
|
-
false
|
35
|
-
end
|
36
32
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
33
|
+
def valid?(method_sym, allow, value)
|
34
|
+
return true if value.to_s.match(/^\s*[+-]?((\d+_?)*\d+(\.(\d+_?)*\d+)?|\.(\d+_?)*\d+)(\s*|([eE][+-]?(\d+_?)*\d+)\s*)$/)
|
35
|
+
return true if allow.include?(value)
|
36
|
+
warn "Предупреждение: значение валюты #{method_sym.to_s.upcase} может быть цифрой или значением из #{allow.inspect}"
|
37
|
+
false
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
def processing_method(method_sym, value)
|
42
|
+
if method_sym.to_s.match(/=$/)
|
43
|
+
key = method_sym.to_s.gsub(/=$/, '')
|
44
|
+
allow = [:cbrf, :nbu, :nbk, :cb]
|
45
|
+
valid?(key.to_s, allow, value)
|
42
46
|
|
43
|
-
|
44
|
-
|
45
|
-
|
47
|
+
@params[key.to_sym] = value
|
48
|
+
else
|
49
|
+
@params[method_sym.to_s.gsub(/=$/, '').to_sym]
|
50
|
+
end
|
46
51
|
end
|
47
|
-
end
|
48
52
|
|
49
|
-
def init_class
|
50
|
-
@params = Hash.new
|
51
53
|
|
52
|
-
|
53
|
-
|
54
|
-
@params[:usd] = nil
|
55
|
-
@params[:eur] = nil
|
56
|
-
@params[:uah] = nil
|
57
|
-
@params[:kzt] = nil
|
58
|
-
end
|
54
|
+
def init_class
|
55
|
+
@params = Hash.new
|
59
56
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
57
|
+
@params[:rur] = nil
|
58
|
+
@params[:rub] = nil
|
59
|
+
@params[:usd] = nil
|
60
|
+
@params[:eur] = nil
|
61
|
+
@params[:uah] = nil
|
62
|
+
@params[:kzt] = nil
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
def method_missing(method_sym, *arguments, &block)
|
67
|
+
if @params.include?(method_sym.to_s.gsub(/=$/, '').to_sym)
|
68
|
+
processing_method(method_sym, arguments.first)
|
69
|
+
else
|
70
|
+
super
|
71
|
+
end
|
65
72
|
end
|
66
|
-
end
|
67
73
|
|
68
74
|
end
|
69
75
|
end
|
@@ -5,27 +5,27 @@ module YmlBuilder # :nodoc:
|
|
5
5
|
super
|
6
6
|
@type = 'simple'
|
7
7
|
|
8
|
-
@params
|
9
|
-
@params[:url]
|
10
|
-
@params[:price]
|
11
|
-
@params[:oldprice]
|
12
|
-
@params[:currency_id]
|
13
|
-
@params[:category_id]
|
14
|
-
@params[:market_category]
|
15
|
-
@params[:picture]
|
16
|
-
@params[:store]
|
17
|
-
@params[:pickup]
|
18
|
-
@params[:delivery]
|
8
|
+
@params = Hash.new
|
9
|
+
@params[:url] = nil
|
10
|
+
@params[:price] = nil
|
11
|
+
@params[:oldprice] = nil
|
12
|
+
@params[:currency_id] = nil
|
13
|
+
@params[:category_id] = nil
|
14
|
+
@params[:market_category] = nil
|
15
|
+
@params[:picture] = nil
|
16
|
+
@params[:store] = nil
|
17
|
+
@params[:pickup] = nil
|
18
|
+
@params[:delivery] = nil
|
19
19
|
@params[:local_delivery_cost] = nil
|
20
|
-
@params[:name]
|
21
|
-
@params[:vendor]
|
22
|
-
@params[:vendor_code]
|
23
|
-
@params[:description]
|
24
|
-
@params[:country_of_origin]
|
25
|
-
@params[:adult]
|
26
|
-
@params[:param]
|
27
|
-
@params[:weight]
|
28
|
-
@params[:dimensions]
|
20
|
+
@params[:name] = nil
|
21
|
+
@params[:vendor] = nil
|
22
|
+
@params[:vendor_code] = nil
|
23
|
+
@params[:description] = nil
|
24
|
+
@params[:country_of_origin] = nil
|
25
|
+
@params[:adult] = nil
|
26
|
+
@params[:param] = nil
|
27
|
+
@params[:weight] = nil
|
28
|
+
@params[:dimensions] = nil
|
29
29
|
|
30
30
|
@mandatories = [:url, :price, :currency_id, :category_id, :delivery, :name]
|
31
31
|
end
|
@@ -6,26 +6,26 @@ module YmlBuilder # :nodoc:
|
|
6
6
|
|
7
7
|
@type = 'vendor.model'
|
8
8
|
|
9
|
-
@params[:m]
|
10
|
-
@params[:m][:url]
|
11
|
-
@params[:m][:price]
|
9
|
+
@params[:m] = Hash.new
|
10
|
+
@params[:m][:url] = nil
|
11
|
+
@params[:m][:price] = nil
|
12
12
|
@params[:m][:currency_id] = nil
|
13
13
|
@params[:m][:category_id] = nil
|
14
|
-
@params[:m][:delivery]
|
15
|
-
@params[:m][:vendor]
|
16
|
-
@params[:m][:model]
|
14
|
+
@params[:m][:delivery] = nil
|
15
|
+
@params[:m][:vendor] = nil
|
16
|
+
@params[:m][:model] = nil
|
17
17
|
|
18
|
-
@params[:o]
|
19
|
-
@params[:o][:local_delivery_cost]
|
20
|
-
@params[:o][:type_prefix]
|
21
|
-
@params[:o][:vendor_code]
|
22
|
-
@params[:o][:description]
|
18
|
+
@params[:o] = Hash.new
|
19
|
+
@params[:o][:local_delivery_cost] = nil
|
20
|
+
@params[:o][:type_prefix] = nil
|
21
|
+
@params[:o][:vendor_code] = nil
|
22
|
+
@params[:o][:description] = nil
|
23
23
|
@params[:o][:manufacturer_warranty] = nil
|
24
|
-
@params[:o][:country_of_origin]
|
25
|
-
@params[:o][:available]
|
26
|
-
@params[:o][:sales_notes]
|
27
|
-
@params[:o][:downloadable]
|
28
|
-
@params[:o][:adult]
|
24
|
+
@params[:o][:country_of_origin] = nil
|
25
|
+
@params[:o][:available] = nil
|
26
|
+
@params[:o][:sales_notes] = nil
|
27
|
+
@params[:o][:downloadable] = nil
|
28
|
+
@params[:o][:adult] = nil
|
29
29
|
end
|
30
30
|
|
31
31
|
end
|
data/lib/yml_builder/offers.rb
CHANGED
@@ -5,11 +5,12 @@ module YmlBuilder
|
|
5
5
|
class Offers
|
6
6
|
|
7
7
|
def initialize(stats, categories)
|
8
|
-
@stats
|
8
|
+
@stats = stats
|
9
9
|
@categories = categories
|
10
10
|
init_class
|
11
11
|
end
|
12
12
|
|
13
|
+
|
13
14
|
# Метод добавляет товар в прайс-лист с учетом выставленных в значении filter настроек.
|
14
15
|
#
|
15
16
|
# @param [{YmlBuilder::CommonOffer}] offer карточка товара
|
@@ -29,6 +30,7 @@ module YmlBuilder
|
|
29
30
|
true
|
30
31
|
end
|
31
32
|
|
33
|
+
|
32
34
|
# Метод формирует фрагмент YML файла каталога Яндекс.Маркет для всего списка товаров
|
33
35
|
#
|
34
36
|
# @param [Integer] ident отступ от левого края в символах
|
@@ -37,13 +39,19 @@ module YmlBuilder
|
|
37
39
|
@offers = @offers.sort_by { |id, offer| id }
|
38
40
|
|
39
41
|
out = Array.new
|
40
|
-
|
41
|
-
|
42
|
-
|
42
|
+
idx = 1
|
43
|
+
out << add_ident("<offers>", ident)
|
44
|
+
@offers.each do |_, offer|
|
45
|
+
# Формируем один товар в YAML, разбиваем на строки, чтобы к каждой
|
46
|
+
# добавить нужное количество пробелов для формирования корректного
|
47
|
+
# YAML-файла
|
48
|
+
arr = offer.to_yml(2).split(/[\n\r]/)
|
49
|
+
arr.map! { |line| add_ident(line, ident) }
|
50
|
+
out << arr.join("\n")
|
51
|
+
# puts "#{idx}/#{@offers.count}" if idx % 1000 == 0
|
52
|
+
idx += 1
|
43
53
|
end
|
44
|
-
out << "</offers>"
|
45
|
-
|
46
|
-
out.map! { |line| ' '.rjust(ident, ' ') + line }
|
54
|
+
out << add_ident("</offers>", ident)
|
47
55
|
out.join("\n")
|
48
56
|
end
|
49
57
|
|
@@ -51,9 +59,14 @@ module YmlBuilder
|
|
51
59
|
private
|
52
60
|
|
53
61
|
|
54
|
-
|
55
|
-
|
56
|
-
|
62
|
+
def add_ident(str, ident)
|
63
|
+
' '.rjust(ident, ' ') + str
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
def init_class
|
68
|
+
@offers = Hash.new
|
69
|
+
end
|
57
70
|
|
58
71
|
end
|
59
72
|
end
|
data/lib/yml_builder/shop.rb
CHANGED
@@ -5,6 +5,7 @@ module YmlBuilder
|
|
5
5
|
init_class
|
6
6
|
end
|
7
7
|
|
8
|
+
|
8
9
|
# Метод формирует фрагмент YML файла каталога Яндекс.Маркет для описания Интернет-магазина
|
9
10
|
#
|
10
11
|
# @return [String] фрагмент YML файла каталога Яндекс.Маркет
|
@@ -34,43 +35,46 @@ module YmlBuilder
|
|
34
35
|
|
35
36
|
private
|
36
37
|
|
37
|
-
def init_class
|
38
|
-
@params = Hash.new
|
39
|
-
|
40
|
-
@params[:m] = Hash.new
|
41
|
-
@params[:m][:name] = ''
|
42
|
-
@params[:m][:company] = ''
|
43
|
-
@params[:m][:url] = ''
|
44
|
-
|
45
|
-
@params[:o] = Hash.new
|
46
|
-
@params[:o][:phone] = nil
|
47
|
-
@params[:o][:platform] = nil
|
48
|
-
@params[:o][:version] = nil
|
49
|
-
@params[:o][:agency] = nil
|
50
|
-
@params[:o][:email] = nil
|
51
|
-
@params[:o][:adult] = nil
|
52
|
-
@params[:o][:cpa] = nil
|
53
|
-
end
|
54
38
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
39
|
+
def init_class
|
40
|
+
@params = Hash.new
|
41
|
+
|
42
|
+
@params[:m] = Hash.new
|
43
|
+
@params[:m][:name] = ''
|
44
|
+
@params[:m][:company] = ''
|
45
|
+
@params[:m][:url] = ''
|
46
|
+
|
47
|
+
@params[:o] = Hash.new
|
48
|
+
@params[:o][:phone] = nil
|
49
|
+
@params[:o][:platform] = nil
|
50
|
+
@params[:o][:version] = nil
|
51
|
+
@params[:o][:agency] = nil
|
52
|
+
@params[:o][:email] = nil
|
53
|
+
@params[:o][:adult] = nil
|
54
|
+
@params[:o][:cpa] = nil
|
62
55
|
end
|
63
|
-
end
|
64
56
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
@params[
|
70
|
-
|
71
|
-
|
57
|
+
|
58
|
+
def method_missing(method_sym, *arguments, &block)
|
59
|
+
if @params[:m].include?(method_sym.to_s.gsub(/=$/, '').to_sym)
|
60
|
+
processing_method(:m, method_sym, arguments.first)
|
61
|
+
elsif @params[:o].include?(method_sym.to_s.gsub(/=$/, '').to_sym)
|
62
|
+
processing_method(:o, method_sym, arguments.first)
|
63
|
+
else
|
64
|
+
super
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
def processing_method(part, method_sym, value)
|
70
|
+
if method_sym.to_s.match(/=$/)
|
71
|
+
key = method_sym.to_s.gsub(/=$/, '')
|
72
|
+
warn "Предупреждение: название магазина не должно быть больше 20 символов" if key == 'name' && value.length > 20
|
73
|
+
@params[part][key.to_sym] = value
|
74
|
+
else
|
75
|
+
@params[part][method_sym.to_s.gsub(/=$/, '').to_sym]
|
76
|
+
end
|
72
77
|
end
|
73
|
-
end
|
74
78
|
|
75
79
|
|
76
80
|
end
|
data/lib/yml_builder/stats.rb
CHANGED
@@ -2,18 +2,21 @@ module YmlBuilder # :nodoc:
|
|
2
2
|
class Stats
|
3
3
|
attr_reader :stats
|
4
4
|
|
5
|
+
|
5
6
|
def initialize
|
6
7
|
init_class
|
7
8
|
end
|
8
9
|
|
10
|
+
|
9
11
|
def init_class
|
10
|
-
@stats
|
12
|
+
@stats = Hash.new
|
11
13
|
@stats[:categories] = 0
|
12
|
-
@stats[:total]
|
13
|
-
@stats[:available]
|
14
|
-
@stats[:price]
|
14
|
+
@stats[:total] = 0
|
15
|
+
@stats[:available] = 0
|
16
|
+
@stats[:price] = 0
|
15
17
|
end
|
16
18
|
|
19
|
+
|
17
20
|
def add(key, value)
|
18
21
|
@stats[key] += value
|
19
22
|
end
|
data/lib/yml_builder/version.rb
CHANGED
data/lib/yml_builder/yml.rb
CHANGED
@@ -31,14 +31,15 @@ module YmlBuilder
|
|
31
31
|
|
32
32
|
|
33
33
|
def initialize
|
34
|
-
@stats
|
35
|
-
@shop
|
36
|
-
@currencies
|
37
|
-
@categories
|
38
|
-
@offers
|
34
|
+
@stats = ::YmlBuilder::Stats.new
|
35
|
+
@shop = ::YmlBuilder::Shop.new
|
36
|
+
@currencies = ::YmlBuilder::Currencies.new
|
37
|
+
@categories = ::YmlBuilder::Categories.new(@stats)
|
38
|
+
@offers = ::YmlBuilder::Offers.new(@stats, @categories)
|
39
39
|
@local_delivery_cost = nil
|
40
40
|
end
|
41
41
|
|
42
|
+
|
42
43
|
# Метод устанавливает стоимость доставки в месте локации магазина. Например, если магазин находится в Москве,
|
43
44
|
# то при указанни данной стоимости, она будет показана покупателям в этом же районе.
|
44
45
|
#
|
@@ -48,6 +49,7 @@ module YmlBuilder
|
|
48
49
|
@local_delivery_cost = value
|
49
50
|
end
|
50
51
|
|
52
|
+
|
51
53
|
# Метод возвращает статистику по результатам генерации прайс-листа: всего товаров, товаров в наличии, стоимость
|
52
54
|
# товаров в наличии (без учета количества)
|
53
55
|
#
|
@@ -59,6 +61,7 @@ module YmlBuilder
|
|
59
61
|
@stats.stats
|
60
62
|
end
|
61
63
|
|
64
|
+
|
62
65
|
# Метод возвращает текстовую строку с прайс-листом в формате Яндекс.Маркет
|
63
66
|
#
|
64
67
|
# @return [String] строка с прайс-листом в формате utf-8
|
@@ -75,6 +78,7 @@ module YmlBuilder
|
|
75
78
|
add_header_footer(out)
|
76
79
|
end
|
77
80
|
|
81
|
+
|
78
82
|
# Метод для записи прайслиста в файл. Запись осущесствится в кодировке windows-1251
|
79
83
|
#
|
80
84
|
# @param [String] filename название файла для записи прайс-листа
|
@@ -83,25 +87,28 @@ module YmlBuilder
|
|
83
87
|
# price = YmlBuilder::Yml.new
|
84
88
|
# price.save('price.yml')
|
85
89
|
def save(filename)
|
86
|
-
File.open(filename, 'w:windows-1251') {|f| f.write(to_yml) }
|
90
|
+
File.open(filename, 'w:windows-1251') { |f| f.write(to_yml) }
|
87
91
|
end
|
88
92
|
|
93
|
+
|
89
94
|
private
|
90
95
|
|
91
|
-
def add_header_footer(text)
|
92
|
-
out = Array.new
|
93
|
-
out << "<?xml version=\"1.0\" encoding=\"windows-1251\"?>"
|
94
|
-
out << "<!DOCTYPE yml_catalog SYSTEM \"shops.dtd\">"
|
95
|
-
out << "<yml_catalog date=#{::Time.now.strftime("%Y-%m-%d %H:%M").inspect}>"
|
96
|
-
out << text
|
97
|
-
out << "</yml_catalog>"
|
98
|
-
out.join("\n")
|
99
|
-
end
|
100
96
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
97
|
+
def add_header_footer(text)
|
98
|
+
out = Array.new
|
99
|
+
out << "<?xml version=\"1.0\" encoding=\"windows-1251\"?>"
|
100
|
+
out << "<!DOCTYPE yml_catalog SYSTEM \"shops.dtd\">"
|
101
|
+
out << "<yml_catalog date=#{::Time.now.strftime("%Y-%m-%d %H:%M").inspect}>"
|
102
|
+
out << text
|
103
|
+
out << "</yml_catalog>"
|
104
|
+
out.join("\n")
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
def lds_to_yml(ident = 4)
|
109
|
+
return "" if @local_delivery_cost.nil?
|
110
|
+
' '.rjust(ident, ' ') + "<local_delivery_cost>#{@local_delivery_cost}</local_delivery_cost>\n"
|
111
|
+
end
|
105
112
|
|
106
113
|
end
|
107
114
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'yml_builder'
|
3
|
+
|
4
|
+
# Запрос URL
|
5
|
+
# У пользователя не отрабатывает генерация 60 тыс. товаров
|
6
|
+
# В ходе тестирования стало понятно, что огромная задержка происходит
|
7
|
+
# в функции to_yaml. Функция переписана вручную.
|
8
|
+
|
9
|
+
describe 'Пример 4 - Формирование выгрузки на 100 тыс. товаров' do
|
10
|
+
|
11
|
+
it 'Test' do
|
12
|
+
price = YmlBuilder::Yml.new
|
13
|
+
price.shop.name = 'Магазин ТЕСТ'
|
14
|
+
price.shop.company = "ООО 'Рога & Копыта'"
|
15
|
+
price.shop.url = 'http://example-site.ru'
|
16
|
+
price.shop.phone = '+7 (123) 456-7890'
|
17
|
+
price.shop.platform = 'OpenCart'
|
18
|
+
price.shop.version = '2.0'
|
19
|
+
price.currencies.rub = 1
|
20
|
+
price.currencies.usd = 55.04
|
21
|
+
price.currencies.eur = :cbrf
|
22
|
+
price.categories.add(id: 1, name: "Тестовая категория")
|
23
|
+
|
24
|
+
0.upto(100_000) do |tovar_id|
|
25
|
+
if tovar_id % 1000 == 0
|
26
|
+
puts "#{tovar_id}/100000"
|
27
|
+
end
|
28
|
+
|
29
|
+
item = YmlBuilder::Offer.new('simple')
|
30
|
+
item.id = tovar_id
|
31
|
+
item.available = [true, false].sample
|
32
|
+
item.currency_id = ['RUR', 'EUR'].sample
|
33
|
+
item.delivery =[true, false].sample
|
34
|
+
item.category_id = 1
|
35
|
+
item.name = "Товар #{tovar_id}"
|
36
|
+
item.url = "http://example-site.ru/items/#{tovar_id}"
|
37
|
+
item.price = Random.rand(300) + 100
|
38
|
+
item.add_picture("http://example-site.ru/#{tovar_id}/image1")
|
39
|
+
item.add_param(name: 'Обложка', value: 'Мягкая')
|
40
|
+
item.add_param(name: 'Страниц', value: 10, unit: 'шт.')
|
41
|
+
|
42
|
+
price.offers.add(item)
|
43
|
+
end
|
44
|
+
|
45
|
+
puts
|
46
|
+
puts "Добавление товаров завершено"
|
47
|
+
print "Фрагмент итоговой выгрузки... "
|
48
|
+
puts price.to_yml[1..1024]
|
49
|
+
puts price.stats.inspect
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
data/test/test_yml.yml
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yml_builder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stan Zhuravlev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-01-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -69,6 +69,7 @@ files:
|
|
69
69
|
- test/example_1_spec.rb
|
70
70
|
- test/example_2_spec.rb
|
71
71
|
- test/example_3_spec.rb
|
72
|
+
- test/example_4_huge_items_spec.rb
|
72
73
|
- test/example_full_spec.rb
|
73
74
|
- test/test_yml.yml
|
74
75
|
homepage: https://github.com/StanZhuravlev/yml_builder
|