openfoodfacts 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +1 -0
- data/lib/openfoodfacts/faq.rb +1 -1
- data/lib/openfoodfacts/locale.rb +15 -12
- data/lib/openfoodfacts/mission.rb +3 -2
- data/lib/openfoodfacts/press.rb +14 -24
- data/lib/openfoodfacts/product.rb +6 -5
- data/lib/openfoodfacts/version.rb +1 -1
- data/test/minitest_helper.rb +7 -1
- data/test/test_openfoodfacts.rb +8 -6
- metadata +22 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8ee85e6766c13c0afa60c4800d43c99c85282f3544427d725cee0a97023631d9
|
4
|
+
data.tar.gz: 054c0a1972297b84f91b7c3d3d96006655d29f755f781800ec80808b297e840f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e9a7773561119e9b32f16677848dd28b54ce4c31f740d5a1f7b3f9592c6798d739d2815030bd507a4ed8df318f30f3fcaf06f26700f36dd26b67f45e2280099
|
7
|
+
data.tar.gz: d188187e2245d87ef1bd051485212f24bce554d7f9add603559617bea6353831535f21dcac65cc008b21492cf50ebdf0b3006359fcf531f7b0bd0ea3d51df5c5
|
data/README.md
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/openfoodfacts.svg)](https://badge.fury.io/rb/openfoodfacts)
|
4
4
|
[![Build Status](https://travis-ci.org/openfoodfacts/openfoodfacts-ruby.svg?branch=master)](https://travis-ci.org/openfoodfacts/openfoodfacts-ruby)
|
5
|
+
[![Build status](https://ci.appveyor.com/api/projects/status/tarhvc59fw478das/branch/master?svg=true)](https://ci.appveyor.com/project/nicolasleger/openfoodfacts-ruby/branch/master)
|
5
6
|
[![Dependency Status](https://gemnasium.com/openfoodfacts/openfoodfacts-ruby.svg)](https://gemnasium.com/openfoodfacts/openfoodfacts-ruby)
|
6
7
|
[![Code Climate](https://codeclimate.com/github/openfoodfacts/openfoodfacts-ruby/badges/gpa.svg)](https://codeclimate.com/github/openfoodfacts/openfoodfacts-ruby)
|
7
8
|
[![Coverage Status](https://coveralls.io/repos/github/openfoodfacts/openfoodfacts-ruby/badge.svg?branch=master)](https://coveralls.io/github/openfoodfacts/openfoodfacts-ruby?branch=master)
|
data/lib/openfoodfacts/faq.rb
CHANGED
@@ -16,7 +16,7 @@ module Openfoodfacts
|
|
16
16
|
class << self
|
17
17
|
def items(locale: DEFAULT_LOCALE, domain: DEFAULT_DOMAIN)
|
18
18
|
if path = LOCALE_PATHS[locale]
|
19
|
-
html = open("https://#{locale}.#{domain}/#{path}").read
|
19
|
+
html = URI.open("https://#{locale}.#{domain}/#{path}").read
|
20
20
|
dom = Nokogiri::HTML.fragment(html)
|
21
21
|
|
22
22
|
titles = dom.css('#main_column h2')
|
data/lib/openfoodfacts/locale.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
|
1
3
|
module Openfoodfacts
|
2
4
|
class Locale < String
|
3
5
|
|
@@ -8,12 +10,13 @@ module Openfoodfacts
|
|
8
10
|
# Get locales
|
9
11
|
#
|
10
12
|
def all(domain: DEFAULT_DOMAIN)
|
11
|
-
|
12
|
-
|
13
|
-
|
13
|
+
path = 'cgi/i18n/countries.pl?_type=query'
|
14
|
+
url = "https://#{GLOBAL}.#{domain}/#{path}"
|
15
|
+
json = URI.open(url).read
|
16
|
+
hash = JSON.parse(json)
|
14
17
|
|
15
|
-
|
16
|
-
|
18
|
+
hash.map { |pair|
|
19
|
+
locale_from_pair(pair, domain: domain)
|
17
20
|
}.compact
|
18
21
|
end
|
19
22
|
|
@@ -24,15 +27,15 @@ module Openfoodfacts
|
|
24
27
|
locale unless locale.nil? || locale == 'static'
|
25
28
|
end
|
26
29
|
|
27
|
-
# Return locale from
|
30
|
+
# Return locale from pair
|
28
31
|
#
|
29
|
-
def
|
30
|
-
|
32
|
+
def locale_from_pair(pair, domain: DEFAULT_DOMAIN)
|
33
|
+
code = pair.first
|
31
34
|
{
|
32
|
-
"name" =>
|
33
|
-
"code" =>
|
34
|
-
"url" => "https://#{
|
35
|
-
} if
|
35
|
+
"name" => pair.last.strip,
|
36
|
+
"code" => code,
|
37
|
+
"url" => "https://#{code}.#{domain}"
|
38
|
+
} if code
|
36
39
|
end
|
37
40
|
|
38
41
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'hashie'
|
2
|
+
require 'open-uri'
|
2
3
|
|
3
4
|
module Openfoodfacts
|
4
5
|
class Mission < Hashie::Mash
|
@@ -15,7 +16,7 @@ module Openfoodfacts
|
|
15
16
|
def all(locale: DEFAULT_LOCALE, domain: DEFAULT_DOMAIN)
|
16
17
|
if path = LOCALE_PATHS[locale]
|
17
18
|
url = "https://#{locale}.#{domain}/#{path}"
|
18
|
-
html = open(url).read
|
19
|
+
html = URI.open(url).read
|
19
20
|
dom = Nokogiri::HTML.fragment(html)
|
20
21
|
|
21
22
|
dom.css('#missions li').map do |mission_dom|
|
@@ -38,7 +39,7 @@ module Openfoodfacts
|
|
38
39
|
#
|
39
40
|
def fetch
|
40
41
|
if (self.url)
|
41
|
-
html = open(self.url).read
|
42
|
+
html = URI.open(self.url).read
|
42
43
|
dom = Nokogiri::HTML.fragment(html)
|
43
44
|
|
44
45
|
description = dom.css('#description').first
|
data/lib/openfoodfacts/press.rb
CHANGED
@@ -8,44 +8,34 @@ module Openfoodfacts
|
|
8
8
|
|
9
9
|
# TODO: Add more locales
|
10
10
|
LOCALE_PATHS = {
|
11
|
-
'fr' => 'presse'
|
12
|
-
'uk' => 'press',
|
13
|
-
'us' => 'press',
|
14
|
-
'world' => 'press'
|
11
|
+
'fr' => 'revue-de-presse-fr'
|
15
12
|
}
|
16
13
|
|
17
14
|
LOCALE_DATE_FORMATS = {
|
18
|
-
'fr' => '%d/%m/%Y'
|
19
|
-
'uk' => '%d/%m/%Y',
|
20
|
-
'us' => '%d/%m/%Y',
|
21
|
-
'world' => '%d/%m/%Y'
|
15
|
+
'fr' => '%d/%m/%Y'
|
22
16
|
}
|
23
17
|
|
24
18
|
class << self
|
25
|
-
def items(locale:
|
19
|
+
def items(locale: 'fr', domain: DEFAULT_DOMAIN)
|
26
20
|
if path = LOCALE_PATHS[locale]
|
27
|
-
|
21
|
+
date_format = LOCALE_DATE_FORMATS[locale]
|
22
|
+
|
23
|
+
html = URI.open("https://#{locale}.#{domain}/#{path}").read
|
28
24
|
dom = Nokogiri::HTML.fragment(html)
|
29
25
|
|
30
|
-
titles = dom.css('#
|
26
|
+
titles = dom.css('#press_table tbody tr')
|
31
27
|
titles.each_with_index.map do |item, index|
|
32
|
-
|
28
|
+
colums = item.css('td')
|
33
29
|
|
34
|
-
link =
|
30
|
+
link = colums[1].css('a')
|
35
31
|
attributes = {
|
36
|
-
"
|
37
|
-
"
|
32
|
+
"type" => colums[0].text,
|
33
|
+
"title" => colums[1].text.strip,
|
34
|
+
"url" => link && link.attr('href') && link.attr('href').value,
|
35
|
+
"source" => colums[2].text.strip,
|
36
|
+
"date" => (DateTime.strptime(colums[3].text, date_format) rescue nil)
|
38
37
|
}
|
39
38
|
|
40
|
-
last = Nokogiri::HTML.fragment(data.last)
|
41
|
-
if date_format = LOCALE_DATE_FORMATS[locale] and date = last.text.strip[/\d+\/\d+\/\d+\z/, 0]
|
42
|
-
attributes["date"] = DateTime.strptime(date, date_format)
|
43
|
-
end
|
44
|
-
|
45
|
-
if data.length >= 3
|
46
|
-
attributes["source"] = Nokogiri::HTML.fragment(data[-2]).text.strip
|
47
|
-
end
|
48
|
-
|
49
39
|
new(attributes)
|
50
40
|
end
|
51
41
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'cgi'
|
1
2
|
require 'hashie'
|
2
3
|
require 'net/http'
|
3
4
|
require 'nokogiri'
|
@@ -21,7 +22,7 @@ module Openfoodfacts
|
|
21
22
|
def get(code, locale: DEFAULT_LOCALE)
|
22
23
|
if code
|
23
24
|
product_url = url(code, locale: locale)
|
24
|
-
json = open(product_url).read
|
25
|
+
json = URI.open(product_url).read
|
25
26
|
hash = JSON.parse(json)
|
26
27
|
|
27
28
|
new(hash["product"]) if !hash["status"].nil? && hash["status"] == 1
|
@@ -44,7 +45,7 @@ module Openfoodfacts
|
|
44
45
|
terms = CGI.escape(terms)
|
45
46
|
path = "cgi/search.pl?search_terms=#{terms}&jqm=1&page=#{page}&page_size=#{page_size}&sort_by=#{sort_by}"
|
46
47
|
url = "https://#{locale}.#{domain}/#{path}"
|
47
|
-
json = open(url).read
|
48
|
+
json = URI.open(url).read
|
48
49
|
hash = JSON.parse(json)
|
49
50
|
html = hash["jqm"]
|
50
51
|
|
@@ -78,7 +79,7 @@ module Openfoodfacts
|
|
78
79
|
end
|
79
80
|
|
80
81
|
def from_jquery_mobile_list(jqm_html)
|
81
|
-
from_html_list(jqm_html, 'ul li:not(#loadmore)', /code=(\d+)\Z/i)
|
82
|
+
from_html_list(jqm_html, 'ul#search_results_list li:not(#loadmore)', /code=(\d+)\Z/i)
|
82
83
|
end
|
83
84
|
|
84
85
|
def from_website_list(html, locale: 'world')
|
@@ -104,13 +105,13 @@ module Openfoodfacts
|
|
104
105
|
products
|
105
106
|
end
|
106
107
|
else
|
107
|
-
html = open("#{page_url}/#{page}").read
|
108
|
+
html = URI.open("#{page_url}/#{page}").read
|
108
109
|
from_website_list(html, locale: Locale.locale_from_link(page_url))
|
109
110
|
end
|
110
111
|
end
|
111
112
|
|
112
113
|
def tags_from_page(_klass, page_url, &custom_tag_parsing)
|
113
|
-
html = open(page_url).read
|
114
|
+
html = URI.open(page_url).read
|
114
115
|
dom = Nokogiri::HTML.fragment(html)
|
115
116
|
|
116
117
|
dom.css('table#tagstable tbody tr').map do |tag|
|
data/test/minitest_helper.rb
CHANGED
@@ -6,7 +6,13 @@ require 'minitest/autorun'
|
|
6
6
|
require 'webmock/minitest'
|
7
7
|
require 'vcr'
|
8
8
|
|
9
|
+
# Avoid OpenSSL certificate verify failed error
|
10
|
+
if ENV.has_key?('APPVEYOR') && Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.4')
|
11
|
+
require 'openssl'
|
12
|
+
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
|
13
|
+
end
|
14
|
+
|
9
15
|
VCR.configure do |c|
|
10
16
|
c.cassette_library_dir = "test/fixtures"
|
11
17
|
c.hook_into :webmock
|
12
|
-
end
|
18
|
+
end
|
data/test/test_openfoodfacts.rb
CHANGED
@@ -103,8 +103,8 @@ class TestOpenfoodfacts < Minitest::Test
|
|
103
103
|
|
104
104
|
def test_it_fetches_additives
|
105
105
|
VCR.use_cassette("additives") do
|
106
|
-
additives = ::Openfoodfacts::Additive.all
|
107
|
-
|
106
|
+
additives = ::Openfoodfacts::Additive.all # World to have riskiness
|
107
|
+
assert_includes additives.map { |additive| additive['url'] }, "https://world.openfoodfacts.org/additive/e330-citric-acid"
|
108
108
|
refute_nil additives.detect { |additive| !additive['riskiness'].nil? }
|
109
109
|
end
|
110
110
|
end
|
@@ -112,7 +112,7 @@ class TestOpenfoodfacts < Minitest::Test
|
|
112
112
|
def test_it_fetches_additives_for_locale
|
113
113
|
VCR.use_cassette("additives_locale") do
|
114
114
|
additives = ::Openfoodfacts::Additive.all(locale: 'fr')
|
115
|
-
|
115
|
+
assert_includes additives.map { |additive| additive['url'] }, "https://fr.openfoodfacts.org/additif/e330-acide-citrique"
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
@@ -201,14 +201,14 @@ class TestOpenfoodfacts < Minitest::Test
|
|
201
201
|
def test_it_fetches_product_states
|
202
202
|
VCR.use_cassette("product_states") do
|
203
203
|
product_states = ::Openfoodfacts::ProductState.all
|
204
|
-
assert_equal "https://world.openfoodfacts.org/state/
|
204
|
+
assert_equal "https://world.openfoodfacts.org/state/front-photo-not-selected", product_states.last.url
|
205
205
|
end
|
206
206
|
end
|
207
207
|
|
208
208
|
def test_it_fetches_product_states_for_locale
|
209
209
|
VCR.use_cassette("product_states_locale") do
|
210
210
|
product_states = ::Openfoodfacts::ProductState.all(locale: 'fr')
|
211
|
-
assert_equal "https://fr.openfoodfacts.org/etat/
|
211
|
+
assert_equal "https://fr.openfoodfacts.org/etat/en:front-photo-not-selected", product_states.last.url
|
212
212
|
end
|
213
213
|
end
|
214
214
|
|
@@ -261,7 +261,7 @@ class TestOpenfoodfacts < Minitest::Test
|
|
261
261
|
end
|
262
262
|
|
263
263
|
def test_it_fetches_products_for_last_edit_date
|
264
|
-
last_edit_date = ::Openfoodfacts::LastEditDate.new("url" => "https://world.openfoodfacts.org/last-edit-date/
|
264
|
+
last_edit_date = ::Openfoodfacts::LastEditDate.new("url" => "https://world.openfoodfacts.org/last-edit-date/2020-04")
|
265
265
|
VCR.use_cassette("products_for_last_edit_date") do
|
266
266
|
products_for_last_edit_date = last_edit_date.products(page: 1)
|
267
267
|
refute_empty products_for_last_edit_date
|
@@ -304,12 +304,14 @@ class TestOpenfoodfacts < Minitest::Test
|
|
304
304
|
|
305
305
|
def test_it_fetches_missions
|
306
306
|
VCR.use_cassette("missions") do
|
307
|
+
skip("Website have a bug with Missions page on https://fr.openfoodfacts.org/missions")
|
307
308
|
refute_empty ::Openfoodfacts::Mission.all(locale: 'fr')
|
308
309
|
end
|
309
310
|
end
|
310
311
|
|
311
312
|
def test_it_fetches_mission
|
312
313
|
VCR.use_cassette("mission", record: :once, match_requests_on: [:host, :path]) do
|
314
|
+
skip("Website have a bug with Mission page on https://fr.openfoodfacts.org/mission/informateur-100-produits")
|
313
315
|
mission = ::Openfoodfacts::Mission.new(url: "https://fr.openfoodfacts.org/mission/informateur-100-produits")
|
314
316
|
mission.fetch
|
315
317
|
refute_empty mission.users
|
metadata
CHANGED
@@ -1,29 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openfoodfacts
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nicolas Leger
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-12-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hashie
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '3.4'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '5.0'
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
|
-
- - "
|
27
|
+
- - ">="
|
25
28
|
- !ruby/object:Gem::Version
|
26
29
|
version: '3.4'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '5.0'
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
34
|
name: nokogiri
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -44,14 +50,14 @@ dependencies:
|
|
44
50
|
requirements:
|
45
51
|
- - "~>"
|
46
52
|
- !ruby/object:Gem::Version
|
47
|
-
version: '1
|
53
|
+
version: '2.1'
|
48
54
|
type: :development
|
49
55
|
prerelease: false
|
50
56
|
version_requirements: !ruby/object:Gem::Requirement
|
51
57
|
requirements:
|
52
58
|
- - "~>"
|
53
59
|
- !ruby/object:Gem::Version
|
54
|
-
version: '1
|
60
|
+
version: '2.1'
|
55
61
|
- !ruby/object:Gem::Dependency
|
56
62
|
name: rake
|
57
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -86,31 +92,31 @@ dependencies:
|
|
86
92
|
requirements:
|
87
93
|
- - "~>"
|
88
94
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
95
|
+
version: '5.1'
|
90
96
|
type: :development
|
91
97
|
prerelease: false
|
92
98
|
version_requirements: !ruby/object:Gem::Requirement
|
93
99
|
requirements:
|
94
100
|
- - "~>"
|
95
101
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
102
|
+
version: '5.1'
|
97
103
|
- !ruby/object:Gem::Dependency
|
98
104
|
name: webmock
|
99
105
|
requirement: !ruby/object:Gem::Requirement
|
100
106
|
requirements:
|
101
107
|
- - "~>"
|
102
108
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
109
|
+
version: '3.11'
|
104
110
|
type: :development
|
105
111
|
prerelease: false
|
106
112
|
version_requirements: !ruby/object:Gem::Requirement
|
107
113
|
requirements:
|
108
114
|
- - "~>"
|
109
115
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
116
|
+
version: '3.11'
|
111
117
|
description: Open Food Facts API Wrapper, the open database about food.
|
112
118
|
email:
|
113
|
-
-
|
119
|
+
- opensource@nleger.com
|
114
120
|
executables: []
|
115
121
|
extensions: []
|
116
122
|
extra_rdoc_files: []
|
@@ -154,7 +160,7 @@ homepage: https://github.com/openfoodfacts/openfoodfacts-ruby
|
|
154
160
|
licenses:
|
155
161
|
- MIT
|
156
162
|
metadata: {}
|
157
|
-
post_install_message:
|
163
|
+
post_install_message:
|
158
164
|
rdoc_options: []
|
159
165
|
require_paths:
|
160
166
|
- lib
|
@@ -162,16 +168,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
162
168
|
requirements:
|
163
169
|
- - ">="
|
164
170
|
- !ruby/object:Gem::Version
|
165
|
-
version: '2.
|
171
|
+
version: '2.5'
|
166
172
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
167
173
|
requirements:
|
168
174
|
- - ">="
|
169
175
|
- !ruby/object:Gem::Version
|
170
176
|
version: '0'
|
171
177
|
requirements: []
|
172
|
-
|
173
|
-
|
174
|
-
signing_key:
|
178
|
+
rubygems_version: 3.2.3
|
179
|
+
signing_key:
|
175
180
|
specification_version: 4
|
176
181
|
summary: Open Food Facts API Wrapper
|
177
182
|
test_files: []
|