ruby-fitbit 0.2.3 → 0.3.1

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.
data/lib/ruby-fitbit.rb CHANGED
@@ -1,11 +1,10 @@
1
1
  require 'rubygems'
2
2
  require 'mechanize'
3
3
  require 'nokogiri'
4
+ require 'json'
4
5
 
5
6
  class RubyFitbit
6
7
 
7
- attr_reader :calories, :steps, :miles_walked, :sedentary_active, :lightly_active, :fairly_active, :very_active
8
-
9
8
  #TODO change tests so reader isn't needed
10
9
  attr_reader :logged_in
11
10
 
@@ -15,10 +14,8 @@ class RubyFitbit
15
14
  @agent = WWW::Mechanize.new #{|a| a.log = Logger.new(STDERR) } #turn on if debugging
16
15
  @logged_in = false
17
16
  @cached_data = {}
18
- get_data
19
17
  end
20
18
 
21
- #todo only login once
22
19
  def login
23
20
  unless @logged_in
24
21
  page = @agent.get 'https://www.fitbit.com/login'
@@ -37,6 +34,93 @@ class RubyFitbit
37
34
  end
38
35
  end
39
36
 
37
+ def submit_food_log(options = {})
38
+ login
39
+
40
+ date = options.fetch(:date) {Time.now}
41
+ date = get_fitbit_date_format(date)
42
+ meal_type = options.fetch(:meal_type){'7'}
43
+ food_id = options[:food_id]
44
+ food = options[:food]
45
+ raise "food_id or food required to submit food log" unless food_id || food
46
+ unless food_id
47
+ food_recommendation = get_food_items(food)
48
+ if food_recommendation.length > 0
49
+ food_recommendation = food_recommendation.first
50
+ food = food_recommendation['name']
51
+ food_id = food_recommendation['id']
52
+ end
53
+ end
54
+
55
+ unit_id = options[:unit_id]
56
+ unit = options[:unit]
57
+ raise "unit_id or unit required to submit food log" unless unit_id || unit
58
+ unless unit_id
59
+ unit_id = get_unit_id_for_unit(unit)
60
+ end
61
+
62
+ page = @agent.get 'http://www.fitbit.com/foods/log'
63
+
64
+ form = page.forms[1]
65
+
66
+ form.action="/foods/log/foodLog?apiFormat=htmljson&log=on&date=#{date}"
67
+ form.foodId = food_id
68
+ form.foodselectinput = food
69
+ form.unitId = unit_id
70
+ form.quantityselectinput = unit
71
+ form.quantityConsumed = unit
72
+ form.mealTypeId = meal_type
73
+
74
+ result = @agent.submit(form, form.buttons.first)
75
+ end
76
+
77
+ def get_unit_id_for_unit(unit)
78
+ unit_id = nil
79
+ unit_type = unit.match(/\d+ (.*)/)[1]
80
+
81
+ type_map = {'oz' => '226',
82
+ 'lb' => '180',
83
+ 'gram' => '147',
84
+ 'kilogram' => '389',
85
+ 'roll' => '290',
86
+ 'serving' => '304',
87
+ 'link' => '188',
88
+ 'piece' => '251',
89
+ 'fl oz' => '128',
90
+ 'ml' => '209',
91
+ 'tsp' => '364',
92
+ 'tbsp' => '349',
93
+ 'cup' => '91',
94
+ 'pint' => '256',
95
+ 'slice' => '311',
96
+ 'liter' => '189',
97
+ 'quart' => '279',
98
+ 'entree' => '117',
99
+ 'portion' => '270'
100
+ }
101
+
102
+ unit_id = type_map[unit_type]
103
+ unit_id
104
+ end
105
+
106
+ def get_food_items(food="Coffe")
107
+ login
108
+ result = @agent.get "http://www.fitbit.com/solr/food/select?q=#{food}&wt=foodjson&qt=food"
109
+ foods = JSON.parse(result.body).first[1]["foods"]
110
+ foods
111
+ end
112
+
113
+ def get_eaten_calories(date = Time.now)
114
+ login
115
+
116
+ date = get_fitbit_date_format(date).gsub('-','/')
117
+ page = @agent.get "https://www.fitbit.com/foods/log/#{date}"
118
+ calories_data = page.search("//div[@id='dailyTotals']").first
119
+ calories_xml = calories_data.to_xml
120
+ calories_text = calories_data.text
121
+ {:calories_xml => calories_xml, :calories_text => calories_text}
122
+ end
123
+
40
124
  def get_data(date = Time.now)
41
125
  login
42
126
 
@@ -45,21 +129,21 @@ class RubyFitbit
45
129
 
46
130
  page = @agent.get "https://www.fitbit.com/#{date}"
47
131
 
48
- @calories = page.search("//div[@class='data']").search("span").children[0].text
49
- @steps = page.search("//div[@class='data']").search("span").children[2].text.strip
50
- @miles_walked = page.search("//div[@class='data']").search("span").children[3].text.strip
51
- @sedentary_active = page.search("//div[@class='sedentary caption']/div[@class='number']").text.strip
52
- @lightly_active = page.search("//div[@class='lightly caption']/div[@class='number']").text.strip
53
- @fairly_active = page.search("//div[@class='caption fairly']/div[@class='number']").text.strip
54
- @very_active = page.search("//div[@class='caption very']/div[@class='number']").text.strip
132
+ calories = page.search("//div[@class='data']").search("span").children[0].text
133
+ steps = page.search("//div[@class='data']").search("span").children[2].text.strip
134
+ miles_walked = page.search("//div[@class='data']").search("span").children[3].text.strip
135
+ sedentary_active = page.search("//div[@class='sedentary caption']/div[@class='number']").text.strip
136
+ lightly_active = page.search("//div[@class='lightly caption']/div[@class='number']").text.strip
137
+ fairly_active = page.search("//div[@class='caption fairly']/div[@class='number']").text.strip
138
+ very_active = page.search("//div[@class='caption very']/div[@class='number']").text.strip
55
139
  data = {}
56
- data['calories'] = @calories.to_i
57
- data['steps'] = @steps.to_i
58
- data['miles_walked'] = @miles_walked.to_f
59
- data['sedentary_active'] = @sedentary_active
60
- data['lightly_active'] = @lightly_active
61
- data['fairly_active'] = @fairly_active
62
- data['very_active'] = @very_active
140
+ data['calories'] = calories.to_i
141
+ data['steps'] = steps.to_i
142
+ data['miles_walked'] = miles_walked.to_f
143
+ data['sedentary_active'] = sedentary_active
144
+ data['lightly_active'] = lightly_active
145
+ data['fairly_active'] = fairly_active
146
+ data['very_active'] = very_active
63
147
  @cached_data[date] = data
64
148
  data
65
149
  end
data/ruby-fitbit.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ruby-fitbit}
8
- s.version = "0.2.3"
8
+ s.version = "0.3.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Dan Mayer"]
12
- s.date = %q{2010-07-24}
12
+ s.date = %q{2010-10-14}
13
13
  s.default_executable = %q{ruby-fitbit}
14
14
  s.description = %q{This is a Ruby API for Fitbit.com, currently scraping, but soon will use the officail API (when released)}
15
15
  s.email = %q{Danmayer@gmail.com}
@@ -26,6 +26,7 @@ Gem::Specification.new do |s|
26
26
  "Rakefile",
27
27
  "VERSION",
28
28
  "bin/ruby-fitbit",
29
+ "fixtures/vcr_cassettes/fitbit_get_data.yml",
29
30
  "lib/ruby-fitbit.rb",
30
31
  "ruby-fitbit.gemspec",
31
32
  "test/helper.rb",
@@ -1,16 +1,16 @@
1
1
  require File.expand_path('./helper', File.dirname(__FILE__))
2
2
  require 'webmock/test_unit'
3
- #require 'vcr'
3
+ require 'vcr'
4
4
  require 'ruby-fitbit'
5
5
  require 'mocha'
6
6
 
7
7
  class TestRubyFitbit < Test::Unit::TestCase
8
8
  include WebMock
9
9
 
10
- #VCR.config do |c|
11
- # c.cassette_library_dir = 'fixtures/vcr_cassettes'
12
- # c.http_stubbing_library = :webmock
13
- #end
10
+ VCR.config do |c|
11
+ c.cassette_library_dir = 'fixtures/vcr_cassettes'
12
+ c.http_stubbing_library = :webmock
13
+ end
14
14
 
15
15
  #TODO this is a mess it took awhile to figure out a way to make the tests work at all clean this up
16
16
 
@@ -62,7 +62,9 @@ END
62
62
  data = File.read("./test/responses/data.txt")
63
63
  response = "#{HEADERS} #{data}"
64
64
 
65
- stub_request(:get, "https://www.fitbit.com/2010/07/18").to_return(response)
65
+ date = Time.now()
66
+ date = date.strftime("%Y/%m/%d")
67
+ stub_request(:get, "https://www.fitbit.com/#{date}").to_return(response)
66
68
 
67
69
  RubyFitbit.any_instance.stubs(:login)
68
70
  fitbit = RubyFitbit.new("fake@fake.com","pass")
@@ -70,15 +72,32 @@ END
70
72
  @logged_in = val
71
73
  end
72
74
  fitbit.set_logged_in(true)
75
+ data = fitbit.get_data
73
76
 
74
- assert_equal "1928", fitbit.calories, "wrong calories"
75
- assert_equal "7821", fitbit.steps, "wrong steps"
76
- assert_equal "3.38", fitbit.miles_walked, "wrong miles"
77
- assert_equal "16hrs 58min", fitbit.sedentary_active, "wrong sedentary"
78
- assert_equal "1hr 42min", fitbit.lightly_active, "wrong lightly"
79
- assert_equal "1hr 51min", fitbit.fairly_active, "wrong fairly"
80
- assert_equal "17min", fitbit.very_active, "wrong very"
77
+ assert_equal 1928, data['calories'], "wrong calories"
78
+ assert_equal 7821, data['steps'], "wrong steps"
79
+ assert_equal 3.38, data['miles_walked'], "wrong miles"
80
+ assert_equal "16hrs 58min", data['sedentary_active'], "wrong sedentary"
81
+ assert_equal "1hr 42min", data['lightly_active'], "wrong lightly"
82
+ assert_equal "1hr 51min", data['fairly_active'], "wrong fairly"
83
+ assert_equal "17min", data['very_active'], "wrong very"
84
+ end
85
+
86
+ should "use VCR successfully" do
87
+ fitbit = nil
88
+ data = nil
89
+ VCR.use_cassette('fitbit_get_data', :record => :new_episodes) do
90
+ fitbit = RubyFitbit.new("fake@fake.com","fake")
91
+ data = fitbit.get_data(Time.parse("2010/08/03"))
92
+ end
81
93
 
94
+ assert_equal 2084, data['calories'], "wrong calories"
95
+ assert_equal 10018, data['steps'], "wrong steps"
96
+ assert_equal 4.61, data['miles_walked'], "wrong miles"
97
+ assert_equal "18hrs 26min", data['sedentary_active'], "wrong sedentary"
98
+ assert_equal "1hr 17min", data['lightly_active'], "wrong lightly"
99
+ assert_equal "1hr 29min", data['fairly_active'], "wrong fairly"
100
+ assert_equal "42min", data['very_active'], "wrong very"
82
101
  end
83
102
 
84
103
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 2
8
7
  - 3
9
- version: 0.2.3
8
+ - 1
9
+ version: 0.3.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Dan Mayer
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-07-24 00:00:00 -04:00
17
+ date: 2010-10-14 00:00:00 -04:00
18
18
  default_executable: ruby-fitbit
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -88,6 +88,7 @@ files:
88
88
  - Rakefile
89
89
  - VERSION
90
90
  - bin/ruby-fitbit
91
+ - fixtures/vcr_cassettes/fitbit_get_data.yml
91
92
  - lib/ruby-fitbit.rb
92
93
  - ruby-fitbit.gemspec
93
94
  - test/helper.rb