letsfreckle-client 0.1.0

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.
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "httparty"
4
+ gem "hashie"
5
+
6
+ group :development do
7
+ gem "rspec", "~> 2.5.0"
8
+ gem "bundler", "~> 1.0.0"
9
+ gem "jeweler", "~> 1.6.4"
10
+ gem "rcov", ">= 0"
11
+ gem "webmock", "~> 1.6.2"
12
+ end
@@ -0,0 +1,39 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ addressable (2.2.6)
5
+ crack (0.1.8)
6
+ diff-lcs (1.1.2)
7
+ git (1.2.5)
8
+ hashie (1.0.0)
9
+ httparty (0.7.8)
10
+ crack (= 0.1.8)
11
+ jeweler (1.6.4)
12
+ bundler (~> 1.0)
13
+ git (>= 1.2.5)
14
+ rake
15
+ rake (0.9.2)
16
+ rcov (0.9.9)
17
+ rspec (2.5.0)
18
+ rspec-core (~> 2.5.0)
19
+ rspec-expectations (~> 2.5.0)
20
+ rspec-mocks (~> 2.5.0)
21
+ rspec-core (2.5.2)
22
+ rspec-expectations (2.5.0)
23
+ diff-lcs (~> 1.1.2)
24
+ rspec-mocks (2.5.0)
25
+ webmock (1.6.4)
26
+ addressable (~> 2.2, > 2.2.5)
27
+ crack (>= 0.1.7)
28
+
29
+ PLATFORMS
30
+ ruby
31
+
32
+ DEPENDENCIES
33
+ bundler (~> 1.0.0)
34
+ hashie
35
+ httparty
36
+ jeweler (~> 1.6.4)
37
+ rcov
38
+ rspec (~> 2.5.0)
39
+ webmock (~> 1.6.2)
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Ryan LeCompte
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,75 @@
1
+ = letsfreckle-client
2
+
3
+ letsfreckle-client is a Ruby client for accessing the Let's Freckle API.
4
+ Let's Freckle is an intuitive time-tracking service.
5
+ See http://www.letsfreckle.com for more information.
6
+
7
+ API information can be found at http://madrobby.github.com/freckle-apidocs/
8
+
9
+ == Installation
10
+
11
+ letsfreckle-client is available as a RubyGem:
12
+
13
+ gem install letsfreckle-client
14
+
15
+ == Examples
16
+
17
+ The following examples show how to access functions of the API. In order to use
18
+ the client, you must have an API token. You can access your token via your
19
+ letsfreckle.com settings/profile. Note that currently letsfreckle.com hosts
20
+ a sample API test account, which the following examples utilize.
21
+
22
+ === Example:
23
+
24
+ # Configure the client before fetching data.
25
+ LetsFreckle.configure do
26
+ account_host "apitest"
27
+ username "apitest@letsfreckle.com"
28
+ token "lx3gi6pxdjtjn57afp8c2bv1me7g89j"
29
+ end
30
+
31
+ # Submit a new entry.
32
+ LetsFreckle::Entry.create(:project_id => 3427, :minutes => '1h', :description => 'fixed a bug')
33
+
34
+ # Fetch all entries.
35
+ LetsFreckle::Entry.all.each do |entry|
36
+ puts "Entry #{entry.description} - #{entry.minutes} minutes"
37
+ end
38
+
39
+ # Search for entries from a specific start date and tags
40
+ LetsFreckle::Entry.find(:from => '2010-07-10', :tags => ['development', 'design']).each do |entry|
41
+ puts entry.description
42
+ end
43
+
44
+ # Fetch all projects and associated entries
45
+ LetsFreckle::Project.all.each do |project|
46
+ puts "Project #{project.name} has #{project.entries.size} entries"
47
+ end
48
+
49
+ # Fetch all tags and associated entries
50
+ LetsFreckle::Tag.all.each do |tag|
51
+ puts "Tag #{tag.name} has #{tag.entries.size} entries"
52
+ end
53
+
54
+ # Fetch all users and associated permissions
55
+ LetsFreckle::User.all.each do |user|
56
+ puts "User #{user.email} has following permissions: #{user.permissions}"
57
+ end
58
+
59
+ == Note on Patches/Pull Requests
60
+
61
+ * Fork the project.
62
+ * Make your feature addition or bug fix.
63
+ * Add tests for it. This is important so I don't break it in a future version unintentionally.
64
+ * Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
65
+ * Send me a pull request. Bonus points for topic branches.
66
+
67
+ == Authors
68
+
69
+ * Ryan LeCompte
70
+
71
+ == Copyright
72
+
73
+ Copyright (c) 2011 Ryan LeCompte. See LICENSE.txt for
74
+ further details.
75
+
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "letsfreckle-client"
18
+ gem.homepage = "http://github.com/ryanlecompte/letsfreckle-client"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Ruby client for letsfreckle.com API}
21
+ gem.description = %Q{Ruby client for letsfreckle.com API that supports entries, projects, tags, and users}
22
+ gem.email = "lecompte@gmail.com"
23
+ gem.authors = ["Ryan LeCompte"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
35
+ spec.pattern = 'spec/**/*_spec.rb'
36
+ spec.rcov = true
37
+ end
38
+
39
+ task :default => :spec
40
+
41
+ require 'rake/rdoctask'
42
+ Rake::RDocTask.new do |rdoc|
43
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
44
+
45
+ rdoc.rdoc_dir = 'rdoc'
46
+ rdoc.title = "letsfreckle-client #{version}"
47
+ rdoc.rdoc_files.include('README*')
48
+ rdoc.rdoc_files.include('lib/**/*.rb')
49
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,87 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{letsfreckle-client}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Ryan LeCompte"]
12
+ s.date = %q{2011-07-25}
13
+ s.description = %q{Ruby client for letsfreckle.com API that supports entries, projects, tags, and users}
14
+ s.email = %q{lecompte@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".rspec",
22
+ "Gemfile",
23
+ "Gemfile.lock",
24
+ "LICENSE.txt",
25
+ "README.rdoc",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "letsfreckle-client.gemspec",
29
+ "lib/letsfreckle.rb",
30
+ "lib/letsfreckle/client_resource.rb",
31
+ "lib/letsfreckle/configuration.rb",
32
+ "lib/letsfreckle/entry.rb",
33
+ "lib/letsfreckle/error.rb",
34
+ "lib/letsfreckle/extensions/mash.rb",
35
+ "lib/letsfreckle/project.rb",
36
+ "lib/letsfreckle/tag.rb",
37
+ "lib/letsfreckle/user.rb",
38
+ "spec/letsfreckle/configuration_spec.rb",
39
+ "spec/letsfreckle/entry_spec.rb",
40
+ "spec/letsfreckle/project_spec.rb",
41
+ "spec/letsfreckle/tag_spec.rb",
42
+ "spec/letsfreckle/user_spec.rb",
43
+ "spec/responses/entries.xml.response",
44
+ "spec/responses/projects.xml.response",
45
+ "spec/responses/tags.xml.response",
46
+ "spec/responses/users.xml.response",
47
+ "spec/spec_helper.rb",
48
+ "spec/support/webmock_helper.rb"
49
+ ]
50
+ s.homepage = %q{http://github.com/ryanlecompte/letsfreckle-client}
51
+ s.licenses = ["MIT"]
52
+ s.require_paths = ["lib"]
53
+ s.rubygems_version = %q{1.3.7}
54
+ s.summary = %q{Ruby client for letsfreckle.com API}
55
+
56
+ if s.respond_to? :specification_version then
57
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
58
+ s.specification_version = 3
59
+
60
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
61
+ s.add_runtime_dependency(%q<httparty>, [">= 0"])
62
+ s.add_runtime_dependency(%q<hashie>, [">= 0"])
63
+ s.add_development_dependency(%q<rspec>, ["~> 2.5.0"])
64
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
65
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
66
+ s.add_development_dependency(%q<rcov>, [">= 0"])
67
+ s.add_development_dependency(%q<webmock>, ["~> 1.6.2"])
68
+ else
69
+ s.add_dependency(%q<httparty>, [">= 0"])
70
+ s.add_dependency(%q<hashie>, [">= 0"])
71
+ s.add_dependency(%q<rspec>, ["~> 2.5.0"])
72
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
73
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
74
+ s.add_dependency(%q<rcov>, [">= 0"])
75
+ s.add_dependency(%q<webmock>, ["~> 1.6.2"])
76
+ end
77
+ else
78
+ s.add_dependency(%q<httparty>, [">= 0"])
79
+ s.add_dependency(%q<hashie>, [">= 0"])
80
+ s.add_dependency(%q<rspec>, ["~> 2.5.0"])
81
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
82
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
83
+ s.add_dependency(%q<rcov>, [">= 0"])
84
+ s.add_dependency(%q<webmock>, ["~> 1.6.2"])
85
+ end
86
+ end
87
+
@@ -0,0 +1,24 @@
1
+ require 'hashie'
2
+ require 'httparty'
3
+ require 'delegate'
4
+
5
+ require 'letsfreckle/extensions/mash'
6
+ require 'letsfreckle/configuration'
7
+ require 'letsfreckle/client_resource'
8
+ require 'letsfreckle/project'
9
+ require 'letsfreckle/error'
10
+ require 'letsfreckle/entry'
11
+ require 'letsfreckle/user'
12
+ require 'letsfreckle/tag'
13
+
14
+ module LetsFreckle
15
+ extend self
16
+
17
+ attr_reader :config
18
+
19
+ def configure(&block)
20
+ raise ArgumentError, 'configuration block required' unless block
21
+ @config = Configuration.new
22
+ @config.instance_eval(&block)
23
+ end
24
+ end
@@ -0,0 +1,40 @@
1
+ module LetsFreckle
2
+ # ClientResource should be extended by resource classes in order to gain
3
+ # access to HTTP methods.
4
+ module ClientResource
5
+ API_URL = "https://%s.letsfreckle.com/api/%s.xml?token=%s"
6
+
7
+ def fetch(resource, options = {})
8
+ response = HTTParty.get(url(resource), :query => options, :format => :xml)
9
+ verify!(response, 200) { raise FetchError, "Fetch failed, HTTP error: #{response.code}" }
10
+ mashes = mashes_from_response(response)
11
+ mashes.map { |m| new(m) }
12
+ end
13
+
14
+ def post(resource, options = {})
15
+ response = HTTParty.post(url(resource), :body => options, :format => :xml)
16
+ verify!(response, 201) { raise CreateError, "Create failed, HTTP error: #{response.code}" }
17
+ end
18
+
19
+ def url(resource)
20
+ API_URL % [LetsFreckle.config.account_host, resource, LetsFreckle.config.token]
21
+ end
22
+
23
+ private
24
+
25
+ def verify!(response, code, &block)
26
+ block.call unless response.code == code
27
+ end
28
+
29
+ def mashes_from_response(response)
30
+ return [] unless response.respond_to?(:to_a)
31
+ flattened_response = response.to_a.flatten
32
+ flattened_response.keep_if { |r| r.is_a?(Hash) }
33
+ flattened_response.map do |h|
34
+ m = Hashie::Mash.new(h)
35
+ # extend so that #respond_to? works nicely with DelegateClass
36
+ m.extend(Extensions::Mash)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,10 @@
1
+ module LetsFreckle
2
+ class Configuration
3
+ [:username, :account_host, :token].each do |method_name|
4
+ define_method(method_name) do |value=nil|
5
+ instance_variable_set("@#{method_name}", value) if value
6
+ instance_variable_get("@#{method_name}")
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,40 @@
1
+ module LetsFreckle
2
+ class Entry < DelegateClass(Hashie::Mash)
3
+ extend ClientResource
4
+
5
+ def self.all
6
+ fetch('entries')
7
+ end
8
+
9
+ # Fetches all entries. Supported options are:
10
+ # :people => ['ryan', 'frank']
11
+ # :projects => ['project1', 'project2']
12
+ # :tags => ['tag1', 'tag2']
13
+ # :from => '2011-01-01'
14
+ # :to => '2012-01-01'
15
+ # :billable => true/false
16
+ def self.find(options = {})
17
+ fetch('entries', searchable_options_from(options))
18
+ end
19
+
20
+ # Creates a new entry. Supported options are:
21
+ # :minutes => '4h' (required)
22
+ # :project_id => 3221
23
+ # :description => 'new task'
24
+ # :date => '2011-08-01'
25
+ def self.create(options = {})
26
+ raise ArgumentError, ':username config missing' unless LetsFreckle.config.username
27
+ raise ArgumentError, ':minutes missing' unless options.has_key?(:minutes)
28
+ post('entries', :entry => options.merge(:user => LetsFreckle.config.username))
29
+ end
30
+
31
+ def self.searchable_options_from(options = {})
32
+ options.each_with_object({}) do |(key, value), result|
33
+ case value
34
+ when Array then result["search[#{key}]"] = value.join(',')
35
+ else result["search[#{key}]"] = value.to_s
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,6 @@
1
+ module LetsFreckle
2
+ class FetchError < StandardError
3
+ end
4
+ class CreateError < StandardError
5
+ end
6
+ end
@@ -0,0 +1,13 @@
1
+ # Ruby's DelegateClass expects the delegate to support the second
2
+ # optional argument to Object#respond_to?. Hashie::Mash doesn't
3
+ # currently define the method in this way, so we provide a module
4
+ # that is #extend'ed into each Hashie::Mash instance that we create.
5
+ module LetsFreckle
6
+ module Extensions
7
+ module Mash
8
+ def respond_to?(sym, include_private=false)
9
+ super(sym)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module LetsFreckle
2
+ class Project < DelegateClass(Hashie::Mash)
3
+ extend ClientResource
4
+
5
+ def self.all
6
+ fetch('projects')
7
+ end
8
+
9
+ def entries
10
+ Entry.find(:projects => [id])
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module LetsFreckle
2
+ class Tag < DelegateClass(Hashie::Mash)
3
+ extend ClientResource
4
+
5
+ def self.all
6
+ fetch('tags')
7
+ end
8
+
9
+ def entries
10
+ Entry.find(:tags => [id])
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module LetsFreckle
2
+ class User < DelegateClass(Hashie::Mash)
3
+ extend ClientResource
4
+
5
+ def self.all
6
+ fetch('users')
7
+ end
8
+
9
+ def entries
10
+ Entry.find(:people => [id])
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe LetsFreckle::Configuration do
4
+ context "as DSL" do
5
+ it "should properly set and read config values" do
6
+ LetsFreckle.configure do
7
+ username "user"
8
+ account_host "userhost"
9
+ token "secret"
10
+ end
11
+
12
+ LetsFreckle.config.username.should == "user"
13
+ LetsFreckle.config.account_host.should == "userhost"
14
+ LetsFreckle.config.token.should == "secret"
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe LetsFreckle::Entry do
4
+ context "#all" do
5
+ it "should return all entries" do
6
+ LetsFreckle.configure do
7
+ username "username"
8
+ account_host "host"
9
+ token "secret"
10
+ end
11
+
12
+ stub_http_request(:get, LetsFreckle::Entry.url('entries')).to_return(:body => load_response('entries'))
13
+ entries = LetsFreckle::Entry.all
14
+ entries.size.should == 2
15
+
16
+ first_entry = entries.first
17
+ first_entry.description.should == 'api test description'
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe LetsFreckle::Project do
4
+ context "#all" do
5
+ it "should return all projects" do
6
+ LetsFreckle.configure do
7
+ username "username"
8
+ account_host "host"
9
+ token "secret"
10
+ end
11
+
12
+ stub_http_request(:get, LetsFreckle::Project.url('projects')).to_return(:body => load_response('projects'))
13
+ projects = LetsFreckle::Project.all
14
+ projects.size.should == 2
15
+
16
+ first_project = projects.first
17
+ first_project.name.should == 'TestProject1'
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe LetsFreckle::Tag do
4
+ context "#all" do
5
+ it "should return all tags" do
6
+ LetsFreckle.configure do
7
+ username "username"
8
+ account_host "host"
9
+ token "secret"
10
+ end
11
+
12
+ stub_http_request(:get, LetsFreckle::Tag.url('tags')).to_return(:body => load_response('tags'))
13
+ tags = LetsFreckle::Tag.all
14
+ tags.size.should == 2
15
+
16
+ first_tag = tags.first
17
+ first_tag.name.should == 'test tag 1'
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe LetsFreckle::User do
4
+ context "#all" do
5
+ it "should return all users" do
6
+ LetsFreckle.configure do
7
+ username "username"
8
+ account_host "host"
9
+ token "secret"
10
+ end
11
+
12
+ stub_http_request(:get, LetsFreckle::User.url('users')).to_return(:body => load_response('users'))
13
+ users = LetsFreckle::User.all
14
+ users.size.should == 2
15
+
16
+ first_user = users.first
17
+ first_user.email.should == 'apitest@letsfreckle.com'
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,55 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <entries type="array">
3
+ <entry>
4
+ <billable type="boolean">true</billable>
5
+ <created-at type="datetime">2011-05-25T13:15:35Z</created-at>
6
+ <date type="date">2011-11-25</date>
7
+ <description>api test description</description>
8
+ <description-text>freckle restful api test</description-text>
9
+ <id type="integer">986234</id>
10
+ <import-id type="integer" nil="true"></import-id>
11
+ <invoiced-at type="datetime" nil="true"></invoiced-at>
12
+ <minutes type="integer">30</minutes>
13
+ <project-id type="integer" nil="true"></project-id>
14
+ <project-invoice-id type="integer" nil="true"></project-invoice-id>
15
+ <recently-updated-at type="datetime">2011-05-25T13:15:35Z</recently-updated-at>
16
+ <time-from type="integer" nil="true"></time-from>
17
+ <time-to type="integer" nil="true"></time-to>
18
+ <updated-at type="datetime">2011-05-25T13:15:35Z</updated-at>
19
+ <url nil="true"></url>
20
+ <user-id type="integer">5543</user-id>
21
+ <tags type="array">
22
+ <tag>
23
+ <billable type="boolean">true</billable>
24
+ <id type="integer">23035</id>
25
+ <name>bulk import</name>
26
+ </tag>
27
+ </tags>
28
+ </entry>
29
+ <entry>
30
+ <billable type="boolean">true</billable>
31
+ <created-at type="datetime">2011-02-18T15:27:57Z</created-at>
32
+ <date type="date">2011-01-28</date>
33
+ <description>api test description</description>
34
+ <description-text></description-text>
35
+ <id type="integer">708805</id>
36
+ <import-id type="integer" nil="true"></import-id>
37
+ <invoiced-at type="datetime" nil="true"></invoiced-at>
38
+ <minutes type="integer">420</minutes>
39
+ <project-id type="integer">8475</project-id>
40
+ <project-invoice-id type="integer" nil="true"></project-invoice-id>
41
+ <recently-updated-at type="datetime">2011-02-18T15:27:57Z</recently-updated-at>
42
+ <time-from type="integer" nil="true"></time-from>
43
+ <time-to type="integer" nil="true"></time-to>
44
+ <updated-at type="datetime">2011-02-18T15:27:57Z</updated-at>
45
+ <url nil="true"></url>
46
+ <user-id type="integer">5543</user-id>
47
+ <tags type="array">
48
+ <tag>
49
+ <billable type="boolean">true</billable>
50
+ <id type="integer">123124</id>
51
+ <name>- instru</name>
52
+ </tag>
53
+ </tags>
54
+ </entry>
55
+ </entries>
@@ -0,0 +1,25 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <projects type="array">
3
+ <project>
4
+ <account-id type="integer">100</account-id>
5
+ <budget type="integer" nil="true"></budget>
6
+ <created-at type="datetime">2008-12-19T16:21:34Z</created-at>
7
+ <enabled type="boolean">true</enabled>
8
+ <id type="integer">1343</id>
9
+ <name>TestProject1</name>
10
+ <stepping type="integer">15</stepping>
11
+ <updated-at type="datetime">2008-12-19T16:21:34Z</updated-at>
12
+ <user-id type="integer" nil="true"></user-id>
13
+ </project>
14
+ <project>
15
+ <account-id type="integer">100</account-id>
16
+ <budget type="integer" nil="true"></budget>
17
+ <created-at type="datetime">2008-12-19T16:23:06Z</created-at>
18
+ <enabled type="boolean">true</enabled>
19
+ <id type="integer">1344</id>
20
+ <name>TestProject2</name>
21
+ <stepping type="integer">15</stepping>
22
+ <updated-at type="datetime">2008-12-19T16:23:06Z</updated-at>
23
+ <user-id type="integer" nil="true"></user-id>
24
+ </project>
25
+ </projects>
@@ -0,0 +1,19 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <tags type="array">
3
+ <tag>
4
+ <account-id type="integer">5039</account-id>
5
+ <billable type="boolean">true</billable>
6
+ <created-at type="datetime">2009-10-16T09:57:22Z</created-at>
7
+ <id type="integer">23035</id>
8
+ <name>test tag 1</name>
9
+ <updated-at type="datetime">2009-10-16T09:57:22Z</updated-at>
10
+ </tag>
11
+ <tag>
12
+ <account-id type="integer">5039</account-id>
13
+ <billable type="boolean">true</billable>
14
+ <created-at type="datetime">2009-10-16T09:04:50Z</created-at>
15
+ <id type="integer">23029</id>
16
+ <name>conf call</name>
17
+ <updated-at type="datetime">2009-10-16T09:04:50Z</updated-at>
18
+ </tag>
19
+ </tags>
@@ -0,0 +1,23 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <users type="array">
3
+ <user>
4
+ <email>apitest@letsfreckle.com</email>
5
+ <first-name>Test</first-name>
6
+ <id type="integer">5538</id>
7
+ <last-name>User</last-name>
8
+ <login>test</login>
9
+ <time-format>fraction</time-format>
10
+ <week-start>Sunday</week-start>
11
+ <permissions>integration, time, invoicing, reports, tags, expenses, projects, team, people, account, billing, import</permissions>
12
+ </user>
13
+ <user>
14
+ <email>apitest2@letsfreckle.com</email>
15
+ <first-name>Test2</first-name>
16
+ <id type="integer">5539</id>
17
+ <last-name>User</last-name>
18
+ <login>test2</login>
19
+ <time-format>fraction</time-format>
20
+ <week-start>Monday</week-start>
21
+ <permissions>integration, time, invoicing, reports, tags, expenses, projects, team</permissions>
22
+ </user>
23
+ </users>
@@ -0,0 +1,11 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'webmock/rspec'
5
+ require 'letsfreckle'
6
+
7
+
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+ RSpec.configure do |config|
10
+ config.include(WebMockHelper)
11
+ end
@@ -0,0 +1,5 @@
1
+ module WebMockHelper
2
+ def load_response(resource)
3
+ File.read(File.join(File.dirname(__FILE__), '/../responses', "#{resource}.xml.response"))
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,192 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: letsfreckle-client
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Ryan LeCompte
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-07-25 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: httparty
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ prerelease: false
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: hashie
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 0
42
+ version: "0"
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: &id003 !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ segments:
54
+ - 2
55
+ - 5
56
+ - 0
57
+ version: 2.5.0
58
+ type: :development
59
+ prerelease: false
60
+ version_requirements: *id003
61
+ - !ruby/object:Gem::Dependency
62
+ name: bundler
63
+ requirement: &id004 !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ segments:
69
+ - 1
70
+ - 0
71
+ - 0
72
+ version: 1.0.0
73
+ type: :development
74
+ prerelease: false
75
+ version_requirements: *id004
76
+ - !ruby/object:Gem::Dependency
77
+ name: jeweler
78
+ requirement: &id005 !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ~>
82
+ - !ruby/object:Gem::Version
83
+ segments:
84
+ - 1
85
+ - 6
86
+ - 4
87
+ version: 1.6.4
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *id005
91
+ - !ruby/object:Gem::Dependency
92
+ name: rcov
93
+ requirement: &id006 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ segments:
99
+ - 0
100
+ version: "0"
101
+ type: :development
102
+ prerelease: false
103
+ version_requirements: *id006
104
+ - !ruby/object:Gem::Dependency
105
+ name: webmock
106
+ requirement: &id007 !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ~>
110
+ - !ruby/object:Gem::Version
111
+ segments:
112
+ - 1
113
+ - 6
114
+ - 2
115
+ version: 1.6.2
116
+ type: :development
117
+ prerelease: false
118
+ version_requirements: *id007
119
+ description: Ruby client for letsfreckle.com API that supports entries, projects, tags, and users
120
+ email: lecompte@gmail.com
121
+ executables: []
122
+
123
+ extensions: []
124
+
125
+ extra_rdoc_files:
126
+ - LICENSE.txt
127
+ - README.rdoc
128
+ files:
129
+ - .document
130
+ - .rspec
131
+ - Gemfile
132
+ - Gemfile.lock
133
+ - LICENSE.txt
134
+ - README.rdoc
135
+ - Rakefile
136
+ - VERSION
137
+ - letsfreckle-client.gemspec
138
+ - lib/letsfreckle.rb
139
+ - lib/letsfreckle/client_resource.rb
140
+ - lib/letsfreckle/configuration.rb
141
+ - lib/letsfreckle/entry.rb
142
+ - lib/letsfreckle/error.rb
143
+ - lib/letsfreckle/extensions/mash.rb
144
+ - lib/letsfreckle/project.rb
145
+ - lib/letsfreckle/tag.rb
146
+ - lib/letsfreckle/user.rb
147
+ - spec/letsfreckle/configuration_spec.rb
148
+ - spec/letsfreckle/entry_spec.rb
149
+ - spec/letsfreckle/project_spec.rb
150
+ - spec/letsfreckle/tag_spec.rb
151
+ - spec/letsfreckle/user_spec.rb
152
+ - spec/responses/entries.xml.response
153
+ - spec/responses/projects.xml.response
154
+ - spec/responses/tags.xml.response
155
+ - spec/responses/users.xml.response
156
+ - spec/spec_helper.rb
157
+ - spec/support/webmock_helper.rb
158
+ has_rdoc: true
159
+ homepage: http://github.com/ryanlecompte/letsfreckle-client
160
+ licenses:
161
+ - MIT
162
+ post_install_message:
163
+ rdoc_options: []
164
+
165
+ require_paths:
166
+ - lib
167
+ required_ruby_version: !ruby/object:Gem::Requirement
168
+ none: false
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ hash: 24628150016863968
173
+ segments:
174
+ - 0
175
+ version: "0"
176
+ required_rubygems_version: !ruby/object:Gem::Requirement
177
+ none: false
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ segments:
182
+ - 0
183
+ version: "0"
184
+ requirements: []
185
+
186
+ rubyforge_project:
187
+ rubygems_version: 1.3.7
188
+ signing_key:
189
+ specification_version: 3
190
+ summary: Ruby client for letsfreckle.com API
191
+ test_files: []
192
+