shopli 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 99ca4e3245d6953d6d110daff6ef93d351206645
4
+ data.tar.gz: 295de735a0669259ab46b20b70e4d4f85e31aed5
5
+ SHA512:
6
+ metadata.gz: 8848f63c961791887f46ce62e47859385a6122011c95fc5a4f4e11a5fc3a05a51edcd0458f8790e85b733562343355710d67838a05b93ff170ab4d89c336ff46
7
+ data.tar.gz: e9825e439ac413a3b714e2ffd8432aede793cd07664379d6de4b9ba54471578c58592eccffe78570ac675977bcaefb704441005a47c101fa3989546734642218
@@ -0,0 +1,21 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ InstalledFiles
7
+ _yardoc
8
+ coverage
9
+ doc/
10
+ lib/bundler/man
11
+ pkg
12
+ rdoc
13
+ spec/reports
14
+ test/tmp
15
+ test/version_tmp
16
+ tmp
17
+ *.bundle
18
+ *.so
19
+ *.o
20
+ *.a
21
+ mkmf.log
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ script: bundle exec rspec spec
3
+ rvm:
4
+ - 2.0.0
5
+ - 2.1.0
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in shopli.gemspec
4
+ gemspec
5
+
6
+ gem 'libdevinput', :git => 'https://github.com/kamaradclimber/libdevinput.git'
@@ -0,0 +1,56 @@
1
+ GIT
2
+ remote: https://github.com/kamaradclimber/libdevinput.git
3
+ revision: 2b5a4df98eef7d794fe44d4e98742c5bb6d32631
4
+ specs:
5
+ libdevinput (0.0.2)
6
+
7
+ PATH
8
+ remote: .
9
+ specs:
10
+ shopli (0.0.1)
11
+ rest-client
12
+
13
+ GEM
14
+ remote: https://rubygems.org/
15
+ specs:
16
+ coveralls (0.7.0)
17
+ multi_json (~> 1.3)
18
+ rest-client
19
+ simplecov (>= 0.7)
20
+ term-ansicolor
21
+ thor
22
+ diff-lcs (1.2.5)
23
+ docile (1.1.3)
24
+ mime-types (2.1)
25
+ multi_json (1.9.0)
26
+ rake (10.3.1)
27
+ rest-client (1.6.7)
28
+ mime-types (>= 1.16)
29
+ rspec (2.14.1)
30
+ rspec-core (~> 2.14.0)
31
+ rspec-expectations (~> 2.14.0)
32
+ rspec-mocks (~> 2.14.0)
33
+ rspec-core (2.14.8)
34
+ rspec-expectations (2.14.5)
35
+ diff-lcs (>= 1.1.3, < 2.0)
36
+ rspec-mocks (2.14.6)
37
+ simplecov (0.8.2)
38
+ docile (~> 1.1.0)
39
+ multi_json
40
+ simplecov-html (~> 0.8.0)
41
+ simplecov-html (0.8.0)
42
+ term-ansicolor (1.3.0)
43
+ tins (~> 1.0)
44
+ thor (0.18.1)
45
+ tins (1.0.0)
46
+
47
+ PLATFORMS
48
+ ruby
49
+
50
+ DEPENDENCIES
51
+ bundler (~> 1.6)
52
+ coveralls
53
+ libdevinput!
54
+ rake
55
+ rspec
56
+ shopli!
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Gregoire Seux
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,34 @@
1
+ # Shopli
2
+
3
+ [![Build Status](https://travis-ci.org/kamaradclimber/shopli.png?branch=master)](https://travis-ci.org/kamaradclimber/shopli)
4
+ [![Gem Version](https://badge.fury.io/rb/shopli.png)](http://badge.fury.io/rb/shopli)
5
+ [![Coverage Status](https://coveralls.io/repos/kamaradclimber/shopli/badge.png)](https://coveralls.io/r/kamaradclimber/shopli)
6
+
7
+ Using a barcode reader, scan all item you put in the trash.
8
+ Shopli will use that list of barcodes and generate a shopping list.
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ gem 'shopli'
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install shopli
23
+
24
+ ## Usage
25
+
26
+ TODO: Write usage instructions here
27
+
28
+ ## Contributing
29
+
30
+ 1. Fork it ( https://github.com/kamaradclimber/shopli/fork )
31
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
32
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
33
+ 4. Push to the branch (`git push origin my-new-feature`)
34
+ 5. Create a new Pull Request
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/shopli.rb'
4
+
5
+
6
+ reader = Shopli::BarcodeReader.new '/dev/input/by-id/usb-1130_USB-TMU-V1-event-kbd'
7
+
8
+ device = Shopli::Device.new
9
+
10
+ device.read(reader.events_stream)
@@ -0,0 +1,7 @@
1
+ require_relative "shopli/version.rb"
2
+
3
+ require_relative 'shopli/barcode.rb'
4
+ require_relative 'shopli/barcode_reader.rb'
5
+
6
+ require_relative 'shopli/open_food_facts.rb'
7
+ require_relative 'shopli/product.rb'
@@ -0,0 +1,35 @@
1
+ class Shopli
2
+ class Barcode
3
+
4
+ BARCODE_SIZE = 13
5
+
6
+ def ==(other)
7
+ other && @barcode == other.barcode
8
+ end
9
+
10
+ def self.read(events)
11
+ events.lazy.select do |event|
12
+ is_release = (event.type == 1) && (event.value_str.eql? 'Release')
13
+ is_release
14
+ end.lazy.slice_before do |event|
15
+ event.code_str.eql? 'Enter'
16
+ end.lazy.map do |cons_events|
17
+ cons_events.reject { |e| e.code_str.eql? 'Enter' }
18
+ end.lazy.reject do |cons_events|
19
+ cons_events.empty?
20
+ end.map do |cons_events|
21
+ barcode = cons_events.map { |e| e.code_str }.join.to_i
22
+ Barcode.new barcode
23
+ end
24
+ end
25
+
26
+ def initialize(barcode)
27
+ @barcode = barcode
28
+ end
29
+
30
+ def to_s
31
+ @barcode.to_s
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,14 @@
1
+ class Shopli
2
+ class BarcodeReader
3
+ require 'libdevinput'
4
+
5
+ def initialize(path)
6
+ @path = path
7
+ end
8
+
9
+ def events_stream
10
+ di = DevInput.new(@path, 24)
11
+ di.to_enum(:each)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,27 @@
1
+ class Shopli
2
+ class Device
3
+
4
+ attr_reader :current_mode
5
+
6
+ TRASH_MODE = Mode.new 'trash'
7
+ SHOP_MODE = Mode.new 'shop'
8
+
9
+ def initialize
10
+ @current_mode = TRASH_MODE
11
+ end
12
+
13
+ def read(stream)
14
+ Barcode.read(stream).each do |barcode|
15
+ process barcode
16
+ end
17
+ end
18
+
19
+
20
+ private
21
+ def process(barcode)
22
+ puts "#{Time.now.to_i} #{barcode.to_s}"
23
+ end
24
+
25
+
26
+ end
27
+ end
@@ -0,0 +1,15 @@
1
+ class Shopli
2
+ class Mode
3
+
4
+ attr_accessor :mode
5
+
6
+ def ==(other)
7
+ other && @mode == other.mode
8
+ end
9
+
10
+ def initialize(mode)
11
+ @mode = mode
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,28 @@
1
+ require 'rest_client'
2
+
3
+ class Shopli
4
+ class OpenFoodFacts
5
+
6
+ API_URL = 'http://fr.openfoodfacts.org/api'
7
+ API_VERSION = 'v0'
8
+ API_ENDPOINT = 'produit'
9
+
10
+ def fetch_product(barcode)
11
+ url = [API_URL, API_VERSION, API_ENDPOINT, barcode + '.json'].join '/'
12
+ resource = RestClient::Resource.new url
13
+ resource.get
14
+ end
15
+
16
+ def product(barcode)
17
+ json = fetch_product(barcode)
18
+ p = JSON.parse(json)
19
+ if p['status'] == 1
20
+ product = Product.new p['product']['_id']
21
+ product.name = p['product']['generic_name']
22
+ product
23
+ else
24
+ nil
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,10 @@
1
+ class Shopli
2
+ class Product
3
+ attr_accessor :id, :name
4
+
5
+ def initialize(id)
6
+ @id = id
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ class Shopli
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'shopli/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "shopli"
8
+ spec.version = Shopli::VERSION
9
+ spec.authors = ["Gregoire Seux"]
10
+ spec.email = ["shopli@familleseux.net"]
11
+ spec.summary = %q{Generate a shop list from a list of barcodes scanned before trash}
12
+ spec.description = %q{If you get the barcode of all things you put to the trash, shopli will generate your next shop list}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File. basename(f) }
18
+ spec.test_files = `git ls-files -- spec/*`.split("\n")
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_runtime_dependency 'rest-client'
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.6"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "rspec"
26
+ spec.add_development_dependency "coveralls"
27
+ end
@@ -0,0 +1 @@
1
+ {"status_verbose":"product found","status":1,"product":{"labels_hierarchy":[],"_id":"3029330003533","categories_hierarchy":["fr:pains-de-mie","fr:pains-de-mie-complet","en:breads"],"checkers_tags":[],"labels_tags":[],"image_small_url":"http://fr.openfoodfacts.org/images/products/302/933/000/3533/front.9.200.jpg","code":"3029330003533","lang":"fr","traces_tags":["lait","oeufs","sesame","soja"],"photographers":["manu1400"],"generic_name":"Pain complet en tranche","ingredients_that_may_be_from_palm_oil_tags":["e471-mono-et-diglycerides-d-acides-gras-alimentaires"],"_keywords":["pain","crousti","france","mie","en","de","moelleux","jacquet","complet","tranche"],"rev":17,"editors":["manu1400","andre","stephane"],"emb_codes":"","max_imgid":"4","additives_tags":["e575","e282","e471","e300"],"emb_codes_orig":"","informers_tags":["andre","manu1400","stephane"],"nutrient_levels_tags":["fat-in-low-quantity","saturated-fat-in-low-quantity","sugars-in-moderate-quantity","salt-in-moderate-quantity"],"additives_n":4,"photographers_tags":["andre"],"unknown_nutrients_tags":[],"packaging_tags":["sac-plastique"],"nutriments":{"sodium":0.44,"sugars":6.5,"fat_unit":"g","carbohydrates_unit":"g","proteins_unit":"g","fat":2.5,"proteins_serving":12.8,"sodium_serving":0.535,"proteins":10.5,"fat_serving":3.04,"sugars_unit":"g","sugars_100g":"6.5","sodium_unit":"g","saturated-fat_unit":"g","saturated-fat_serving":0.608,"sodium_100g":0.44,"fiber_unit":"g","energy":1067,"energy_unit":"kJ","sugars_serving":7.9,"carbohydrates_100g":44,"proteins_100g":10.5,"fiber_serving":7.29,"carbohydrates_serving":53.5,"energy_serving":1300,"fat_100g":"2.5","saturated-fat_100g":"0.5","fiber":6,"salt_100g":"1.1176","carbohydrates":44,"fiber_100g":6,"energy_100g":1067,"saturated-fat":0.5},"countries_tags":["en:france"],"ingredients_from_palm_oil_tags":[],"brands_tags":["jacquet"],"emb_codes_tags":[],"purchase_places":"","traces":"lait,oeufs,sésame,soja","countries_hierarchy":["en:france"],"categories":"Pain de mie complet,Pain,Pain de mie","ingredients_text":"Pain de mie complet : Farine complète de blé (61%), eau, levure, sucre, huile de colza, sel, arôme, dextrose, levain de blé déshydraté et dévitalisé, gluten de blé, Correcteur d'acidité: E575, Conservateur: E282, farine de blé, émulsifiant: E471, fibres végétales (avoine et/ou pois et/ou maïs), Agent de traitement de la farine: E300.","product_name":"Crousti Moelleux Complet","created_t":1338046925,"ingredients_from_or_that_may_be_from_palm_oil_n":1,"creator":"andre","no_nutrition_data":null,"serving_size":"2 tranches 121.5g","last_modified_by":"stephane","completed_t":1350567513,"origins":"France","stores":"","nutrient_levels":{"salt":"moderate","fat":"low","sugars":"moderate","saturated-fat":"low"},"stores_tags":[],"id":"3029330003533","countries":"France","purchase_places_tags":[],"interface_version_modified":"20120622","sortkey":1350576360,"last_modified_t":1350576360,"countries.20131227":null,"correctors_tags":["manu1400"],"correctors":["manu1400"],"brands":"Jacquet","ingredients_tags":["pain-de-mie-complet","eau","levure","sucre","huile-de-colza","sel","arome","dextrose","levain-de-ble-deshydrate-et-devitalise","gluten-de-ble","correcteur-d-acidite","e575","conservateur","e282","farine-de-ble","emulsifiant","e471","fibres-vegetales","avoine-et-ou-pois-et-ou-mais","agent-de-traitement-de-la-farine","e300","farine-complete-de-ble"],"status":"A vérifier, Complet, Informations nutritionnelles complétées, Ingrédients complétés, Date limite à compléter, Caractéristiques complétées, Photos validées, Photos envoyées","informers":["manu1400","stephane"],"packaging":"sac plastique","serving_quantity":"121.5","origins_tags":["france"],"nutrition_data_per":"100g","labels":"","cities_tags":[],"categories_tags":["fr:pains-de-mie","fr:pains-de-mie-complet","en:breads"],"quantity":"12 Tranches","expiration_date":"","status_tags":["a-verifier","complet","informations-nutritionnelles-completees","ingredients-completes","date-limite-a-completer","caracteristiques-completees","photos-validees","photos-envoyees"],"ingredients_that_may_be_from_palm_oil_n":1,"emb_code":"","ingredients_from_palm_oil_n":0,"image_url":"http://fr.openfoodfacts.org/images/products/302/933/000/3533/front.9.400.jpg","ingredients":[{"text":"Pain de mie complet","id":"pain-de-mie-complet","rank":1},{"text":"eau","id":"eau","rank":2},{"text":"levure","id":"levure","rank":3},{"text":"sucre","id":"sucre","rank":4},{"text":"huile de colza","id":"huile-de-colza","rank":5},{"text":"sel","id":"sel","rank":6},{"text":"arôme","id":"arome","rank":7},{"text":"dextrose","id":"dextrose","rank":8},{"text":"levain de blé déshydraté et dévitalisé","id":"levain-de-ble-deshydrate-et-devitalise","rank":9},{"text":"gluten de blé","id":"gluten-de-ble","rank":10},{"text":"Correcteur d'acidité","id":"correcteur-d-acidite","rank":11},{"text":"E575","id":"e575","rank":12},{"text":"Conservateur","id":"conservateur","rank":13},{"text":"E282","id":"e282","rank":14},{"text":"farine de blé","id":"farine-de-ble","rank":15},{"text":"émulsifiant","id":"emulsifiant","rank":16},{"text":"E471","id":"e471","rank":17},{"text":"fibres végétales","id":"fibres-vegetales","rank":18},{"text":"avoine et/ou pois et/ou maïs","id":"avoine-et-ou-pois-et-ou-mais","rank":19},{"text":"Agent de traitement de la farine","id":"agent-de-traitement-de-la-farine","rank":20},{"text":"E300.","id":"e300","rank":21},{"text":"Farine complète de blé","percent":"61","id":"farine-complete-de-ble"},{"text":"Pain de mie complet","id":"pain-de-mie-complet","rank":1},{"text":"eau","id":"eau","rank":2},{"text":"levure","id":"levure","rank":3},{"text":"sucre","id":"sucre","rank":4},{"text":"huile de colza","id":"huile-de-colza","rank":5},{"text":"sel","id":"sel","rank":6},{"text":"arôme","id":"arome","rank":7},{"text":"dextrose","id":"dextrose","rank":8},{"text":"levain de blé déshydraté et dévitalisé","id":"levain-de-ble-deshydrate-et-devitalise","rank":9},{"text":"gluten de blé","id":"gluten-de-ble","rank":10},{"text":"Correcteur d'acidité","id":"correcteur-d-acidite","rank":11},{"text":"E575","id":"e575","rank":12},{"text":"Conservateur","id":"conservateur","rank":13},{"text":"E282","id":"e282","rank":14},{"text":"farine de blé","id":"farine-de-ble","rank":15},{"text":"émulsifiant","id":"emulsifiant","rank":16},{"text":"E471","id":"e471","rank":17},{"text":"fibres végétales","id":"fibres-vegetales","rank":18},{"text":"avoine et/ou pois et/ou maïs","id":"avoine-et-ou-pois-et-ou-mais","rank":19},{"text":"Agent de traitement de la farine","id":"agent-de-traitement-de-la-farine","rank":20},{"text":"E300.","id":"e300","rank":21},{"percent":"61","text":"Farine complète de blé","id":"farine-complete-de-ble"},{"text":"Pain de mie complet","id":"pain-de-mie-complet","rank":1},{"text":"eau","id":"eau","rank":2},{"text":"levure","id":"levure","rank":3},{"text":"sucre","id":"sucre","rank":4},{"text":"huile de colza","id":"huile-de-colza","rank":5},{"text":"sel","id":"sel","rank":6},{"text":"arôme","id":"arome","rank":7},{"text":"dextrose","id":"dextrose","rank":8},{"text":"levain de blé déshydraté et dévitalisé","id":"levain-de-ble-deshydrate-et-devitalise","rank":9},{"text":"gluten de blé","id":"gluten-de-ble","rank":10},{"text":"Correcteur d'acidité","id":"correcteur-d-acidite","rank":11},{"text":"E575","id":"e575","rank":12},{"text":"Conservateur","id":"conservateur","rank":13},{"text":"E282","id":"e282","rank":14},{"text":"farine de blé","id":"farine-de-ble","rank":15},{"text":"émulsifiant","id":"emulsifiant","rank":16},{"text":"E471","id":"e471","rank":17},{"text":"fibres végétales","id":"fibres-vegetales","rank":18},{"text":"avoine et/ou pois et/ou maïs","id":"avoine-et-ou-pois-et-ou-mais","rank":19},{"text":"Agent de traitement de la farine","id":"agent-de-traitement-de-la-farine","rank":20},{"text":"E300.","id":"e300","rank":21},{"text":"Farine complète de blé","percent":"61","id":"farine-complete-de-ble"},{"text":"Pain de mie complet","id":"pain-de-mie-complet","rank":1},{"text":"eau","id":"eau","rank":2},{"text":"levure","id":"levure","rank":3},{"text":"sucre","id":"sucre","rank":4},{"text":"huile de colza","id":"huile-de-colza","rank":5},{"text":"sel","id":"sel","rank":6},{"text":"arôme","id":"arome","rank":7},{"text":"dextrose","id":"dextrose","rank":8},{"text":"levain de blé déshydraté et dévitalisé","id":"levain-de-ble-deshydrate-et-devitalise","rank":9},{"text":"gluten de blé","id":"gluten-de-ble","rank":10},{"text":"Correcteur d'acidité","id":"correcteur-d-acidite","rank":11},{"text":"E575","id":"e575","rank":12},{"text":"Conservateur","id":"conservateur","rank":13},{"text":"E282","id":"e282","rank":14},{"text":"farine de blé","id":"farine-de-ble","rank":15},{"text":"émulsifiant","id":"emulsifiant","rank":16},{"text":"E471","id":"e471","rank":17},{"text":"fibres végétales","id":"fibres-vegetales","rank":18},{"text":"avoine et/ou pois et/ou maïs","id":"avoine-et-ou-pois-et-ou-mais","rank":19},{"text":"Agent de traitement de la farine","id":"agent-de-traitement-de-la-farine","rank":20},{"text":"E300.","id":"e300","rank":21},{"percent":"61","text":"Farine complète de blé","id":"farine-complete-de-ble"}],"lc":"fr","checkers":[],"complete":1},"code":"3029330003533"}
@@ -0,0 +1,39 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe Shopli::Barcode do
4
+ describe '.to_s' do
5
+ it 'returns the barcode figure' do
6
+ b = Shopli::Barcode.new 123456
7
+ expect(b.to_s).to eq '123456'
8
+ end
9
+ end
10
+
11
+ def generate_events(code)
12
+ press = DevInput::Event.new 1,0,1,code, 1
13
+ release = DevInput::Event.new 1,0,1,code, 0
14
+ scan = DevInput::Event.new 1,0,4,4, 0
15
+ [scan, press, release]
16
+ end
17
+
18
+ let(:barcode1_events) do
19
+ [
20
+ (2..10).map { |i| generate_events(i) },
21
+ generate_events(28)
22
+ ].flatten
23
+ end
24
+ let(:barcode2_events) do
25
+ [
26
+ (2..10).map { |i| generate_events(12 - i) },
27
+ generate_events(28)
28
+ ].flatten
29
+ end
30
+
31
+
32
+ describe '.read' do
33
+ it 'finds barcodes' do
34
+ events = [barcode1_events, barcode2_events].flatten
35
+ barcodes = Shopli::Barcode.read(events).to_a
36
+ expect(barcodes).to have(2).barcodes
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,13 @@
1
+ require_relative '../spec_helper.rb'
2
+
3
+ describe Shopli::OpenFoodFacts do
4
+ describe 'products' do
5
+
6
+ it 'can call openfoodfacts.org' do
7
+ off = Shopli::OpenFoodFacts.new
8
+ expect{ @product = off.fetch_product('3029330003533') }.not_to raise_error
9
+ expect{ JSON.parse(@product) }.not_to raise_error
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,39 @@
1
+ require_relative 'spec_helper.rb'
2
+
3
+ describe Shopli::OpenFoodFacts do
4
+ describe '.fetch_product' do
5
+
6
+ it 'calls the correct url' do
7
+ rest_client = double('rest_client')
8
+ allow(RestClient::Resource).to receive(:new).
9
+ with('http://fr.openfoodfacts.org/api/v0/produit/3029330003533.json').
10
+ and_return(rest_client)
11
+ allow(rest_client).to receive(:get)
12
+ off = Shopli::OpenFoodFacts.new
13
+ off.fetch_product('3029330003533')
14
+ end
15
+ end
16
+
17
+ describe '.product' do
18
+ it 'return nil when product does not exist' do
19
+ rest_client = double('rest_client')
20
+ allow(RestClient::Resource).to receive(:new).and_return(rest_client)
21
+ allow(rest_client).to receive(:get).and_return('{"status_verbose":"product not found","status":0,"code":"302933678560003533"}')
22
+ off = Shopli::OpenFoodFacts.new
23
+ expect(off.product('inexistant_product')).to be_nil
24
+ end
25
+
26
+ it 'return a product otherwise' do
27
+ rest_client = double('rest_client')
28
+ allow(RestClient::Resource).to receive(:new).and_return(rest_client)
29
+ allow(rest_client).to receive(:get).and_return(File.read(File.join(File.dirname(__FILE__), '3029330003533.json')))
30
+ off = Shopli::OpenFoodFacts.new
31
+ product = off.product('3029330003533')
32
+ expect(product).to be_a(Shopli::Product)
33
+ expect(product.id).to eq '3029330003533'
34
+ expect(product.name).to eq 'Pain complet en tranche'
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,8 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+
4
+ lib = File.expand_path('../lib', __FILE__)
5
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
+
7
+ require 'rspec'
8
+ require 'shopli'
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shopli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Gregoire Seux
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-05-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rest-client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.6'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: coveralls
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: If you get the barcode of all things you put to the trash, shopli will
84
+ generate your next shop list
85
+ email:
86
+ - shopli@familleseux.net
87
+ executables:
88
+ - daemon.rb
89
+ extensions: []
90
+ extra_rdoc_files: []
91
+ files:
92
+ - ".gitignore"
93
+ - ".travis.yml"
94
+ - Gemfile
95
+ - Gemfile.lock
96
+ - LICENSE.txt
97
+ - README.md
98
+ - Rakefile
99
+ - bin/daemon.rb
100
+ - lib/shopli.rb
101
+ - lib/shopli/barcode.rb
102
+ - lib/shopli/barcode_reader.rb
103
+ - lib/shopli/device.rb
104
+ - lib/shopli/mode.rb
105
+ - lib/shopli/open_food_facts.rb
106
+ - lib/shopli/product.rb
107
+ - lib/shopli/version.rb
108
+ - shopli.gemspec
109
+ - spec/3029330003533.json
110
+ - spec/barcode_spec.rb
111
+ - spec/integration/open_food_facts_spec.rb
112
+ - spec/open_food_facts_spec.rb
113
+ - spec/spec_helper.rb
114
+ homepage: ''
115
+ licenses:
116
+ - MIT
117
+ metadata: {}
118
+ post_install_message:
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ requirements: []
133
+ rubyforge_project:
134
+ rubygems_version: 2.2.2
135
+ signing_key:
136
+ specification_version: 4
137
+ summary: Generate a shop list from a list of barcodes scanned before trash
138
+ test_files:
139
+ - spec/3029330003533.json
140
+ - spec/barcode_spec.rb
141
+ - spec/integration/open_food_facts_spec.rb
142
+ - spec/open_food_facts_spec.rb
143
+ - spec/spec_helper.rb