Skip to content

Commit

Permalink
Close #12: Add intraday time series support
Browse files Browse the repository at this point in the history
* Add method to be able to fetch intraday time series data for activities sub-resources
* Add tests around the method
* Fix some typos in other method documentation
  • Loading branch information
Zachery Moneypenny authored and zmoneype committed May 17, 2013
1 parent 621bab1 commit 5f46eb4
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 2 deletions.
49 changes: 48 additions & 1 deletion lib/fitgem/activities.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def goals
# @option opts [String, Integer] :durationMillis Activity duration in milliseconds.
# Must be a numeric value in Integer or String format. This value is REQUIRED for all calls.
# @option opts [String] :startTime Activity start time, in the format "HH:mm" using hours
# and seconds. Thie value is REQUIRED for all calls.
# and seconds. This value is REQUIRED for all calls.
# @option opts [String] :date Activity date, in "yyyy-MM-dd" format. This value is REQUIRED for all calls.
#
# @option opts [String] :distance Distance traveled, a string in the format "X.XX". This value is
Expand Down Expand Up @@ -139,5 +139,52 @@ def delete_logged_activity(activity_log_id)
def remove_favorite_activity(activity_id)
delete("/user/#{@user_id}/activities/log/favorite/#{activity_id}.json")
end

# ==========================================
# Intraday Activity Data Methods
# ==========================================

# Get intraday time series data for the specified resource
#
# @option opts [Symbol] :resource The sub-resource you want to retrieve time series data for; must
# be one of :calories, :steps, :floors, or :elevation. This value is REQUIRED for all calls.
# @option opts [String, Datetime, Date] :date The date to retrieve a time series on. This value is
# REQUIRED for all calls.
# @option opts [String] :detailLevel The resolution of the time series data; must be one of "1min"
# or "15min".
#
# @options opts [DateTime, Time, String] :startTime The start of the time period to request data for.
# @options opts [DateTime, Time, String] :endTime The end of the time period to request data for.
#
# @return [Hash] A hash containing time series data
def intraday_time_series(opts)
unless opts[:resource] && [:calories, :steps, :floors, :elevation].include?(opts[:resource])
raise Fitgem::InvalidArgumentError, 'Must specify resource to fetch intraday time series data for. One of (:calories, :steps, :floors, or :elevation) is required.'
end

unless opts[:date]
raise Fitgem::InvalidArgumentError, 'Must specify the date to fetch intraday time series data for.'
end

unless opts[:detailLevel] && %w(1min 15min).include?(opts[:detailLevel])
raise Fitgem::InvalidArgumentError, 'Must specify the data resolution to fetch intraday time series data for. One of (\"1d\" or \"15min\") is required.'
end

resource = opts.delete(:resource)
date = format_date(opts.delete(:date))
detail_level = opts.delete(:detailLevel)
time_window_specified = opts[:startTime] || opts[:endTime]
resource_path = "/user/#{@user_id}/activities/"

if time_window_specified
start_time = format_time(opts.delete(:startTime))
end_time = format_time(opts.delete(:endTime))
resource_path += "#{resource}/date/#{date}/1d/#{detail_level}/time/#{start_time}/#{end_time}.json"
else
resource_path += "#{resource}/date/#{date}/1d/#{detail_level}.json"
end

get(resource_path, opts)
end
end
end
97 changes: 97 additions & 0 deletions spec/fitgem_activities_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
require 'spec_helper'

describe Fitgem::Client do
before do
@client = Fitgem::Client.new({
:consumer_key => '12345',
:consumer_secret => '67890'
})
end

describe '#intraday_time_series' do
before(:each) do
@date_opts = {
resource: :calories,
date: '2013-05-13',
detailLevel: '1min'
}
@time_opts = {
resource: :calories,
date: '2013-05-13',
detailLevel: '15min',
startTime: '10:00',
endTime: '13:00'
}
end

it 'raises an exception if the resource is missing' do
expect {
@client.intraday_time_series(@date_opts.merge!(resource: nil))
}.to raise_error(Fitgem::InvalidArgumentError)
end

it 'raises an exception if the resource is not valid' do
expect {
@client.intraday_time_series(@date_opts.merge!(resource: :some_wrong_thing))
}.to raise_error(Fitgem::InvalidArgumentError)
end

it 'raises an exception if the date is missing' do
expect {
@client.intraday_time_series(@date_opts.merge!(date: nil))
}.to raise_error(Fitgem::InvalidArgumentError)
end

it 'raises an exception if the date is invalid' do
expect {
@client.intraday_time_series(@date_opts.merge!(date: 'zach-is-cool'))
}.to raise_error(Fitgem::InvalidDateArgument)
end

it 'raises an exception if the detail level is missing' do
expect {
@client.intraday_time_series(@date_opts.merge!(detailLevel: nil))
}.to raise_error(Fitgem::InvalidArgumentError)
end

it 'raises an exception if the detail level is invalid' do
expect {
@client.intraday_time_series(@date_opts.merge!(detailLevel: '5years'))
}.to raise_error(Fitgem::InvalidArgumentError)
end

it 'raises an exception if only the start time is supplied' do
expect {
@client.intraday_time_series(@time_opts.merge!(endTime: nil))
}.to raise_error(Fitgem::InvalidArgumentError)
end

it 'raises an exception if only the end time is supplied' do
expect {
@client.intraday_time_series(@time_opts.merge!(startTime: nil))
}.to raise_error(Fitgem::InvalidArgumentError)
end

it 'raises an exception if the start time is invalid' do
expect {
@client.intraday_time_series(@time_opts.merge!(startTime: 'what-is-this-nonsense'))
}.to raise_error(Fitgem::InvalidTimeArgument)
end

it 'raises an exception if the end time is invalid' do
expect {
@client.intraday_time_series(@time_opts.merge!(endTime: 'what-is-this-nonsense'))
}.to raise_error(Fitgem::InvalidTimeArgument)
end

it 'constructs the correct time-based url' do
@client.should_receive(:get).with('/user/-/activities/calories/date/2013-05-13/1d/15min/time/10:00/13:00.json', {})
@client.intraday_time_series(@time_opts)
end

it 'constructs the correct date-based url' do
@client.should_receive(:get).with('/user/-/activities/calories/date/2013-05-13/1d/1min.json', {})
@client.intraday_time_series(@date_opts)
end
end
end
2 changes: 1 addition & 1 deletion spec/fitgem_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
})
end

describe "global settings" do
describe 'global settings' do
it 'should expose the api_version' do
@client.api_version.should == "1"
end
Expand Down

0 comments on commit 5f46eb4

Please sign in to comment.