openfoodfacts 0.4.1 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 83043dd2a373d7a71a92f5bd91dcb5d0bd9ad41f
4
- data.tar.gz: 8e593ecdbdba0f096d0bd51a4e6a34a94685f4f3
3
+ metadata.gz: 68fa8db761da44f61bc222db596a11b97f0b5e58
4
+ data.tar.gz: 44daa5950492034cc61e8eb6b9e4bc39d67d71b5
5
5
  SHA512:
6
- metadata.gz: 1b824b0ac2ace0129647140cd3d5d2e1a1c241f6636d2066d290dc385343ed5f0aff411f746a3bea84d9c14dc57c195ea07975ae76250a6d51bc801f69ec32e7
7
- data.tar.gz: 0442dea498913a0f52d49dcef4c19b6dac01361145bbf92907c96937e4dcac8aee001c8ebe59c4000e5cfa42e9db63819abd69e433de331a924d59fd64696706
6
+ metadata.gz: bde80ecfacd51c7726da778c78086625f9b5adcb118a6a47032ed8c376ebb4f62f73c5e2557e9f2e96d08d5b7512030ff62ccd0affc8f0e99b5e66510f32fd9b
7
+ data.tar.gz: c7ab2313f16df56770886a69cda9428d7392a33d0758e8f545e6b06b9fbbb0dd3f59321ac0e70e097cb5c1f8e9239d4e498064dc73b3c502f743c7ab92d12dcc
data/README.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # Open Food Facts
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/openfoodfacts.svg)](http://badge.fury.io/rb/openfoodfacts)
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
5
  [![Dependency Status](https://gemnasium.com/openfoodfacts/openfoodfacts-ruby.svg)](https://gemnasium.com/openfoodfacts/openfoodfacts-ruby)
6
6
  [![Code Climate](https://codeclimate.com/github/openfoodfacts/openfoodfacts-ruby/badges/gpa.svg)](https://codeclimate.com/github/openfoodfacts/openfoodfacts-ruby)
7
7
  [![Coverage Status](https://coveralls.io/repos/github/openfoodfacts/openfoodfacts-ruby/badge.svg?branch=master)](https://coveralls.io/github/openfoodfacts/openfoodfacts-ruby?branch=master)
8
- [![Documentation](http://inch-ci.org/github/openfoodfacts/openfoodfacts-ruby.svg?branch=master)](http://inch-ci.org/github/openfoodfacts/openfoodfacts-ruby)
8
+ [![Documentation](https://inch-ci.org/github/openfoodfacts/openfoodfacts-ruby.svg?branch=master)](https://inch-ci.org/github/openfoodfacts/openfoodfacts-ruby)
9
9
 
10
10
  API Wrapper for [Open Food Facts](https://openfoodfacts.org/), the open database about food.
11
11
 
@@ -35,11 +35,17 @@ All data is available for World, French, UK and US version for now. You should u
35
35
  - City
36
36
  - Contributor
37
37
  - Country
38
+ - EntryDate
38
39
  - Faq
39
40
  - IngredientThatMayBeFromPalmOil
40
41
  - Label
42
+ - LastEditDate
43
+ - Language
41
44
  - Locale
42
45
  - ManufacturingPlace
46
+ - Mission
47
+ - NumberOfIngredients
48
+ - NutritionGrade
43
49
  - Origin
44
50
  - PackagerCode
45
51
  - Packaging
@@ -4,11 +4,17 @@ require_relative 'openfoodfacts/category'
4
4
  require_relative 'openfoodfacts/city'
5
5
  require_relative 'openfoodfacts/contributor'
6
6
  require_relative 'openfoodfacts/country'
7
+ require_relative 'openfoodfacts/entry_date'
7
8
  require_relative 'openfoodfacts/faq'
8
9
  require_relative 'openfoodfacts/ingredient_that_may_be_from_palm_oil'
9
10
  require_relative 'openfoodfacts/label'
11
+ require_relative 'openfoodfacts/language'
12
+ require_relative 'openfoodfacts/last_edit_date'
10
13
  require_relative 'openfoodfacts/locale'
11
14
  require_relative 'openfoodfacts/manufacturing_place'
15
+ require_relative 'openfoodfacts/mission'
16
+ require_relative 'openfoodfacts/number_of_ingredients'
17
+ require_relative 'openfoodfacts/nutrition_grade'
12
18
  require_relative 'openfoodfacts/origin'
13
19
  require_relative 'openfoodfacts/packager_code'
14
20
  require_relative 'openfoodfacts/packaging'
@@ -0,0 +1,33 @@
1
+ require 'hashie'
2
+
3
+ module Openfoodfacts
4
+ class EntryDate < Hashie::Mash
5
+
6
+ # TODO: Add more locales
7
+ LOCALE_PATHS = {
8
+ 'fr' => 'dates-d-ajout',
9
+ 'uk' => 'entry-dates',
10
+ 'us' => 'entry-dates',
11
+ 'world' => 'entry-dates'
12
+ }
13
+
14
+ class << self
15
+
16
+ # Get entry dates
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
+
24
+ end
25
+
26
+ # Get products with entry date
27
+ #
28
+ def products(page: -1)
29
+ Product.from_website_page(url, page: page, products_count: products_count) if url
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ require 'hashie'
2
+
3
+ module Openfoodfacts
4
+ class Language < Hashie::Mash
5
+
6
+ # TODO: Add more locales
7
+ LOCALE_PATHS = {
8
+ 'fr' => 'langues',
9
+ 'uk' => 'languages',
10
+ 'us' => 'languages',
11
+ 'world' => 'languages'
12
+ }
13
+
14
+ class << self
15
+
16
+ # Get languages
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
+
24
+ end
25
+
26
+ # Get products with language
27
+ #
28
+ def products(page: -1)
29
+ Product.from_website_page(url, page: page, products_count: products_count) if url
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ require 'hashie'
2
+
3
+ module Openfoodfacts
4
+ class LastEditDate < Hashie::Mash
5
+
6
+ # TODO: Add more locales
7
+ LOCALE_PATHS = {
8
+ 'fr' => 'dates-de-derniere-modification',
9
+ 'uk' => 'last-edit-dates',
10
+ 'us' => 'last-edit-dates',
11
+ 'world' => 'last-edit-dates'
12
+ }
13
+
14
+ class << self
15
+
16
+ # Get last edit dates
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
+
24
+ end
25
+
26
+ # Get products with last edit date
27
+ #
28
+ def products(page: -1)
29
+ Product.from_website_page(url, page: page, products_count: products_count) if url
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,71 @@
1
+ require 'hashie'
2
+
3
+ module Openfoodfacts
4
+ class Mission < Hashie::Mash
5
+
6
+ # TODO: Add more locales
7
+ LOCALE_PATHS = {
8
+ 'fr' => 'missions',
9
+ 'uk' => 'missions',
10
+ 'us' => 'missions',
11
+ 'world' => 'missions'
12
+ }
13
+
14
+ class << self
15
+ def all(locale: DEFAULT_LOCALE, domain: DEFAULT_DOMAIN)
16
+ if path = LOCALE_PATHS[locale]
17
+ url = "https://#{locale}.#{domain}/#{path}"
18
+ html = open(url).read
19
+ dom = Nokogiri::HTML.fragment(html)
20
+
21
+ dom.css('#missions li').map do |mission_dom|
22
+ links = mission_dom.css('a')
23
+
24
+ attributes = {
25
+ "title" => links.first.text.strip,
26
+ "url" => URI.join(url, links.first.attr('href')).to_s,
27
+ "description" => mission_dom.css('div').first.children[2].text.gsub('→', '').strip,
28
+ "users_count" => links.last.text[/(\d+)/, 1].to_i
29
+ }
30
+
31
+ new(attributes)
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ # Fetch mission
38
+ #
39
+ def fetch
40
+ if (self.url)
41
+ html = open(self.url).read
42
+ dom = Nokogiri::HTML.fragment(html)
43
+
44
+ description = dom.css('#description').first
45
+
46
+ # Remove "All missions" link
47
+ users = dom.css('#main_column a')[0..-2].map do |user_link|
48
+ User.new(
49
+ "user_id" => user_link.text.strip,
50
+ "url" => URI.join(self.url, user_link.attr('href')).to_s,
51
+ )
52
+ end
53
+
54
+ mission = {
55
+ "title" => dom.css('h1').first.text.strip,
56
+ "description" => description.text.strip,
57
+ "description_long" => description.next.text.strip,
58
+
59
+ "users" => users,
60
+ "users_count" => users.count
61
+ }
62
+
63
+ self.merge!(mission)
64
+ end
65
+
66
+ self
67
+ end
68
+ alias_method :reload, :fetch
69
+
70
+ end
71
+ end
@@ -0,0 +1,33 @@
1
+ require 'hashie'
2
+
3
+ module Openfoodfacts
4
+ class NumberOfIngredients < Hashie::Mash
5
+
6
+ # TODO: Add more locales
7
+ LOCALE_PATHS = {
8
+ 'fr' => 'nombres-d-ingredients',
9
+ 'uk' => 'numbers-of-ingredients',
10
+ 'us' => 'numbers-of-ingredients',
11
+ 'world' => 'numbers-of-ingredients'
12
+ }
13
+
14
+ class << self
15
+
16
+ # Get last edit dates
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
+
24
+ end
25
+
26
+ # Get products with last edit date
27
+ #
28
+ def products(page: -1)
29
+ Product.from_website_page(url, page: page, products_count: products_count) if url
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ require 'hashie'
2
+
3
+ module Openfoodfacts
4
+ class NutritionGrade < Hashie::Mash
5
+
6
+ # TODO: Add more locales
7
+ LOCALE_PATHS = {
8
+ 'fr' => 'notes-nutritionnelles',
9
+ 'uk' => 'nutrition-grades',
10
+ 'us' => 'nutrition-grades',
11
+ 'world' => 'nutrition-grades'
12
+ }
13
+
14
+ class << self
15
+
16
+ # Get nutrition grades
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
+
24
+ end
25
+
26
+ # Get products with nutrition grade
27
+ #
28
+ def products(page: -1)
29
+ Product.from_website_page(url, page: page, products_count: products_count) if url
30
+ end
31
+
32
+ end
33
+ end
@@ -90,7 +90,7 @@ module Openfoodfacts
90
90
  if page == -1
91
91
  if products_count # Avoid one call
92
92
  pages_count = (products_count.to_f / 20).ceil
93
- (1..pages_count).map { |page| from_website_page(page_url, page: page) }.flatten
93
+ (1..pages_count).map { |page_i| from_website_page(page_url, page: page_i) }.flatten
94
94
  else
95
95
  products = []
96
96
 
@@ -6,7 +6,6 @@ module Openfoodfacts
6
6
  class << self
7
7
 
8
8
  # Login
9
- # WARNING SECURITY: It is not made throught HTTPS Secure so password can be read on the way.
10
9
  #
11
10
  def login(user_id, password, locale: DEFAULT_LOCALE, domain: DEFAULT_DOMAIN)
12
11
  path = 'cgi/session.pl'
@@ -1,3 +1,3 @@
1
1
  module Openfoodfacts
2
- VERSION = "0.4.1"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -121,7 +121,7 @@ class TestOpenfoodfacts < Minitest::Test
121
121
  def test_it_fetches_products_with_additive
122
122
  additive = ::Openfoodfacts::Additive.new("url" => "https://world.openfoodfacts.org/additive/e452i-sodium-polyphosphate")
123
123
  VCR.use_cassette("products_with_additive") do
124
- products_with_additive = additive.products(page: -1)
124
+ products_with_additive = additive.products(page: 1)
125
125
  refute_empty products_with_additive
126
126
  end
127
127
  end
@@ -145,11 +145,59 @@ class TestOpenfoodfacts < Minitest::Test
145
145
  def test_it_fetches_products_for_brand
146
146
  brand = ::Openfoodfacts::Brand.new("url" => "https://world.openfoodfacts.org/brand/bel")
147
147
  VCR.use_cassette("products_for_brand") do
148
- products_for_brand = brand.products(page: -1)
148
+ products_for_brand = brand.products(page: 1)
149
149
  refute_empty products_for_brand
150
150
  end
151
151
  end
152
152
 
153
+ # Nutrition Grades
154
+
155
+ def test_it_fetches_nutrition_grades
156
+ VCR.use_cassette("nutrition_grades") do
157
+ nutrition_grades = ::Openfoodfacts::NutritionGrade.all
158
+ assert_includes nutrition_grades.map { |nutrition_grade| nutrition_grade['name'] }, "Unknown"
159
+ end
160
+ end
161
+
162
+ def test_it_fetches_nutrition_grades_for_locale
163
+ VCR.use_cassette("nutrition_grades_locale") do
164
+ nutrition_grades = ::Openfoodfacts::NutritionGrade.all(locale: 'fr')
165
+ assert_includes nutrition_grades.map { |nutrition_grade| nutrition_grade['name'] }, "Inconnu"
166
+ end
167
+ end
168
+
169
+ def test_it_fetches_products_for_nutrition_grade
170
+ nutrition_grade = ::Openfoodfacts::NutritionGrade.new("url" => "https://world.openfoodfacts.org/nutrition-grade/c")
171
+ VCR.use_cassette("products_for_nutrition_grade") do
172
+ products_for_nutrition_grade = nutrition_grade.products(page: 1)
173
+ refute_empty products_for_nutrition_grade
174
+ end
175
+ end
176
+
177
+ # Languages
178
+
179
+ def test_it_fetches_languages
180
+ VCR.use_cassette("languages") do
181
+ languages = ::Openfoodfacts::Language.all
182
+ assert_includes languages.map { |language| language['name'] }, "French"
183
+ end
184
+ end
185
+
186
+ def test_it_fetches_languages_for_locale
187
+ VCR.use_cassette("languages_locale") do
188
+ languages = ::Openfoodfacts::Language.all(locale: 'fr')
189
+ assert_includes languages.map { |language| language['name'] }, "Anglais"
190
+ end
191
+ end
192
+
193
+ def test_it_fetches_products_for_language
194
+ language = ::Openfoodfacts::Language.new("url" => "https://world.openfoodfacts.org/language/french")
195
+ VCR.use_cassette("products_for_language") do
196
+ products_for_language = language.products(page: 1)
197
+ refute_empty products_for_language
198
+ end
199
+ end
200
+
153
201
  # Product states
154
202
 
155
203
  def test_it_fetches_product_states
@@ -169,11 +217,83 @@ class TestOpenfoodfacts < Minitest::Test
169
217
  def test_it_fetches_products_for_state
170
218
  product_state = ::Openfoodfacts::ProductState.new("url" => "https://world.openfoodfacts.org/state/photos-uploaded", "products_count" => 22)
171
219
  VCR.use_cassette("products_for_state") do
172
- products_for_state = product_state.products(page: -1)
220
+ products_for_state = product_state.products(page: 1)
173
221
  refute_empty products_for_state
174
222
  end
175
223
  end
176
224
 
225
+ # Entry date
226
+
227
+ def test_it_fetches_entry_dates
228
+ VCR.use_cassette("entry_dates") do
229
+ entry_dates = ::Openfoodfacts::EntryDate.all
230
+ assert_includes entry_dates.map { |entry_date| entry_date['name'] }, "2017-03-09"
231
+ end
232
+ end
233
+
234
+ def test_it_fetches_entry_dates_for_locale
235
+ VCR.use_cassette("entry_dates_locale") do
236
+ entry_dates = ::Openfoodfacts::EntryDate.all(locale: 'fr')
237
+ assert_includes entry_dates.map { |entry_date| entry_date['name'] }, "2017-03-09"
238
+ end
239
+ end
240
+
241
+ def test_it_fetches_products_for_entry_date
242
+ entry_date = ::Openfoodfacts::EntryDate.new("url" => "https://world.openfoodfacts.org/entry-date/2014-04-17")
243
+ VCR.use_cassette("products_for_entry_date") do
244
+ products_for_entry_date = entry_date.products(page: 1)
245
+ refute_empty products_for_entry_date
246
+ end
247
+ end
248
+
249
+ # Last edit date
250
+
251
+ def test_it_fetches_last_edit_dates
252
+ VCR.use_cassette("last_edit_dates") do
253
+ last_edit_dates = ::Openfoodfacts::LastEditDate.all
254
+ assert_includes last_edit_dates.map { |last_edit_date| last_edit_date['name'] }, "2017-03-23"
255
+ end
256
+ end
257
+
258
+ def test_it_fetches_last_edit_dates_for_locale
259
+ VCR.use_cassette("last_edit_dates_locale") do
260
+ last_edit_dates = ::Openfoodfacts::LastEditDate.all(locale: 'fr')
261
+ assert_includes last_edit_dates.map { |last_edit_date| last_edit_date['name'] }, "2017-03-23"
262
+ end
263
+ end
264
+
265
+ def test_it_fetches_products_for_last_edit_date
266
+ last_edit_date = ::Openfoodfacts::LastEditDate.new("url" => "https://world.openfoodfacts.org/last-edit-date/2013-11-11")
267
+ VCR.use_cassette("products_for_last_edit_date") do
268
+ products_for_last_edit_date = last_edit_date.products(page: 1)
269
+ refute_empty products_for_last_edit_date
270
+ end
271
+ end
272
+
273
+ # Number of Ingredients
274
+
275
+ def test_it_fetches_numbers_of_ingredients
276
+ VCR.use_cassette("numbers_of_ingredients") do
277
+ numbers_of_ingredients = ::Openfoodfacts::NumberOfIngredients.all
278
+ assert_includes numbers_of_ingredients.map { |number_of_ingredients| number_of_ingredients['name'] }, "38"
279
+ end
280
+ end
281
+
282
+ def test_it_fetches_numbers_of_ingredients_for_locale
283
+ VCR.use_cassette("number_of_ingredients_locale") do
284
+ numbers_of_ingredients = ::Openfoodfacts::NumberOfIngredients.all(locale: 'fr')
285
+ assert_includes numbers_of_ingredients.map { |number_of_ingredients| number_of_ingredients['name'] }, "38"
286
+ end
287
+ end
288
+
289
+ def test_it_fetches_products_for_number_of_ingredients
290
+ number_of_ingredients = ::Openfoodfacts::NumberOfIngredients.new("url" => "https://world.openfoodfacts.org/number-of-ingredients/38")
291
+ VCR.use_cassette("products_for_number_of_ingredients") do
292
+ products_for_number_of_ingredients = number_of_ingredients.products(page: 1)
293
+ refute_empty products_for_number_of_ingredients
294
+ end
295
+ end
296
+
177
297
  # FAQ
178
298
 
179
299
  def test_it_fetches_faq
@@ -182,6 +302,22 @@ class TestOpenfoodfacts < Minitest::Test
182
302
  end
183
303
  end
184
304
 
305
+ # Mission
306
+
307
+ def test_it_fetches_missions
308
+ VCR.use_cassette("missions") do
309
+ refute_empty ::Openfoodfacts::Mission.all(locale: 'fr')
310
+ end
311
+ end
312
+
313
+ def test_it_fetches_mission
314
+ VCR.use_cassette("mission", record: :once, match_requests_on: [:host, :path]) do
315
+ mission = ::Openfoodfacts::Mission.new(url: "https://fr.openfoodfacts.org/mission/informateur-100-produits")
316
+ mission.fetch
317
+ refute_empty mission.users
318
+ end
319
+ end
320
+
185
321
  # Press
186
322
 
187
323
  def test_it_fetches_press