openfoodfacts 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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