openfoodfacts 0.6.2 → 0.10.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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +24 -3
  3. data/Rakefile +7 -5
  4. data/lib/openfoodfacts/additive.rb +9 -13
  5. data/lib/openfoodfacts/allergen.rb +4 -6
  6. data/lib/openfoodfacts/brand.rb +5 -7
  7. data/lib/openfoodfacts/category.rb +4 -6
  8. data/lib/openfoodfacts/city.rb +4 -6
  9. data/lib/openfoodfacts/contributor.rb +4 -6
  10. data/lib/openfoodfacts/country.rb +4 -6
  11. data/lib/openfoodfacts/entry_date.rb +5 -7
  12. data/lib/openfoodfacts/faq.rb +11 -16
  13. data/lib/openfoodfacts/ingredient.rb +31 -0
  14. data/lib/openfoodfacts/ingredient_that_may_be_from_palm_oil.rb +4 -6
  15. data/lib/openfoodfacts/label.rb +4 -6
  16. data/lib/openfoodfacts/language.rb +5 -7
  17. data/lib/openfoodfacts/last_edit_date.rb +5 -7
  18. data/lib/openfoodfacts/locale.rb +12 -14
  19. data/lib/openfoodfacts/manufacturing_place.rb +4 -6
  20. data/lib/openfoodfacts/mission.rb +20 -21
  21. data/lib/openfoodfacts/number_of_ingredients.rb +5 -7
  22. data/lib/openfoodfacts/nutrition_grade.rb +5 -7
  23. data/lib/openfoodfacts/origin.rb +4 -6
  24. data/lib/openfoodfacts/packager_code.rb +4 -6
  25. data/lib/openfoodfacts/packaging.rb +4 -6
  26. data/lib/openfoodfacts/period_after_opening.rb +31 -0
  27. data/lib/openfoodfacts/press.rb +16 -13
  28. data/lib/openfoodfacts/product.rb +132 -67
  29. data/lib/openfoodfacts/product_state.rb +5 -7
  30. data/lib/openfoodfacts/purchase_place.rb +4 -6
  31. data/lib/openfoodfacts/store.rb +4 -6
  32. data/lib/openfoodfacts/trace.rb +4 -6
  33. data/lib/openfoodfacts/user.rb +16 -15
  34. data/lib/openfoodfacts/version.rb +1 -1
  35. data/lib/openfoodfacts.rb +11 -2
  36. metadata +17 -18
  37. data/test/minitest_helper.rb +0 -18
  38. data/test/test_openfoodfacts.rb +0 -329
@@ -1,29 +1,27 @@
1
- require 'open-uri'
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/i18n/countries.pl?_type=query'
11
+ path = 'cgi/countries.pl'
14
12
  url = "https://#{GLOBAL}.#{domain}/#{path}"
15
- json = URI.open(url).read
13
+ json = Openfoodfacts.http_get(url).read
16
14
  hash = JSON.parse(json)
17
15
 
18
- hash.map { |pair|
16
+ hash.map do |pair|
19
17
  locale_from_pair(pair, domain: domain)
20
- }.compact
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[/^https?:\/\/([^.]+)\./i, 1]
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
- "name" => pair.last.strip,
36
- "code" => code,
37
- "url" => "https://#{code}.#{domain}"
38
- } if code
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 = URI.open(url).read
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
- "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
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 (self.url)
42
- html = URI.open(self.url).read
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
- "user_id" => user_link.text.strip,
51
- "url" => URI.join(self.url, user_link.attr('href')).to_s,
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
- "title" => dom.css('h1').first.text.strip,
57
- "description" => description.text.strip,
58
- "description_long" => description.next.text.strip,
56
+ 'title' => dom.css('h1').first.text.strip,
57
+ 'description' => description.text.strip,
58
+ 'description_long' => description.next.text.strip,
59
59
 
60
- "users" => users,
61
- "users_count" => users.count
60
+ 'users' => users,
61
+ 'users_count' => users.count
62
62
  }
63
63
 
64
- self.merge!(mission)
64
+ merge!(mission)
65
65
  end
66
66
 
67
67
  self
68
68
  end
69
- alias_method :reload, :fetch
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
@@ -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
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'hashie'
4
+
5
+ module Openfoodfacts
6
+ class PeriodAfterOpening < Hashie::Mash
7
+ # TODO: Add more locales
8
+ LOCALE_PATHS = {
9
+ 'fr' => 'durees-d-utilisation-apres-ouverture',
10
+ 'uk' => 'periods-after-opening',
11
+ 'us' => 'periods-after-opening',
12
+ 'world' => 'periods-after-opening'
13
+ }.freeze
14
+
15
+ class << self
16
+ # Get labels
17
+ #
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}")
21
+ end
22
+ end
23
+ end
24
+
25
+ # Get products with label
26
+ #
27
+ def products(page: -1)
28
+ Product.from_website_page(url, page: page, products_count: products_count) if url
29
+ end
30
+ end
31
+ end
@@ -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 = URI.open("https://#{locale}.#{domain}/#{path}").read
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, index|
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
- "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)
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