letsfreckle-client 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+