yml_builder 0.1.3 → 0.1.4
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.
- 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
|