Permalink
Browse files

initial checkin.

  • Loading branch information...
0 parents commit 5a5ef6d1f57704f4dec654dd2555c4e9ddf1cbd9 Brian Cooke committed Apr 14, 2008
Showing with 212 additions and 0 deletions.
  1. +2 −0 .gitignore
  2. +6 −0 History.txt
  3. +7 −0 Manifest.txt
  4. +75 −0 README.txt
  5. +22 −0 Rakefile
  6. +57 −0 lib/harvest.rb
  7. +37 −0 lib/harvest_entry.rb
  8. +6 −0 spec/harvest_spec.rb
@@ -0,0 +1,2 @@
+pkg
+coverage
@@ -0,0 +1,6 @@
+=== 1.0.0 / 2008-04-14
+
+* 1 major enhancement
+
+ * Birthday!
+
@@ -0,0 +1,7 @@
+History.txt
+Manifest.txt
+README.txt
+Rakefile
+lib/harvest.rb
+lib/harvest_entry.rb
+spec/harvest_spec.rb
@@ -0,0 +1,75 @@
+= harvest-ruby
+
+http://github.com/bricooke/harvest-ruby
+
+== DESCRIPTION:
+
+Ruby wrapper around the Harvest API
+http://www.getharvest.com/api
+
+== SYNOPSIS:
+
+harvest = Harvest.new("company.harvestapp.com", "email@example.com", "password")
+
+harvest.users[0].last_name
+=> "email@example.com"
+
+harvest.users[0].created_at
+=> "Fri May 11 15:00:08 EDT 2007"
+
+harvest.projects[0].name
+=> "Best Project Ever"
+
+harvest.tasks[0].name
+=> "Project Management"
+
+harvest.tasks(59273).name
+=> "Project Management"
+
+Fetch all entries and expenses for a project:
+harvest.report(5.years.ago, Time.now, :project_id => 6)
+
+or to filter on person:
+harvest.report(5.years.ago, Time.now, :person_id => 555)
+
+or to filter on both:
+harvest.report(5.years.ago, Time.now, :person_id => 555, :project_id => 6)
+
+
+== REQUIREMENTS:
+
+activesupport xml-simple
+
+== INSTALL:
+
+sudo gem install harvest-ruby
+
+== TODO:
+
+* Specs
+* Document the public API for rdocs
+
+== LICENSE:
+
+(The MIT License)
+
+Copyright (c) 2008 Brian Cooke
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,22 @@
+# -*- ruby -*-
+
+require 'rubygems'
+require 'hoe'
+require './lib/harvest.rb'
+require 'spec/rake/spectask'
+
+
+Hoe.new('harvest-ruby', Harvest::VERSION) do |p|
+ p.rubyforge_name = 'harvest-ruby' # if different than lowercase project name
+ p.developer('Brian Cooke', 'bcooke@roobasoft.com')
+end
+
+
+desc "Run specifications"
+Spec::Rake::SpecTask.new('spec') do |t|
+ t.spec_opts = ["--format", "specdoc", "--colour"]
+ t.spec_files = './spec/**/*_spec.rb'
+end
+
+
+# vim: syntax=Ruby
@@ -0,0 +1,57 @@
+require 'rubygems'
+require 'net/http'
+require 'xmlsimple'
+require 'activesupport'
+require File.dirname(__FILE__) + '/harvest_entry'
+
+class Harvest
+ VERSION = '0.1.0'
+
+ def initialize(domain, email, password)
+ @domain = domain
+ @email = email
+ @password = password
+ end
+
+ def users(params={})
+ request("/people", params).users
+ end
+
+ def projects
+ request("/projects").projects
+ end
+
+ def report(from, to, project_and_or_person_id)
+ entries = []
+ if project_and_or_person_id.has_key?(:project_id)
+ entries += request("/projects/#{project_and_or_person_id[:project_id]}/entries?from=#{from.strftime("%Y%m%d")}&to=#{to.strftime("%Y%m%d")}").day_entries
+ end
+
+ if project_and_or_person_id.has_key?(:person_id)
+ entries += request("/people/#{project_and_or_person_id[:person_id]}/entries?from=#{from.strftime("%Y%m%d")}&to=#{to.strftime("%Y%m%d")}").day_entries
+ end
+
+ entries
+ end
+
+ def tasks(task_id=nil)
+ if task_id.nil?
+ request("/tasks").tasks
+ else
+ request("/tasks/#{task_id}")
+ end
+ end
+
+private
+ def request(path, params={})
+ request = Net::HTTP::Get.new(path, { "Accept" => "application/xml"})
+ request.basic_auth(@email, @password)
+ request.content_type = "application/xml"
+ ret = nil
+ Net::HTTP.new(@domain).start {|http|
+ response = http.request(request)
+ ret = HarvestEntry.new(XmlSimple.xml_in(response.body))
+ }
+ ret
+ end
+end
@@ -0,0 +1,37 @@
+class HarvestEntry
+ def initialize(parsed)
+ @hash = parsed
+ end
+
+ def id
+ self.method_missing(:id)
+ end
+
+ def empty?
+ if @hash["type"] == "array" && @hash["content"] == "\n"
+ true
+ else
+ false
+ end
+ end
+
+ def method_missing(method, *args)
+ method = method.to_s.gsub("_", "-").to_sym
+
+ if @hash.has_key?(method.to_s.singularize)
+ entry = @hash[method.to_s.singularize]
+ if method.to_s.pluralize == method.to_s && entry.class == Array
+ return entry.collect {|e| HarvestEntry.new(e)}
+ else
+ return entry[0] unless entry[0].class == Hash && entry[0].has_key?("content")
+ return entry[0]["content"]
+ end
+ elsif @hash.has_key?(method.to_s)
+ entry = @hash[method.to_s]
+ return entry[0] unless entry[0].class == Hash && entry[0].has_key?("content")
+ return entry[0]["content"]
+ else
+ super
+ end
+ end
+end
@@ -0,0 +1,6 @@
+require './lib/harvest'
+
+describe "Harvest" do
+ it "should do some things"
+end
+

0 comments on commit 5a5ef6d

Please sign in to comment.