fat_secret 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fat_secret.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Matt Beedle
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,68 @@
1
+ FatSecret
2
+ =========
3
+
4
+ Introduction
5
+ ------------
6
+
7
+ A ruby wrapper for the FatSecret API. Currently only supports the foods.search and food.get methods, but I will add more when I have the need/time. Alternatively please feel free to send a tested pull request.
8
+
9
+ Prerequisits
10
+ ------------
11
+
12
+ Get your api key and oauth tokens by signing up for an account with FatSecret at http://platform.fatsecret.com/api/Default.aspx?screen=r
13
+
14
+
15
+ Installation
16
+ ------------
17
+
18
+ Bundler:
19
+
20
+ `gem 'fat_secret'`
21
+
22
+ Otherwise:
23
+
24
+ `gem install fat_secret`
25
+
26
+
27
+ Setup
28
+ -----
29
+
30
+ ```ruby
31
+ FatSecret.configure do |config|
32
+ config.access_key = <your access key>
33
+ config.consumer_key = <your consumer key>
34
+ config.shared_secret = <your shared secret>
35
+ config.logger = <your logger> #OPTIONAL
36
+ end
37
+ ```
38
+
39
+ Searching for Food
40
+ ------------------
41
+
42
+ ```ruby
43
+ foods = FatSecret::Food.search('Milk')
44
+ ```
45
+
46
+ Getting 1 Food
47
+ --------------
48
+
49
+ ```ruby
50
+ food = FatSecret::Food.get(id)
51
+ food.servings #(automatically lazy loaded for you)
52
+ ```
53
+
54
+
55
+ Development
56
+ -----------
57
+
58
+ ```
59
+ git clone git://github.com/mattbeedle/FatSecret.git
60
+ cd FatSecret
61
+ bundle install
62
+ ```
63
+
64
+ Then add your own api keys to the `spec/support/helpers.rb` file before running the specs with
65
+
66
+ ```
67
+ bundle exec rspec
68
+ ```
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/fat_secret/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Matt Beedle"]
6
+ gem.email = ["mattbeedle@googlemail.com"]
7
+ gem.description = %q{FatSecret API wrapper}
8
+ gem.summary = %q{FatSecret API wrapper}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "fat_secret"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = FatSecret::VERSION
17
+
18
+ gem.add_dependency('active_attr')
19
+ gem.add_dependency('activesupport')
20
+ # gem.add_dependency('typhoeus', '~> 0.5.0.rc')
21
+ gem.add_dependency('yajl-ruby')
22
+
23
+ gem.add_development_dependency('fakeweb')
24
+ gem.add_development_dependency('rspec')
25
+ gem.add_development_dependency('vcr')
26
+ end
@@ -0,0 +1,30 @@
1
+ require 'active_attr'
2
+ require 'active_support'
3
+ require 'fat_secret/relations/belongs_to'
4
+ require 'fat_secret/relations/has_many'
5
+ require 'fat_secret/relations/has_many_proxy'
6
+ require 'fat_Secret/relations'
7
+ require 'fat_secret/base'
8
+ require 'fat_secret/config'
9
+ require 'fat_secret/connection'
10
+ require 'fat_secret/food'
11
+ require 'fat_secret/results_proxy'
12
+ require 'fat_secret/serving'
13
+ require 'fat_secret/version'
14
+ require 'logger'
15
+ require 'open-uri'
16
+ # require 'typhoeus'
17
+ require 'yajl'
18
+
19
+ module FatSecret
20
+
21
+ class << self
22
+ attr_accessor :configuration
23
+ end
24
+
25
+ def self.configure
26
+ self.configuration ||= FatSecret::Config.new
27
+ yield(configuration)
28
+ return self.configuration
29
+ end
30
+ end
@@ -0,0 +1,10 @@
1
+ module FatSecret
2
+ class Base
3
+ include ActiveAttr::Attributes
4
+ include ActiveAttr::MassAssignment
5
+ include ActiveAttr::TypecastedAttributes
6
+ include FatSecret::Relations
7
+
8
+ attribute :id, type: Integer
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ module FatSecret
2
+ class Config
3
+ attr_accessor :access_key, :consumer_key, :shared_secret, :logger
4
+
5
+ def uri
6
+ 'http://platform.fatsecret.com/rest/server.api'
7
+ end
8
+
9
+ def logger
10
+ @logger || Logger.new($STDOUT)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,65 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext/object'
3
+ require 'cgi'
4
+ require 'uri'
5
+
6
+ module FatSecret
7
+ class Connection
8
+
9
+ class << self
10
+ def get(method, params)
11
+ FatSecret.configuration.logger.debug(
12
+ "FatSecret::Connection.get #{method} with #{params}"
13
+ )
14
+
15
+ params = default_parameters.merge(params).merge(method: method)
16
+ uri = request_uri('GET', params)
17
+ # response = Typhoeus.get(
18
+ # "#{uri.scheme}://#{uri.host}:#{uri.port}#{uri.path}",
19
+ # params: params, followlocation: true
20
+ # )
21
+ Yajl::Parser.parse(uri.read)
22
+ end
23
+
24
+ private
25
+
26
+ def request_uri(http_method, params)
27
+ params.merge!('oauth_signature' => generate_signature(http_method, params))
28
+ URI.parse("#{FatSecret.configuration.uri}?#{params.to_param}")
29
+ end
30
+
31
+ def generate_signature(http_method, params)
32
+ signature_value(
33
+ [
34
+ CGI.escape(http_method), CGI.escape(FatSecret.configuration.uri),
35
+ CGI.escape(Hash[params.sort].to_query)
36
+ ].join('&')
37
+ )
38
+ end
39
+
40
+ def normalized_parameters(params)
41
+ URI.encode(default_parameters.merge(params).sort.to_param)
42
+ end
43
+
44
+ def default_parameters
45
+ {
46
+ oauth_consumer_key: FatSecret.configuration.consumer_key,
47
+ oauth_signature_method: 'HMAC-SHA1',
48
+ oauth_timestamp: Time.now.to_i,
49
+ oauth_nonce: SecureRandom.hex(8),
50
+ oauth_version: '1.0',
51
+ format: 'json'
52
+ }
53
+ end
54
+
55
+ def signature_value(base_string, access_secret = '')
56
+ digest = OpenSSL::HMAC.digest(
57
+ OpenSSL::Digest::Digest.new('sha1'),
58
+ "#{FatSecret.configuration.shared_secret}&#{access_secret}",
59
+ base_string
60
+ )
61
+ Base64.encode64(digest).gsub(/\n/, '')
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,44 @@
1
+ module FatSecret
2
+ class Food < Base
3
+ attribute :description, type: String
4
+ attribute :name, type: String
5
+ attribute :type, type: String
6
+ attribute :url, type: String
7
+ attribute :brand_name, type: String
8
+
9
+ has_many :servings, autoload: true
10
+
11
+ alias :food_id= :id=
12
+ alias :food_description= :description=
13
+ alias :food_name= :name=
14
+ alias :food_type= :type=
15
+ alias :food_url= :url=
16
+
17
+ class << self
18
+ def search(search_expression, options = {})
19
+ results = Connection.get(
20
+ 'foods.search', default_search_options.
21
+ merge({ search_expression: search_expression }).merge(options)
22
+ )
23
+ ResultsProxy.new(
24
+ results['foods']['food'].map { |f| new(f) },
25
+ results['foods']['max_results'],
26
+ results['foods']['page_number'],
27
+ results['foods']['total_results']
28
+ )
29
+ end
30
+
31
+ def get(food_id)
32
+ new FatSecret::Connection.get('food.get', food_id: food_id)['food']
33
+ end
34
+
35
+ private
36
+
37
+ def default_search_options
38
+ {
39
+ max_results: 50, page_number: 0
40
+ }
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,8 @@
1
+ module FatSecret
2
+ module Relations
3
+ extend ActiveSupport::Concern
4
+
5
+ include FatSecret::Relations::HasMany
6
+ include FatSecret::Relations::BelongsTo
7
+ end
8
+ end
@@ -0,0 +1,23 @@
1
+ module FatSecret
2
+ module Relations
3
+ module BelongsTo
4
+ extend ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+ def belongs_to(type, options = {})
8
+
9
+ class_eval do
10
+ attribute "#{type}_id", type: Integer
11
+
12
+ attr_reader type
13
+ end
14
+
15
+ define_method "#{type}=" do |arg|
16
+ instance_variable_set(:"@#{type}", arg)
17
+ arg.send("#{self.class.name.split('::').last.downcase.pluralize}") << self
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,29 @@
1
+ module FatSecret
2
+ module Relations
3
+ module HasMany
4
+ extend ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+ def has_many(type, options = {})
8
+
9
+ define_method type do
10
+ @servings ||= HasManyProxy.new([])
11
+ if options[:autoload] && @servings.blank? && id
12
+ self.class.get(id).servings
13
+ else
14
+ @servings
15
+ end
16
+ end
17
+
18
+ define_method "#{type}=" do |array|
19
+ klass = "FatSecret::#{type.to_s.singularize.classify}".constantize
20
+ servings = array[type.to_s.singularize].map do |attrs|
21
+ klass.new(attrs)
22
+ end
23
+ @servings = HasManyProxy.new(servings)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,22 @@
1
+ module FatSecret
2
+ module Relations
3
+ class HasManyProxy < BasicObject
4
+
5
+ attr_reader :target
6
+
7
+ def initialize(target)
8
+ @target = target
9
+ end
10
+
11
+ protected
12
+
13
+ def method_missing(name, *args, &block)
14
+ target.send(name, *args, &block)
15
+ end
16
+
17
+ def target
18
+ @target || []
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,27 @@
1
+ module FatSecret
2
+ class ResultsProxy < BasicObject
3
+
4
+ attr_reader :max_results, :page_number, :total_results
5
+
6
+ def initialize(target, max_results, page_number, total_results )
7
+ @max_results = max_results.try(:to_i)
8
+ @page_number = page_number.try(:to_i)
9
+ @total_results = total_results.try(:to_i)
10
+ @target = target
11
+ end
12
+
13
+ def load_associations
14
+ raise NotImplementedError
15
+ end
16
+
17
+ protected
18
+
19
+ def method_missing(name, *args, &block)
20
+ target.send(name, *args, &block)
21
+ end
22
+
23
+ def target
24
+ @target ||= []
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,34 @@
1
+ module FatSecret
2
+ class Serving < Base
3
+
4
+ attribute :description, type: String
5
+ attribute :url, type: String
6
+ attribute :metric_serving_unit, type: String
7
+ attribute :metric_serving_amount, type: Float
8
+ attribute :number_of_units, type: Integer
9
+ attribute :measurement_description, type: String
10
+ attribute :calories, type: Float
11
+ attribute :carbohydrate, type: Float
12
+ attribute :protein, type: Float
13
+ attribute :fat, type: Float
14
+ attribute :saturated_fat, type: Float
15
+ attribute :polyunsaturated_fat, type: Float
16
+ attribute :monounsaturated_fat, type: Float
17
+ attribute :trans_fat, type: Float
18
+ attribute :cholesterol, type: Float
19
+ attribute :sodium, type: Float
20
+ attribute :potassium, type: Float
21
+ attribute :fiber, type: Float
22
+ attribute :sugar, type: Float
23
+ attribute :vitamin_a, type: Float
24
+ attribute :vitamin_c, type: Float
25
+ attribute :calcium, type: Float
26
+ attribute :iron, type: Float
27
+
28
+ alias :serving_id= :id=
29
+ alias :serving_description= :description=
30
+ alias :serving_url= :url=
31
+
32
+ belongs_to :food
33
+ end
34
+ end