openfoodfacts 0.6.2 → 0.9.0
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/README.md +24 -3
- data/Rakefile +7 -5
- data/lib/openfoodfacts/additive.rb +9 -13
- data/lib/openfoodfacts/allergen.rb +4 -6
- data/lib/openfoodfacts/brand.rb +5 -7
- data/lib/openfoodfacts/category.rb +4 -6
- data/lib/openfoodfacts/city.rb +4 -6
- data/lib/openfoodfacts/contributor.rb +4 -6
- data/lib/openfoodfacts/country.rb +4 -6
- data/lib/openfoodfacts/entry_date.rb +5 -7
- data/lib/openfoodfacts/faq.rb +11 -16
- data/lib/openfoodfacts/ingredient_that_may_be_from_palm_oil.rb +4 -6
- data/lib/openfoodfacts/label.rb +4 -6
- data/lib/openfoodfacts/language.rb +5 -7
- data/lib/openfoodfacts/last_edit_date.rb +5 -7
- data/lib/openfoodfacts/locale.rb +12 -14
- data/lib/openfoodfacts/manufacturing_place.rb +4 -6
- data/lib/openfoodfacts/mission.rb +20 -21
- data/lib/openfoodfacts/number_of_ingredients.rb +5 -7
- data/lib/openfoodfacts/nutrition_grade.rb +5 -7
- data/lib/openfoodfacts/origin.rb +4 -6
- data/lib/openfoodfacts/packager_code.rb +4 -6
- data/lib/openfoodfacts/packaging.rb +4 -6
- data/lib/openfoodfacts/press.rb +16 -13
- data/lib/openfoodfacts/product.rb +132 -67
- data/lib/openfoodfacts/product_state.rb +5 -7
- data/lib/openfoodfacts/purchase_place.rb +4 -6
- data/lib/openfoodfacts/store.rb +4 -6
- data/lib/openfoodfacts/trace.rb +4 -6
- data/lib/openfoodfacts/user.rb +16 -15
- data/lib/openfoodfacts/version.rb +3 -1
- data/lib/openfoodfacts.rb +9 -2
- metadata +15 -18
- data/test/minitest_helper.rb +0 -18
- data/test/test_openfoodfacts.rb +0 -329
data/lib/openfoodfacts/locale.rb
CHANGED
@@ -1,29 +1,27 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Openfoodfacts
|
4
4
|
class Locale < String
|
5
|
-
|
6
5
|
GLOBAL = 'world'
|
7
6
|
|
8
7
|
class << self
|
9
|
-
|
10
8
|
# Get locales
|
11
9
|
#
|
12
10
|
def all(domain: DEFAULT_DOMAIN)
|
13
|
-
path = 'cgi/
|
11
|
+
path = 'cgi/countries.pl'
|
14
12
|
url = "https://#{GLOBAL}.#{domain}/#{path}"
|
15
|
-
json =
|
13
|
+
json = Openfoodfacts.http_get(url).read
|
16
14
|
hash = JSON.parse(json)
|
17
15
|
|
18
|
-
hash.map
|
16
|
+
hash.map do |pair|
|
19
17
|
locale_from_pair(pair, domain: domain)
|
20
|
-
|
18
|
+
end.compact
|
21
19
|
end
|
22
20
|
|
23
21
|
# Return locale from link
|
24
22
|
#
|
25
23
|
def locale_from_link(link)
|
26
|
-
locale = link[
|
24
|
+
locale = link[%r{^https?://([^.]+)\.}i, 1]
|
27
25
|
locale unless locale.nil? || locale == 'static'
|
28
26
|
end
|
29
27
|
|
@@ -31,14 +29,14 @@ module Openfoodfacts
|
|
31
29
|
#
|
32
30
|
def locale_from_pair(pair, domain: DEFAULT_DOMAIN)
|
33
31
|
code = pair.first
|
32
|
+
return unless code
|
33
|
+
|
34
34
|
{
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
}
|
35
|
+
'name' => pair.last.strip,
|
36
|
+
'code' => code,
|
37
|
+
'url' => "https://#{code}.#{domain}"
|
38
|
+
}
|
39
39
|
end
|
40
|
-
|
41
40
|
end
|
42
|
-
|
43
41
|
end
|
44
42
|
end
|
@@ -1,26 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'hashie'
|
2
4
|
|
3
5
|
module Openfoodfacts
|
4
6
|
class ManufacturingPlace < Hashie::Mash
|
5
|
-
|
6
7
|
# TODO: Add more locales
|
7
8
|
LOCALE_PATHS = {
|
8
9
|
'fr' => 'lieux-de-fabrication',
|
9
10
|
'uk' => 'manufacturing-places',
|
10
11
|
'us' => 'manufacturing-places',
|
11
12
|
'world' => 'manufacturing-places'
|
12
|
-
}
|
13
|
+
}.freeze
|
13
14
|
|
14
15
|
class << self
|
15
|
-
|
16
16
|
# Get manufacturing places
|
17
17
|
#
|
18
18
|
def all(locale: DEFAULT_LOCALE, domain: DEFAULT_DOMAIN)
|
19
|
-
if path = LOCALE_PATHS[locale]
|
19
|
+
if (path = LOCALE_PATHS[locale])
|
20
20
|
Product.tags_from_page(self, "https://#{locale}.#{domain}/#{path}")
|
21
21
|
end
|
22
22
|
end
|
23
|
-
|
24
23
|
end
|
25
24
|
|
26
25
|
# Get products from manufacturing place
|
@@ -28,6 +27,5 @@ module Openfoodfacts
|
|
28
27
|
def products(page: -1)
|
29
28
|
Product.from_website_page(url, page: page, products_count: products_count) if url
|
30
29
|
end
|
31
|
-
|
32
30
|
end
|
33
31
|
end
|
@@ -1,32 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'hashie'
|
2
|
-
require 'open-uri'
|
3
4
|
|
4
5
|
module Openfoodfacts
|
5
6
|
class Mission < Hashie::Mash
|
6
|
-
|
7
7
|
# TODO: Add more locales
|
8
8
|
LOCALE_PATHS = {
|
9
9
|
'fr' => 'missions',
|
10
10
|
'uk' => 'missions',
|
11
11
|
'us' => 'missions',
|
12
12
|
'world' => 'missions'
|
13
|
-
}
|
13
|
+
}.freeze
|
14
14
|
|
15
15
|
class << self
|
16
16
|
def all(locale: DEFAULT_LOCALE, domain: DEFAULT_DOMAIN)
|
17
|
-
if path = LOCALE_PATHS[locale]
|
17
|
+
if (path = LOCALE_PATHS[locale])
|
18
18
|
url = "https://#{locale}.#{domain}/#{path}"
|
19
|
-
html =
|
19
|
+
html = Openfoodfacts.http_get(url).read
|
20
20
|
dom = Nokogiri::HTML.fragment(html)
|
21
21
|
|
22
22
|
dom.css('#missions li').map do |mission_dom|
|
23
23
|
links = mission_dom.css('a')
|
24
24
|
|
25
25
|
attributes = {
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
'title' => links.first.text.strip,
|
27
|
+
'url' => URI.join(url, links.first.attr('href')).to_s,
|
28
|
+
'description' => mission_dom.css('div').first.children[2].text.gsub('→', '').strip,
|
29
|
+
'users_count' => links.last.text[/(\d+)/, 1].to_i
|
30
30
|
}
|
31
31
|
|
32
32
|
new(attributes)
|
@@ -38,8 +38,8 @@ module Openfoodfacts
|
|
38
38
|
# Fetch mission
|
39
39
|
#
|
40
40
|
def fetch
|
41
|
-
if
|
42
|
-
html =
|
41
|
+
if url
|
42
|
+
html = Openfoodfacts.http_get(url).read
|
43
43
|
dom = Nokogiri::HTML.fragment(html)
|
44
44
|
|
45
45
|
description = dom.css('#description').first
|
@@ -47,26 +47,25 @@ module Openfoodfacts
|
|
47
47
|
# Remove "All missions" link
|
48
48
|
users = dom.css('#main_column a')[0..-2].map do |user_link|
|
49
49
|
User.new(
|
50
|
-
|
51
|
-
|
50
|
+
'user_id' => user_link.text.strip,
|
51
|
+
'url' => URI.join(url, user_link.attr('href')).to_s
|
52
52
|
)
|
53
53
|
end
|
54
54
|
|
55
55
|
mission = {
|
56
|
-
|
57
|
-
|
58
|
-
|
56
|
+
'title' => dom.css('h1').first.text.strip,
|
57
|
+
'description' => description.text.strip,
|
58
|
+
'description_long' => description.next.text.strip,
|
59
59
|
|
60
|
-
|
61
|
-
|
60
|
+
'users' => users,
|
61
|
+
'users_count' => users.count
|
62
62
|
}
|
63
63
|
|
64
|
-
|
64
|
+
merge!(mission)
|
65
65
|
end
|
66
66
|
|
67
67
|
self
|
68
68
|
end
|
69
|
-
|
70
|
-
|
69
|
+
alias reload fetch
|
71
70
|
end
|
72
71
|
end
|
@@ -1,26 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'hashie'
|
2
4
|
|
3
5
|
module Openfoodfacts
|
4
6
|
class NumberOfIngredients < Hashie::Mash
|
5
|
-
|
6
7
|
# TODO: Add more locales
|
7
8
|
LOCALE_PATHS = {
|
8
9
|
'fr' => 'nombres-d-ingredients',
|
9
10
|
'uk' => 'numbers-of-ingredients',
|
10
11
|
'us' => 'numbers-of-ingredients',
|
11
12
|
'world' => 'numbers-of-ingredients'
|
12
|
-
}
|
13
|
+
}.freeze
|
13
14
|
|
14
15
|
class << self
|
15
|
-
|
16
16
|
# Get last edit dates
|
17
17
|
#
|
18
18
|
def all(locale: DEFAULT_LOCALE, domain: DEFAULT_DOMAIN)
|
19
|
-
if path = LOCALE_PATHS[locale]
|
20
|
-
Product.tags_from_page(self, "https://#{locale}.#{domain}/#{path}")
|
19
|
+
if (path = LOCALE_PATHS[locale])
|
20
|
+
Product.tags_from_page(self, "https://#{locale}.#{domain}/facets/#{path}")
|
21
21
|
end
|
22
22
|
end
|
23
|
-
|
24
23
|
end
|
25
24
|
|
26
25
|
# Get products with last edit date
|
@@ -28,6 +27,5 @@ module Openfoodfacts
|
|
28
27
|
def products(page: -1)
|
29
28
|
Product.from_website_page(url, page: page, products_count: products_count) if url
|
30
29
|
end
|
31
|
-
|
32
30
|
end
|
33
31
|
end
|
@@ -1,26 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'hashie'
|
2
4
|
|
3
5
|
module Openfoodfacts
|
4
6
|
class NutritionGrade < Hashie::Mash
|
5
|
-
|
6
7
|
# TODO: Add more locales
|
7
8
|
LOCALE_PATHS = {
|
8
9
|
'fr' => 'notes-nutritionnelles',
|
9
10
|
'uk' => 'nutrition-grades',
|
10
11
|
'us' => 'nutrition-grades',
|
11
12
|
'world' => 'nutrition-grades'
|
12
|
-
}
|
13
|
+
}.freeze
|
13
14
|
|
14
15
|
class << self
|
15
|
-
|
16
16
|
# Get nutrition grades
|
17
17
|
#
|
18
18
|
def all(locale: DEFAULT_LOCALE, domain: DEFAULT_DOMAIN)
|
19
|
-
if path = LOCALE_PATHS[locale]
|
20
|
-
Product.tags_from_page(self, "https://#{locale}.#{domain}/#{path}")
|
19
|
+
if (path = LOCALE_PATHS[locale])
|
20
|
+
Product.tags_from_page(self, "https://#{locale}.#{domain}/facets/#{path}")
|
21
21
|
end
|
22
22
|
end
|
23
|
-
|
24
23
|
end
|
25
24
|
|
26
25
|
# Get products with nutrition grade
|
@@ -28,6 +27,5 @@ module Openfoodfacts
|
|
28
27
|
def products(page: -1)
|
29
28
|
Product.from_website_page(url, page: page, products_count: products_count) if url
|
30
29
|
end
|
31
|
-
|
32
30
|
end
|
33
31
|
end
|
data/lib/openfoodfacts/origin.rb
CHANGED
@@ -1,26 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'hashie'
|
2
4
|
|
3
5
|
module Openfoodfacts
|
4
6
|
class Origin < Hashie::Mash
|
5
|
-
|
6
7
|
# TODO: Add more locales
|
7
8
|
LOCALE_PATHS = {
|
8
9
|
'fr' => 'origines',
|
9
10
|
'uk' => 'origins',
|
10
11
|
'us' => 'origins',
|
11
12
|
'world' => 'origins'
|
12
|
-
}
|
13
|
+
}.freeze
|
13
14
|
|
14
15
|
class << self
|
15
|
-
|
16
16
|
# Get origins
|
17
17
|
#
|
18
18
|
def all(locale: DEFAULT_LOCALE, domain: DEFAULT_DOMAIN)
|
19
|
-
if path = LOCALE_PATHS[locale]
|
19
|
+
if (path = LOCALE_PATHS[locale])
|
20
20
|
Product.tags_from_page(self, "https://#{locale}.#{domain}/#{path}")
|
21
21
|
end
|
22
22
|
end
|
23
|
-
|
24
23
|
end
|
25
24
|
|
26
25
|
# Get products with origin
|
@@ -28,6 +27,5 @@ module Openfoodfacts
|
|
28
27
|
def products(page: -1)
|
29
28
|
Product.from_website_page(url, page: page, products_count: products_count) if url
|
30
29
|
end
|
31
|
-
|
32
30
|
end
|
33
31
|
end
|
@@ -1,26 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'hashie'
|
2
4
|
|
3
5
|
module Openfoodfacts
|
4
6
|
class PackagerCode < Hashie::Mash
|
5
|
-
|
6
7
|
# TODO: Add more locales
|
7
8
|
LOCALE_PATHS = {
|
8
9
|
'fr' => 'codes-emballeurs',
|
9
10
|
'uk' => 'packager-codes',
|
10
11
|
'us' => 'packager-codes',
|
11
12
|
'world' => 'packager-codes'
|
12
|
-
}
|
13
|
+
}.freeze
|
13
14
|
|
14
15
|
class << self
|
15
|
-
|
16
16
|
# Get packager codes
|
17
17
|
#
|
18
18
|
def all(locale: DEFAULT_LOCALE, domain: DEFAULT_DOMAIN)
|
19
|
-
if path = LOCALE_PATHS[locale]
|
19
|
+
if (path = LOCALE_PATHS[locale])
|
20
20
|
Product.tags_from_page(self, "https://#{locale}.#{domain}/#{path}")
|
21
21
|
end
|
22
22
|
end
|
23
|
-
|
24
23
|
end
|
25
24
|
|
26
25
|
# Get products with packager code
|
@@ -28,6 +27,5 @@ module Openfoodfacts
|
|
28
27
|
def products(page: -1)
|
29
28
|
Product.from_website_page(url, page: page, products_count: products_count) if url
|
30
29
|
end
|
31
|
-
|
32
30
|
end
|
33
31
|
end
|
@@ -1,26 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'hashie'
|
2
4
|
|
3
5
|
module Openfoodfacts
|
4
6
|
class Packaging < Hashie::Mash
|
5
|
-
|
6
7
|
# TODO: Add more locales
|
7
8
|
LOCALE_PATHS = {
|
8
9
|
'fr' => 'conditionnements',
|
9
10
|
'uk' => 'packaging',
|
10
11
|
'us' => 'packaging',
|
11
12
|
'world' => 'packaging'
|
12
|
-
}
|
13
|
+
}.freeze
|
13
14
|
|
14
15
|
class << self
|
15
|
-
|
16
16
|
# Get packagings
|
17
17
|
#
|
18
18
|
def all(locale: DEFAULT_LOCALE, domain: DEFAULT_DOMAIN)
|
19
|
-
if path = LOCALE_PATHS[locale]
|
19
|
+
if (path = LOCALE_PATHS[locale])
|
20
20
|
Product.tags_from_page(self, "https://#{locale}.#{domain}/#{path}")
|
21
21
|
end
|
22
22
|
end
|
23
|
-
|
24
23
|
end
|
25
24
|
|
26
25
|
# Get products with packaging
|
@@ -28,6 +27,5 @@ module Openfoodfacts
|
|
28
27
|
def products(page: -1)
|
29
28
|
Product.from_website_page(url, page: page, products_count: products_count) if url
|
30
29
|
end
|
31
|
-
|
32
30
|
end
|
33
31
|
end
|
data/lib/openfoodfacts/press.rb
CHANGED
@@ -1,39 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'hashie'
|
2
4
|
require 'nokogiri'
|
3
|
-
require 'open-uri'
|
4
5
|
require 'time'
|
5
6
|
|
6
7
|
module Openfoodfacts
|
7
8
|
class Press < Hashie::Mash
|
8
|
-
|
9
9
|
# TODO: Add more locales
|
10
10
|
LOCALE_PATHS = {
|
11
11
|
'fr' => 'revue-de-presse-fr'
|
12
|
-
}
|
12
|
+
}.freeze
|
13
13
|
|
14
14
|
LOCALE_DATE_FORMATS = {
|
15
15
|
'fr' => '%d/%m/%Y'
|
16
|
-
}
|
16
|
+
}.freeze
|
17
17
|
|
18
18
|
class << self
|
19
19
|
def items(locale: 'fr', domain: DEFAULT_DOMAIN)
|
20
|
-
if path = LOCALE_PATHS[locale]
|
20
|
+
if (path = LOCALE_PATHS[locale])
|
21
21
|
date_format = LOCALE_DATE_FORMATS[locale]
|
22
22
|
|
23
|
-
html =
|
23
|
+
html = Openfoodfacts.http_get("https://#{locale}.#{domain}/#{path}").read
|
24
24
|
dom = Nokogiri::HTML.fragment(html)
|
25
25
|
|
26
26
|
titles = dom.css('#press_table tbody tr')
|
27
|
-
titles.each_with_index.map do |item,
|
27
|
+
titles.each_with_index.map do |item, _index|
|
28
28
|
colums = item.css('td')
|
29
29
|
|
30
30
|
link = colums[1].css('a')
|
31
31
|
attributes = {
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
32
|
+
'type' => colums[0].text,
|
33
|
+
'title' => colums[1].text.strip,
|
34
|
+
'url' => link&.attr('href')&.value,
|
35
|
+
'source' => colums[2].text.strip,
|
36
|
+
'date' => begin
|
37
|
+
DateTime.strptime(colums[3].text, date_format)
|
38
|
+
rescue StandardError
|
39
|
+
nil
|
40
|
+
end
|
37
41
|
}
|
38
42
|
|
39
43
|
new(attributes)
|
@@ -41,6 +45,5 @@ module Openfoodfacts
|
|
41
45
|
end
|
42
46
|
end
|
43
47
|
end
|
44
|
-
|
45
48
|
end
|
46
49
|
end
|