harvested 0.5.3 → 0.6.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.
- data/Gemfile +2 -3
- data/HISTORY +2 -0
- data/Rakefile +1 -4
- data/VERSION +1 -1
- data/harvested.gemspec +5 -8
- data/lib/harvest/client.rb +6 -19
- data/lib/harvest/contact.rb +3 -15
- data/lib/harvest/expense.rb +3 -21
- data/lib/harvest/expense_category.rb +3 -12
- data/lib/harvest/invoice.rb +13 -45
- data/lib/harvest/invoice_category.rb +4 -13
- data/lib/harvest/line_item.rb +2 -10
- data/lib/harvest/model.rb +29 -18
- data/lib/harvest/project.rb +4 -41
- data/lib/harvest/rate_limit_status.rb +5 -11
- data/lib/harvest/task.rb +3 -14
- data/lib/harvest/task_assignment.rb +3 -16
- data/lib/harvest/time_entry.rb +8 -29
- data/lib/harvest/user.rb +4 -41
- data/lib/harvest/user_assignment.rb +9 -20
- data/spec/functional/reporting_spec.rb +6 -6
- data/spec/functional/time_tracking_spec.rb +13 -13
- data/spec/functional/users_spec.rb +16 -15
- data/spec/spec_helper.rb +7 -15
- data/spec/support/harvested_helpers.rb +10 -10
- metadata +8 -24
data/Gemfile
CHANGED
@@ -6,10 +6,9 @@ gem 'json'
|
|
6
6
|
|
7
7
|
group :development, :test do
|
8
8
|
gem "rspec", "~> 2"
|
9
|
-
gem 'ruby-debug', :platform => [:mri_18, :jruby]
|
10
|
-
gem 'ruby-debug19', :platform => :mri_19, :require => 'ruby-debug'
|
11
9
|
gem 'jruby-openssl', :platform => [:jruby], :require => false
|
12
10
|
gem "webmock"
|
13
11
|
gem "vcr"
|
14
12
|
gem 'jeweler', :require => false
|
15
|
-
|
13
|
+
gem 'debugger'
|
14
|
+
end
|
data/HISTORY
CHANGED
data/Rakefile
CHANGED
@@ -21,7 +21,7 @@ end
|
|
21
21
|
require 'rspec/core/rake_task'
|
22
22
|
RSpec::Core::RakeTask.new(:spec)
|
23
23
|
|
24
|
-
task :default => %w(spec
|
24
|
+
task :default => %w(spec)
|
25
25
|
|
26
26
|
begin
|
27
27
|
require 'yard'
|
@@ -38,6 +38,3 @@ task 'clean_remote' do
|
|
38
38
|
require "spec/support/harvested_helpers"
|
39
39
|
HarvestedHelpers.clean_remote
|
40
40
|
end
|
41
|
-
|
42
|
-
task :foo do
|
43
|
-
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.6.0
|
data/harvested.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "harvested"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.6.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Zach Moazeni"]
|
12
|
-
s.date = "2012-08-
|
12
|
+
s.date = "2012-08-23"
|
13
13
|
s.description = "Harvested wraps the Harvest API concisely without the use of Rails dependencies. More information about the Harvest API can be found on their website (http://www.getharvest.com/api). For support hit up the Mailing List (http://groups.google.com/group/harvested)"
|
14
14
|
s.email = "zach.moazeni@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -113,35 +113,32 @@ Gem::Specification.new do |s|
|
|
113
113
|
s.add_runtime_dependency(%q<hashie>, ["~> 1"])
|
114
114
|
s.add_runtime_dependency(%q<json>, [">= 0"])
|
115
115
|
s.add_development_dependency(%q<rspec>, ["~> 2"])
|
116
|
-
s.add_development_dependency(%q<ruby-debug>, [">= 0"])
|
117
|
-
s.add_development_dependency(%q<ruby-debug19>, [">= 0"])
|
118
116
|
s.add_development_dependency(%q<jruby-openssl>, [">= 0"])
|
119
117
|
s.add_development_dependency(%q<webmock>, [">= 0"])
|
120
118
|
s.add_development_dependency(%q<vcr>, [">= 0"])
|
121
119
|
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
120
|
+
s.add_development_dependency(%q<debugger>, [">= 0"])
|
122
121
|
else
|
123
122
|
s.add_dependency(%q<httparty>, [">= 0"])
|
124
123
|
s.add_dependency(%q<hashie>, ["~> 1"])
|
125
124
|
s.add_dependency(%q<json>, [">= 0"])
|
126
125
|
s.add_dependency(%q<rspec>, ["~> 2"])
|
127
|
-
s.add_dependency(%q<ruby-debug>, [">= 0"])
|
128
|
-
s.add_dependency(%q<ruby-debug19>, [">= 0"])
|
129
126
|
s.add_dependency(%q<jruby-openssl>, [">= 0"])
|
130
127
|
s.add_dependency(%q<webmock>, [">= 0"])
|
131
128
|
s.add_dependency(%q<vcr>, [">= 0"])
|
132
129
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
130
|
+
s.add_dependency(%q<debugger>, [">= 0"])
|
133
131
|
end
|
134
132
|
else
|
135
133
|
s.add_dependency(%q<httparty>, [">= 0"])
|
136
134
|
s.add_dependency(%q<hashie>, ["~> 1"])
|
137
135
|
s.add_dependency(%q<json>, [">= 0"])
|
138
136
|
s.add_dependency(%q<rspec>, ["~> 2"])
|
139
|
-
s.add_dependency(%q<ruby-debug>, [">= 0"])
|
140
|
-
s.add_dependency(%q<ruby-debug19>, [">= 0"])
|
141
137
|
s.add_dependency(%q<jruby-openssl>, [">= 0"])
|
142
138
|
s.add_dependency(%q<webmock>, [">= 0"])
|
143
139
|
s.add_dependency(%q<vcr>, [">= 0"])
|
144
140
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
141
|
+
s.add_dependency(%q<debugger>, [">= 0"])
|
145
142
|
end
|
146
143
|
end
|
147
144
|
|
data/lib/harvest/client.rb
CHANGED
@@ -10,26 +10,13 @@ module Harvest
|
|
10
10
|
# [+active?+] true|false on whether the client is active
|
11
11
|
# [+highrise_id+] (READONLY) the highrise id associated with this client
|
12
12
|
# [+update_at+] (READONLY) the last modification timestamp
|
13
|
-
class Client < Hashie::
|
13
|
+
class Client < Hashie::Mash
|
14
14
|
include Harvest::Model
|
15
|
-
|
15
|
+
|
16
16
|
api_path '/clients'
|
17
|
-
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
property :details
|
23
|
-
property :currency
|
24
|
-
property :currency_symbol
|
25
|
-
property :cache_version
|
26
|
-
property :created_at
|
27
|
-
property :updated_at
|
28
|
-
property :highrise_id
|
29
|
-
property :default_invoice_timeframe
|
30
|
-
property :last_invoice_kind
|
31
|
-
|
32
|
-
alias_method :active?, :active
|
33
|
-
alias_method :is_active=, :active=
|
18
|
+
def is_active=(val)
|
19
|
+
self.active = val
|
20
|
+
end
|
34
21
|
end
|
35
|
-
end
|
22
|
+
end
|
data/lib/harvest/contact.rb
CHANGED
@@ -11,21 +11,9 @@ module Harvest
|
|
11
11
|
# [+phone_office+] the office phone number of the contact
|
12
12
|
# [+phone_moble+] the moble phone number of the contact
|
13
13
|
# [+fax+] the fax number of the contact
|
14
|
-
class Contact < Hashie::
|
14
|
+
class Contact < Hashie::Mash
|
15
15
|
include Harvest::Model
|
16
|
-
|
16
|
+
|
17
17
|
api_path '/contacts'
|
18
|
-
|
19
|
-
property :id
|
20
|
-
property :client_id
|
21
|
-
property :email
|
22
|
-
property :first_name
|
23
|
-
property :last_name
|
24
|
-
property :phone_office
|
25
|
-
property :phone_mobile
|
26
|
-
property :fax
|
27
|
-
property :title
|
28
|
-
property :created_at
|
29
|
-
property :updated_at
|
30
18
|
end
|
31
|
-
end
|
19
|
+
end
|
data/lib/harvest/expense.rb
CHANGED
@@ -1,24 +1,10 @@
|
|
1
1
|
module Harvest
|
2
|
-
class Expense < Hashie::
|
2
|
+
class Expense < Hashie::Mash
|
3
3
|
include Harvest::Model
|
4
4
|
|
5
5
|
api_path '/expenses'
|
6
|
-
|
7
|
-
|
8
|
-
property :notes
|
9
|
-
property :units
|
10
|
-
property :total_cost
|
11
|
-
property :project_id
|
12
|
-
property :expense_category_id
|
13
|
-
property :user_id
|
14
|
-
property :spent_at
|
15
|
-
property :created_at
|
16
|
-
property :updated_at
|
17
|
-
property :is_billed
|
18
|
-
property :is_closed
|
19
|
-
property :invoice_id
|
20
|
-
property :has_receipt
|
21
|
-
property :receipt_url
|
6
|
+
delegate_methods(:billed? => :is_billed,
|
7
|
+
:closed? => :is_closed)
|
22
8
|
|
23
9
|
def initialize(args = {})
|
24
10
|
args = args.stringify_keys
|
@@ -37,9 +23,5 @@ module Harvest
|
|
37
23
|
hash[json_root].delete("receipt_url")
|
38
24
|
end
|
39
25
|
end
|
40
|
-
|
41
|
-
alias_method :billed?, :is_billed
|
42
|
-
alias_method :closed?, :is_closed
|
43
|
-
alias_method :has_receipt?, :has_receipt
|
44
26
|
end
|
45
27
|
end
|
@@ -1,19 +1,10 @@
|
|
1
1
|
module Harvest
|
2
|
-
class ExpenseCategory < Hashie::
|
2
|
+
class ExpenseCategory < Hashie::Mash
|
3
3
|
include Harvest::Model
|
4
4
|
api_path '/expense_categories'
|
5
|
-
|
6
|
-
property :id
|
7
|
-
property :name
|
8
|
-
property :unit_name
|
9
|
-
property :unit_price
|
10
|
-
property :deactivated
|
11
|
-
property :created_at
|
12
|
-
property :updated_at
|
13
|
-
property :cache_version
|
14
|
-
|
5
|
+
|
15
6
|
def active?
|
16
7
|
!deactivated
|
17
8
|
end
|
18
9
|
end
|
19
|
-
end
|
10
|
+
end
|
data/lib/harvest/invoice.rb
CHANGED
@@ -1,46 +1,14 @@
|
|
1
1
|
module Harvest
|
2
|
-
class Invoice < Hashie::
|
2
|
+
class Invoice < Hashie::Mash
|
3
3
|
include Harvest::Model
|
4
|
-
|
4
|
+
|
5
5
|
api_path '/invoices'
|
6
|
-
|
6
|
+
|
7
7
|
attr_reader :line_items
|
8
|
-
|
9
|
-
property :id
|
10
|
-
property :subject
|
11
|
-
property :number
|
12
|
-
property :created_at
|
13
|
-
property :updated_at
|
14
|
-
property :issued_at
|
15
|
-
property :due_at
|
16
|
-
property :due_at_human_format
|
17
|
-
property :due_amount
|
18
|
-
property :notes
|
19
|
-
property :recurring_invoice_id
|
20
|
-
property :period_start
|
21
|
-
property :period_end
|
22
|
-
property :discount
|
23
|
-
property :discount_amount
|
24
|
-
property :client_key
|
25
|
-
property :amount
|
26
|
-
property :tax
|
27
|
-
property :tax2
|
28
|
-
property :tax_amount
|
29
|
-
property :tax2_amount
|
30
|
-
property :csv_line_items
|
31
|
-
property :client_id
|
32
|
-
property :estimate_id
|
33
|
-
property :purchase_order
|
34
|
-
property :retainer_id
|
35
|
-
property :currency
|
36
|
-
property :state
|
37
|
-
property :kind
|
38
|
-
property :import_hours
|
39
|
-
property :import_expenses
|
40
|
-
|
8
|
+
|
41
9
|
def self.json_root; "doc"; end
|
42
10
|
# skip_json_root true
|
43
|
-
|
11
|
+
|
44
12
|
def initialize(args = {})
|
45
13
|
@line_items = []
|
46
14
|
args = args.stringify_keys
|
@@ -48,7 +16,7 @@ module Harvest
|
|
48
16
|
self.line_items = args.delete("line_items")
|
49
17
|
super
|
50
18
|
end
|
51
|
-
|
19
|
+
|
52
20
|
def line_items=(raw_or_rich)
|
53
21
|
unless raw_or_rich.nil?
|
54
22
|
@line_items = case raw_or_rich
|
@@ -59,13 +27,13 @@ module Harvest
|
|
59
27
|
end
|
60
28
|
end
|
61
29
|
end
|
62
|
-
|
30
|
+
|
63
31
|
def as_json(*options)
|
64
32
|
json = super(*options)
|
65
33
|
json[json_root]["csv_line_items"] = encode_csv(@line_items)
|
66
34
|
json
|
67
35
|
end
|
68
|
-
|
36
|
+
|
69
37
|
private
|
70
38
|
def decode_csv(string)
|
71
39
|
csv = CSV.parse(string)
|
@@ -73,19 +41,19 @@ module Harvest
|
|
73
41
|
csv.map! {|row| headers.zip(row) }
|
74
42
|
csv.map {|row| row.inject({}) {|h, tuple| h.update(tuple[0] => tuple[1]) } }
|
75
43
|
end
|
76
|
-
|
44
|
+
|
77
45
|
def encode_csv(line_items)
|
78
46
|
if line_items.empty?
|
79
47
|
""
|
80
48
|
else
|
81
49
|
header = %w(kind description quantity unit_price amount taxed taxed2 project_id)
|
82
|
-
|
50
|
+
|
83
51
|
# writing this in stdlib so we don't force 1.8 users to install FasterCSV and make gem dependencies wierd
|
84
52
|
if RUBY_VERSION =~ /1.8/
|
85
53
|
csv_data = ""
|
86
54
|
CSV.generate_row(header, header.size, csv_data)
|
87
55
|
line_items.each do |item|
|
88
|
-
row_data = header.inject([]) {|row, attr| row << item[attr] }
|
56
|
+
row_data = header.inject([]) {|row, attr| row << item[attr] }
|
89
57
|
CSV.generate_row(row_data, row_data.size, csv_data)
|
90
58
|
end
|
91
59
|
csv_data
|
@@ -93,11 +61,11 @@ module Harvest
|
|
93
61
|
CSV.generate do |csv|
|
94
62
|
csv << header
|
95
63
|
line_items.each do |item|
|
96
|
-
csv << header.inject([]) {|row, attr| row << item[attr] }
|
64
|
+
csv << header.inject([]) {|row, attr| row << item[attr] }
|
97
65
|
end
|
98
66
|
end
|
99
67
|
end
|
100
68
|
end
|
101
69
|
end
|
102
70
|
end
|
103
|
-
end
|
71
|
+
end
|
@@ -1,18 +1,9 @@
|
|
1
1
|
module Harvest
|
2
|
-
class InvoiceCategory < Hashie::
|
2
|
+
class InvoiceCategory < Hashie::Mash
|
3
3
|
include Harvest::Model
|
4
|
-
|
4
|
+
|
5
5
|
api_path '/invoice_item_categories'
|
6
6
|
def self.json_root; "category"; end
|
7
|
-
|
8
|
-
property :id
|
9
|
-
property :name
|
10
|
-
property :created_at
|
11
|
-
property :updated_at
|
12
|
-
property :use_as_expense
|
13
|
-
property :use_as_service
|
14
|
-
|
15
|
-
alias_method :use_as_expense?, :use_as_expense
|
16
|
-
alias_method :use_as_service?, :use_as_service
|
7
|
+
|
17
8
|
end
|
18
|
-
end
|
9
|
+
end
|
data/lib/harvest/line_item.rb
CHANGED
@@ -1,12 +1,4 @@
|
|
1
1
|
module Harvest
|
2
|
-
class LineItem < Hashie::
|
3
|
-
property :kind
|
4
|
-
property :description
|
5
|
-
property :quantity
|
6
|
-
property :unit_price
|
7
|
-
property :amount
|
8
|
-
property :taxed
|
9
|
-
property :taxed2
|
10
|
-
property :project_id
|
2
|
+
class LineItem < Hashie::Mash
|
11
3
|
end
|
12
|
-
end
|
4
|
+
end
|
data/lib/harvest/model.rb
CHANGED
@@ -4,12 +4,12 @@ module Harvest
|
|
4
4
|
base.send :include, InstanceMethods
|
5
5
|
base.send :extend, ClassMethods
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
8
|
module InstanceMethods
|
9
9
|
def to_json(*args)
|
10
10
|
as_json(*args).to_json(*args)
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
def as_json(args = {})
|
14
14
|
inner_json = self.to_hash.stringify_keys
|
15
15
|
inner_json.delete("cache_version")
|
@@ -19,13 +19,13 @@ module Harvest
|
|
19
19
|
{ self.class.json_root => inner_json }
|
20
20
|
end
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
def to_i; id; end
|
24
|
-
|
24
|
+
|
25
25
|
def ==(other)
|
26
26
|
id == other.id
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
def impersonated_user_id
|
30
30
|
if respond_to?(:of_user) && respond_to?(:user_id)
|
31
31
|
of_user || user_id
|
@@ -35,41 +35,41 @@ module Harvest
|
|
35
35
|
of_user
|
36
36
|
end
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
def json_root
|
40
40
|
self.class.json_root
|
41
41
|
end
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
module ClassMethods
|
45
45
|
# This sets the API path so the API collections can use them in an agnostic way
|
46
46
|
# @return [void]
|
47
47
|
def api_path(path = nil)
|
48
48
|
@_api_path ||= path
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
def skip_json_root(skip = nil)
|
52
52
|
@_skip_json_root ||= skip
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
55
|
def skip_json_root?
|
56
56
|
@_skip_json_root == true
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
def parse(json)
|
60
60
|
parsed = String === json ? JSON.parse(json) : json
|
61
61
|
Array.wrap(parsed).map {|attrs| skip_json_root? ? new(attrs) : new(attrs[json_root])}
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
def json_root
|
65
65
|
Harvest::Model::Utility.underscore(
|
66
66
|
Harvest::Model::Utility.demodulize(to_s)
|
67
67
|
)
|
68
68
|
end
|
69
|
-
|
69
|
+
|
70
70
|
def wrap(model_or_attrs)
|
71
71
|
case model_or_attrs
|
72
|
-
when Hashie::
|
72
|
+
when Hashie::Mash
|
73
73
|
model_or_attrs
|
74
74
|
when Hash
|
75
75
|
new(model_or_attrs)
|
@@ -77,13 +77,24 @@ module Harvest
|
|
77
77
|
model_or_attrs
|
78
78
|
end
|
79
79
|
end
|
80
|
+
|
81
|
+
def delegate_methods(options)
|
82
|
+
raise "no methods given" if options.empty?
|
83
|
+
options.each do |source, dest|
|
84
|
+
class_eval <<-EOV
|
85
|
+
def #{source}
|
86
|
+
#{dest}
|
87
|
+
end
|
88
|
+
EOV
|
89
|
+
end
|
90
|
+
end
|
80
91
|
end
|
81
|
-
|
92
|
+
|
82
93
|
module Utility
|
83
94
|
class << self
|
84
|
-
|
95
|
+
|
85
96
|
# Both methods are shamelessly ripped from https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflector/inflections.rb
|
86
|
-
|
97
|
+
|
87
98
|
# Removes the module part from the expression in the string.
|
88
99
|
#
|
89
100
|
# Examples:
|
@@ -92,7 +103,7 @@ module Harvest
|
|
92
103
|
def demodulize(class_name_in_module)
|
93
104
|
class_name_in_module.to_s.gsub(/^.*::/, '')
|
94
105
|
end
|
95
|
-
|
106
|
+
|
96
107
|
# Makes an underscored, lowercase form from the expression in the string.
|
97
108
|
#
|
98
109
|
# Changes '::' to '/' to convert namespaces to paths.
|
@@ -117,4 +128,4 @@ module Harvest
|
|
117
128
|
end
|
118
129
|
end
|
119
130
|
end
|
120
|
-
end
|
131
|
+
end
|
data/lib/harvest/project.rb
CHANGED
@@ -22,58 +22,21 @@ module Harvest
|
|
22
22
|
# [+active_task_assignments_count+] (READONLY) the number of active task assignments
|
23
23
|
# [+created_at+] (READONLY) when the project was created
|
24
24
|
# [+updated_at+] (READONLY) when the project was updated
|
25
|
-
class Project < Hashie::
|
25
|
+
class Project < Hashie::Mash
|
26
26
|
include Harvest::Model
|
27
27
|
|
28
28
|
api_path '/projects'
|
29
29
|
|
30
|
-
property :id
|
31
|
-
property :client_id
|
32
|
-
property :name
|
33
|
-
property :code
|
34
|
-
property :notes
|
35
|
-
property :fees
|
36
|
-
property :active
|
37
|
-
property :billable
|
38
|
-
property :budget
|
39
|
-
property :budget_by
|
40
|
-
property :hourly_rate
|
41
|
-
property :bill_by
|
42
|
-
property :created_at
|
43
|
-
property :updated_at
|
44
|
-
property :notify_when_over_budget
|
45
|
-
property :over_budget_notification_percentage
|
46
|
-
property :show_budget_to_all
|
47
|
-
property :basecamp_id
|
48
|
-
property :highrise_deal_id
|
49
|
-
property :active_task_assignments_count
|
50
|
-
property :over_budget_notified_at
|
51
|
-
property :earliest_record_at
|
52
|
-
property :cost_budget
|
53
|
-
property :cost_budget_include_expenses
|
54
|
-
property :latest_record_at
|
55
|
-
property :estimate_by
|
56
|
-
property :hint_earliest_record_at
|
57
|
-
property :hint_latest_record_at
|
58
|
-
property :active_user_assignments_count
|
59
|
-
property :cache_version
|
60
|
-
property :estimate
|
61
|
-
|
62
|
-
alias_method :active?, :active
|
63
|
-
alias_method :billable?, :billable
|
64
|
-
alias_method :notify_when_over_budget?, :notify_when_over_budget
|
65
|
-
alias_method :show_budget_to_all?, :show_budget_to_all
|
66
|
-
|
67
30
|
def as_json(args = {})
|
68
31
|
super(args).tap do |json|
|
69
32
|
json[json_root].delete("hint_earliest_record_at")
|
70
33
|
json[json_root].delete("hint_latest_record_at")
|
71
34
|
end
|
72
35
|
end
|
73
|
-
|
36
|
+
|
74
37
|
def self.parse(json)
|
75
38
|
json = String === json ? JSON.parse(json) : json
|
76
|
-
Array.wrap(json).each do |attrs|
|
39
|
+
Array.wrap(json).each do |attrs|
|
77
40
|
# need to cleanup some attributes
|
78
41
|
project_attrs = attrs[json_root] || {}
|
79
42
|
project_attrs["hint_latest_record_at"] = project_attrs.delete("hint-latest-record-at")
|
@@ -82,4 +45,4 @@ module Harvest
|
|
82
45
|
super(json)
|
83
46
|
end
|
84
47
|
end
|
85
|
-
end
|
48
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Harvest
|
2
|
-
|
2
|
+
|
3
3
|
# The model that contains the information about the user's rate limit
|
4
4
|
#
|
5
5
|
# == Fields
|
@@ -8,17 +8,11 @@ module Harvest
|
|
8
8
|
# [+timeframe_limit+] The amount of seconds before a rate limit refresh occurs
|
9
9
|
# [+max_calls+] The number of requests you can make within the +timeframe_limit+
|
10
10
|
# [+lockout_seconds+] If you exceed the rate limit, how long you will be locked out from Harvest
|
11
|
-
class RateLimitStatus < Hashie::
|
11
|
+
class RateLimitStatus < Hashie::Mash
|
12
12
|
include Harvest::Model
|
13
|
-
|
13
|
+
|
14
14
|
skip_json_root true
|
15
|
-
|
16
|
-
property :last_access_at
|
17
|
-
property :count
|
18
|
-
property :timeframe_limit
|
19
|
-
property :max_calls
|
20
|
-
property :lockout_seconds
|
21
|
-
|
15
|
+
|
22
16
|
# Returns true if the user is over their rate limit
|
23
17
|
# @return [Boolean]
|
24
18
|
# @see http://www.getharvest.com/api
|
@@ -26,4 +20,4 @@ module Harvest
|
|
26
20
|
count > max_calls
|
27
21
|
end
|
28
22
|
end
|
29
|
-
end
|
23
|
+
end
|
data/lib/harvest/task.rb
CHANGED
@@ -9,25 +9,14 @@ module Harvest
|
|
9
9
|
# [+deactivated+] whether the task is deactivated
|
10
10
|
# [+hourly_rate+] what the default hourly rate for the task is
|
11
11
|
# [+default?+] whether to add this task to new projects by default
|
12
|
-
class Task < Hashie::
|
12
|
+
class Task < Hashie::Mash
|
13
13
|
include Harvest::Model
|
14
14
|
|
15
15
|
api_path '/tasks'
|
16
|
+
delegate_methods :default? => :is_default
|
16
17
|
|
17
|
-
property :id
|
18
|
-
property :name
|
19
|
-
property :billable_by_default
|
20
|
-
property :deactivated
|
21
|
-
property :default_hourly_rate
|
22
|
-
property :is_default
|
23
|
-
property :created_at
|
24
|
-
property :updated_at
|
25
|
-
property :cache_version
|
26
|
-
|
27
18
|
def active?
|
28
19
|
!deactivated
|
29
20
|
end
|
30
|
-
|
31
|
-
alias_method :default?, :is_default
|
32
21
|
end
|
33
|
-
end
|
22
|
+
end
|
@@ -1,25 +1,14 @@
|
|
1
1
|
module Harvest
|
2
|
-
class TaskAssignment < Hashie::
|
2
|
+
class TaskAssignment < Hashie::Mash
|
3
3
|
include Harvest::Model
|
4
4
|
|
5
|
-
property :id
|
6
|
-
property :task_id
|
7
|
-
property :project_id
|
8
|
-
property :billable
|
9
|
-
property :deactivated
|
10
|
-
property :hourly_rate
|
11
|
-
property :budget
|
12
|
-
property :estimate
|
13
|
-
property :created_at
|
14
|
-
property :updated_at
|
15
|
-
|
16
5
|
def initialize(args = {})
|
17
6
|
args = args.stringify_keys
|
18
7
|
self.task = args.delete("task") if args["task"]
|
19
8
|
self.project = args.delete("project") if args["project"]
|
20
9
|
super
|
21
10
|
end
|
22
|
-
|
11
|
+
|
23
12
|
def task=(task)
|
24
13
|
self["task_id"] = task.to_i
|
25
14
|
end
|
@@ -35,7 +24,5 @@ module Harvest
|
|
35
24
|
def task_as_json
|
36
25
|
{"task" => {"id" => task_id}}
|
37
26
|
end
|
38
|
-
|
39
|
-
alias_method :billable?, :billable
|
40
27
|
end
|
41
|
-
end
|
28
|
+
end
|
data/lib/harvest/time_entry.rb
CHANGED
@@ -1,46 +1,25 @@
|
|
1
1
|
module Harvest
|
2
|
-
class TimeEntry < Hashie::
|
2
|
+
class TimeEntry < Hashie::Mash
|
3
3
|
include Harvest::Model
|
4
|
-
|
5
|
-
property :id
|
6
|
-
property :client
|
7
|
-
property :hours
|
8
|
-
property :notes
|
9
|
-
|
10
|
-
property :project_id
|
11
|
-
property :task_id
|
12
|
-
property :project
|
13
|
-
property :task
|
14
|
-
property :spent_at
|
15
|
-
property :created_at
|
16
|
-
property :updated_at
|
17
|
-
property :user_id
|
18
|
-
property :of_user
|
19
|
-
property :is_closed
|
20
|
-
property :is_billed
|
21
|
-
property :timer_started_at
|
22
|
-
property :adjustment_record
|
23
|
-
property :hours_without_timer
|
24
|
-
|
4
|
+
|
25
5
|
skip_json_root true
|
26
|
-
|
6
|
+
delegate_methods(:closed? => :is_closed,
|
7
|
+
:billed? => :is_billed)
|
8
|
+
|
27
9
|
def initialize(args = {})
|
28
10
|
args = args.stringify_keys
|
29
11
|
self.spent_at = args.delete("spent_at") if args["spent_at"]
|
30
12
|
super
|
31
13
|
end
|
32
|
-
|
14
|
+
|
33
15
|
def spent_at=(date)
|
34
16
|
self["spent_at"] = (String === date ? Time.parse(date) : date)
|
35
17
|
end
|
36
|
-
|
18
|
+
|
37
19
|
def as_json(args = {})
|
38
|
-
super(args).stringify_keys.tap do |hash|
|
20
|
+
super(args).stringify_keys.tap do |hash|
|
39
21
|
hash.update("spent_at" => (spent_at.nil? ? nil : spent_at.to_time.xmlschema))
|
40
22
|
end
|
41
23
|
end
|
42
|
-
|
43
|
-
alias_method :closed?, :is_closed
|
44
|
-
alias_method :billed?, :is_billed
|
45
24
|
end
|
46
25
|
end
|
data/lib/harvest/user.rb
CHANGED
@@ -15,51 +15,14 @@ module Harvest
|
|
15
15
|
# [+contractor?+] whether the user is a contractor
|
16
16
|
# [+contractor?+] whether the user is a contractor
|
17
17
|
# [+timezone+] the timezone for the user.
|
18
|
-
class User < Hashie::
|
18
|
+
class User < Hashie::Mash
|
19
19
|
include Harvest::Model
|
20
20
|
|
21
21
|
api_path '/people'
|
22
|
-
property :id
|
23
|
-
property :email
|
24
|
-
property :first_name
|
25
|
-
property :last_name
|
26
|
-
property :has_access_to_all_future_projects
|
27
|
-
property :default_hourly_rate
|
28
|
-
property :is_active
|
29
|
-
property :is_admin
|
30
|
-
property :is_contractor
|
31
|
-
property :telephone
|
32
|
-
property :department
|
33
|
-
property :timezone
|
34
|
-
property :password
|
35
|
-
property :first_timer
|
36
|
-
property :wants_newsletter
|
37
|
-
property :preferred_project_status_reports_screen
|
38
|
-
property :preferred_approval_screen
|
39
|
-
property :created_at
|
40
|
-
property :updated_at
|
41
|
-
property :twitter_username
|
42
|
-
property :preferred_entry_method
|
43
|
-
property :default_time_project_id
|
44
|
-
property :default_task_id
|
45
|
-
property :default_expense_category_id
|
46
|
-
property :opensocial_identifier
|
47
|
-
property :duplicate_timesheet_wants_notes
|
48
|
-
property :wants_timesheet_duplication
|
49
|
-
property :cache_version
|
50
|
-
property :email_after_submit
|
51
|
-
property :default_expense_project_id
|
52
|
-
property :identity_url
|
53
|
-
property :timestamp_timers
|
54
|
-
property :weekly_digest_sent_on
|
55
|
-
property :wants_weekly_digest
|
56
|
-
property :password_change_required
|
57
|
-
property :has_timesheet_2012_beta
|
58
|
-
property :timesheet_2012_beta_control_group
|
59
22
|
|
60
|
-
|
61
|
-
|
62
|
-
|
23
|
+
delegate_methods(:active? => :is_active,
|
24
|
+
:admin? => :is_admin,
|
25
|
+
:contractor? => :is_contractor)
|
63
26
|
|
64
27
|
def initialize(args = {})
|
65
28
|
args = args.stringify_keys
|
@@ -1,41 +1,30 @@
|
|
1
1
|
module Harvest
|
2
|
-
class UserAssignment < Hashie::
|
2
|
+
class UserAssignment < Hashie::Mash
|
3
3
|
include Harvest::Model
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
property :project_id
|
8
|
-
property :deactivated
|
9
|
-
property :is_project_manager
|
10
|
-
property :hourly_rate
|
11
|
-
property :created_at
|
12
|
-
property :updated_at
|
13
|
-
property :budget
|
14
|
-
property :estimate
|
15
|
-
|
4
|
+
|
5
|
+
delegate_methods :project_manager? => :is_project_manager
|
6
|
+
|
16
7
|
def initialize(args = {})
|
17
8
|
args = args.stringify_keys
|
18
9
|
self.user = args.delete("user") if args["user"]
|
19
10
|
self.project = args.delete("project") if args["project"]
|
20
11
|
super
|
21
12
|
end
|
22
|
-
|
13
|
+
|
23
14
|
def user=(user)
|
24
15
|
self["user_id"] = user.to_i
|
25
16
|
end
|
26
|
-
|
17
|
+
|
27
18
|
def project=(project)
|
28
19
|
self["project_id"] = project.to_i
|
29
20
|
end
|
30
|
-
|
21
|
+
|
31
22
|
def active?
|
32
23
|
!deactivated
|
33
24
|
end
|
34
|
-
|
25
|
+
|
35
26
|
def user_as_json
|
36
27
|
{"user" => {"id" => user_id}}
|
37
28
|
end
|
38
|
-
|
39
|
-
alias_method :project_manager?, :is_project_manager
|
40
29
|
end
|
41
|
-
end
|
30
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe 'harvest reporting' do
|
3
|
+
describe 'harvest reporting' do
|
4
4
|
it 'allows project and people entry reporting' do
|
5
5
|
cassette("reports1") do
|
6
6
|
user = harvest.users.create(
|
@@ -20,8 +20,8 @@ describe 'harvest reporting' do
|
|
20
20
|
harvest.user_assignments.create("project" => project1, "user" => user)
|
21
21
|
harvest.user_assignments.create("project" => project2, "user" => user)
|
22
22
|
|
23
|
-
entry1 = harvest.time.create("notes" => "billable entry1", "hours" => 3, "spent_at" => "12/28
|
24
|
-
entry2 = harvest.time.create("notes" => "non billable entry2", "hours" => 6, "spent_at" => "12/28
|
23
|
+
entry1 = harvest.time.create("notes" => "billable entry1", "hours" => 3, "spent_at" => "2009/12/28", "task_id" => task1.id, "project_id" => project1.id, "of_user" => user.id)
|
24
|
+
entry2 = harvest.time.create("notes" => "non billable entry2", "hours" => 6, "spent_at" => "2009/12/28", "task_id" => task2.id, "project_id" => project2.id, "of_user" => user.id)
|
25
25
|
|
26
26
|
harvest.reports.time_by_project(project1, Time.utc(2009, 12, 20), Time.utc(2009,12,30)).first.should == entry1
|
27
27
|
|
@@ -40,7 +40,7 @@ describe 'harvest reporting' do
|
|
40
40
|
|
41
41
|
harvest.reports.time_by_user(user, Time.utc(2009, 12, 20), Time.utc(2009,12,30), :billable => true).first.should == entry1
|
42
42
|
harvest.reports.time_by_user(user, Time.utc(2009, 12, 20), Time.utc(2009,12,30), :billable => false).first.should == entry2
|
43
|
-
|
43
|
+
|
44
44
|
client2 = harvest.clients.create("name" => "Phil's Sandwich Shop")
|
45
45
|
harvest.reports.projects_by_client(client).map(&:id).to_set.should == [project1, project2].map(&:id).to_set
|
46
46
|
harvest.reports.projects_by_client(client2).should == []
|
@@ -69,9 +69,9 @@ describe 'harvest reporting' do
|
|
69
69
|
"project_id" => project.id,
|
70
70
|
"user_id" => user.id
|
71
71
|
)
|
72
|
-
|
72
|
+
|
73
73
|
harvest.reports.expenses_by_user(user, Time.utc(2009, 12, 20), Time.utc(2009,12,30)).first.should == expense
|
74
|
-
|
74
|
+
|
75
75
|
my_user = harvest.users.all.detect {|u| u.email == credentials["username"]}
|
76
76
|
my_user.should_not be_nil
|
77
77
|
harvest.reports.expenses_by_user(my_user, Time.utc(2009, 12, 20), Time.utc(2009,12,30)).should == []
|
@@ -7,23 +7,23 @@ describe 'harvest time tracking' do
|
|
7
7
|
project = harvest.projects.create("name" => "Tracking Project", "client_id" => client.id)
|
8
8
|
harvest.projects.create_task(project, "A billable task")
|
9
9
|
task = harvest.tasks.all.detect {|t| t.name == "A billable task"}
|
10
|
-
|
11
|
-
entry = harvest.time.create("notes" => "Test api support", "hours" => 3, "spent_at" => "12/28
|
10
|
+
|
11
|
+
entry = harvest.time.create("notes" => "Test api support", "hours" => 3, "spent_at" => "2009/12/28", "task_id" => task.id, "project_id" => project.id)
|
12
12
|
entry.notes.should == "Test api support"
|
13
|
-
|
13
|
+
|
14
14
|
entry.notes = "Upgraded to JSON"
|
15
15
|
entry = harvest.time.update(entry)
|
16
16
|
entry.notes.should == "Upgraded to JSON"
|
17
|
-
|
17
|
+
|
18
18
|
harvest.time.delete(entry)
|
19
19
|
harvest.time.all(Time.utc(2009, 12, 28)).should == []
|
20
20
|
end
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
it 'allows you to save entries for a different user' do
|
24
24
|
cassette("time_tracking2") do
|
25
25
|
user = harvest.users.create(
|
26
|
-
"email" => "frank@example.com",
|
26
|
+
"email" => "frank@example.com",
|
27
27
|
"first_name" => "Frank",
|
28
28
|
"last_name" => "Doe",
|
29
29
|
"password" => "secure"
|
@@ -33,21 +33,21 @@ describe 'harvest time tracking' do
|
|
33
33
|
harvest.user_assignments.create("project" => project, "user" => user)
|
34
34
|
harvest.projects.create_task(project, "A billable task for tuxes")
|
35
35
|
task = harvest.tasks.all.detect {|t| t.name == "A billable task for tuxes"}
|
36
|
-
|
37
|
-
entry = harvest.time.create("notes" => "Test api support", "hours" => 3, "spent_at" => "12/28
|
36
|
+
|
37
|
+
entry = harvest.time.create("notes" => "Test api support", "hours" => 3, "spent_at" => "2009/12/28", "task_id" => task.id, "project_id" => project.id, "of_user" => user.id)
|
38
38
|
harvest.time.all(Time.utc(2009, 12, 28), user).should == [entry]
|
39
|
-
|
39
|
+
|
40
40
|
entry.notes = "Updating notes"
|
41
41
|
entry = harvest.time.update(entry, user)
|
42
42
|
entry.notes.should == "Updating notes"
|
43
|
-
|
43
|
+
|
44
44
|
entry = harvest.time.find(entry, user)
|
45
45
|
entry.notes.should == "Updating notes"
|
46
|
-
|
46
|
+
|
47
47
|
harvest.time.delete(entry, user)
|
48
48
|
harvest.time.all(Time.utc(2009, 12, 28), user).should == []
|
49
49
|
end
|
50
50
|
end
|
51
|
-
|
51
|
+
|
52
52
|
it 'allows toggling of timers'
|
53
|
-
end
|
53
|
+
end
|
@@ -7,60 +7,61 @@ describe 'harvest users' do
|
|
7
7
|
"first_name" => "Edgar",
|
8
8
|
"last_name" => "Ruth",
|
9
9
|
"email" => "edgar@ruth.com",
|
10
|
-
"password" => "mypassword",
|
11
10
|
"timezone" => "cst",
|
12
11
|
"is_admin" => "false",
|
13
12
|
"telephone" => "444-4444"
|
14
13
|
)
|
15
|
-
user.id.should_not
|
16
|
-
|
14
|
+
user.id.should_not be_nil
|
15
|
+
|
17
16
|
user.first_name = "Joey"
|
18
17
|
user = harvest.users.update(user)
|
19
18
|
user.first_name.should == "Joey"
|
20
|
-
|
19
|
+
|
21
20
|
id = harvest.users.delete(user)
|
22
21
|
harvest.users.all.map(&:id).should_not include(id)
|
23
22
|
end
|
24
23
|
end
|
25
|
-
|
24
|
+
|
26
25
|
it "allows activating and deactivating users" do
|
27
26
|
cassette("users2") do
|
28
27
|
user = harvest.users.create(
|
29
28
|
"first_name" => "John",
|
30
29
|
"last_name" => "Ruth",
|
31
30
|
"email" => "john@ruth.com",
|
32
|
-
"password" => "mypassword",
|
33
31
|
"timezone" => "cst",
|
34
32
|
"is_admin" => "false",
|
35
33
|
"telephone" => "444-4444"
|
36
34
|
)
|
37
35
|
user.should be_active
|
38
|
-
|
36
|
+
|
39
37
|
user = harvest.users.deactivate(user)
|
40
38
|
user.should_not be_active
|
41
|
-
|
39
|
+
|
42
40
|
user = harvest.users.activate(user)
|
43
41
|
user.should be_active
|
42
|
+
|
43
|
+
harvest.users.delete(user)
|
44
44
|
end
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
it "allows password resets" do
|
48
48
|
cassette("users3") do
|
49
|
+
pending "Something is wrong with resetting passwords"
|
49
50
|
user = harvest.users.create(
|
50
51
|
"first_name" => "Timmy",
|
51
52
|
"last_name" => "Ruth",
|
52
53
|
"email" => "timmy@ruth.com",
|
53
|
-
"password" => "mypassword",
|
54
54
|
"timezone" => "cst",
|
55
55
|
"is_admin" => "false",
|
56
56
|
"telephone" => "444-4444"
|
57
57
|
)
|
58
58
|
user.should be_active
|
59
|
-
|
59
|
+
|
60
60
|
harvest.users.reset_password(user) # nothing else to assert
|
61
|
+
harvest.users.delete(user)
|
61
62
|
end
|
62
63
|
end
|
63
|
-
|
64
|
+
|
64
65
|
context "assignments" do
|
65
66
|
it "allows adding, updating, and removing users from projects" do
|
66
67
|
cassette('users4') do
|
@@ -85,10 +86,10 @@ describe 'harvest users' do
|
|
85
86
|
"is_admin" => "false",
|
86
87
|
"telephone" => "444-4444"
|
87
88
|
)
|
88
|
-
|
89
|
+
|
89
90
|
|
90
91
|
assignment = harvest.user_assignments.create("project" => project, "user" => user)
|
91
|
-
|
92
|
+
|
92
93
|
assignment.hourly_rate = 100
|
93
94
|
assignment = harvest.user_assignments.update(assignment)
|
94
95
|
assignment.hourly_rate.should == "100.0"
|
@@ -99,4 +100,4 @@ describe 'harvest users' do
|
|
99
100
|
end
|
100
101
|
end
|
101
102
|
end
|
102
|
-
end
|
103
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -4,36 +4,28 @@ require 'vcr'
|
|
4
4
|
|
5
5
|
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require File.expand_path(f) }
|
6
6
|
|
7
|
-
VCR.
|
7
|
+
VCR.configure do |c|
|
8
8
|
c.cassette_library_dir = '.cassettes'
|
9
|
-
c.
|
9
|
+
c.hook_into :webmock
|
10
10
|
end
|
11
11
|
|
12
|
+
FileUtils.rm(Dir["#{VCR.configuration.cassette_library_dir}/*"]) if ENV['VCR_REFRESH'] == 'true'
|
13
|
+
|
12
14
|
RSpec.configure do |config|
|
13
15
|
config.include HarvestedHelpers
|
14
|
-
|
16
|
+
|
15
17
|
config.before(:suite) do
|
16
18
|
WebMock.allow_net_connect!
|
17
19
|
cassette("clean") do
|
18
20
|
HarvestedHelpers.clean_remote
|
19
21
|
end
|
20
22
|
end
|
21
|
-
|
23
|
+
|
22
24
|
config.before(:each) do
|
23
25
|
WebMock.allow_net_connect!
|
24
26
|
end
|
25
|
-
|
27
|
+
|
26
28
|
def cassette(*args)
|
27
|
-
if ENV['CACHE'] == "false"
|
28
|
-
if args.last.is_a?(Hash)
|
29
|
-
last = args.pop
|
30
|
-
last[:record] = :all
|
31
|
-
args << last
|
32
|
-
else
|
33
|
-
args << {:record => :all}
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
29
|
VCR.use_cassette(*args) do
|
38
30
|
yield
|
39
31
|
end
|
@@ -4,33 +4,33 @@ module HarvestedHelpers
|
|
4
4
|
@credentials ||= YAML.load_file("#{File.dirname(__FILE__)}/harvest_credentials.yml")
|
5
5
|
end
|
6
6
|
def credentials; HarvestedHelpers.credentials; end
|
7
|
-
|
7
|
+
|
8
8
|
def self.simple_harvest
|
9
9
|
Harvest.client(credentials["subdomain"], credentials["username"], credentials["password"], :ssl => true)
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
# def connect_to_harvest
|
13
13
|
# @harvest = Harvest.hardy_client(credentials["subdomain"], credentials["username"], credentials["password"], :ssl => true)
|
14
14
|
# end
|
15
|
-
|
15
|
+
|
16
16
|
# def harvest; @harvest; end
|
17
17
|
def harvest; @harvest ||= HarvestedHelpers.simple_harvest; end
|
18
|
-
|
18
|
+
|
19
19
|
def hardy_harvest
|
20
20
|
Harvest.hardy_client(credentials["subdomain"], credentials["username"], credentials["password"], :ssl => true)
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
def self.clean_remote
|
24
24
|
harvest = simple_harvest
|
25
25
|
harvest.users.all.each do |u|
|
26
|
-
harvest.reports.expenses_by_user(u, Time.utc(2000, 1, 1), Time.utc(
|
26
|
+
harvest.reports.expenses_by_user(u, Time.utc(2000, 1, 1), Time.utc(2013, 6,21)).each do |expense|
|
27
27
|
harvest.expenses.delete(expense, u)
|
28
28
|
end
|
29
|
-
|
30
|
-
harvest.reports.time_by_user(u, Time.utc(2000, 1, 1), Time.utc(
|
29
|
+
|
30
|
+
harvest.reports.time_by_user(u, Time.utc(2000, 1, 1), Time.utc(2013, 6,21)).each do |time|
|
31
31
|
harvest.time.delete(time, u)
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
harvest.users.delete(u) if u.email != credentials["username"]
|
35
35
|
end
|
36
36
|
|
@@ -41,4 +41,4 @@ module HarvestedHelpers
|
|
41
41
|
harvest.send(collection).all.each {|m| harvest.send(collection).delete(m) }
|
42
42
|
end
|
43
43
|
end
|
44
|
-
end
|
44
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: harvested
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-08-
|
12
|
+
date: 2012-08-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: httparty
|
@@ -76,23 +76,7 @@ dependencies:
|
|
76
76
|
- !ruby/object:Gem::Version
|
77
77
|
version: '2'
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
|
-
name:
|
80
|
-
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
|
-
requirements:
|
83
|
-
- - ! '>='
|
84
|
-
- !ruby/object:Gem::Version
|
85
|
-
version: '0'
|
86
|
-
type: :development
|
87
|
-
prerelease: false
|
88
|
-
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
|
-
requirements:
|
91
|
-
- - ! '>='
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: '0'
|
94
|
-
- !ruby/object:Gem::Dependency
|
95
|
-
name: ruby-debug19
|
79
|
+
name: jruby-openssl
|
96
80
|
requirement: !ruby/object:Gem::Requirement
|
97
81
|
none: false
|
98
82
|
requirements:
|
@@ -108,7 +92,7 @@ dependencies:
|
|
108
92
|
- !ruby/object:Gem::Version
|
109
93
|
version: '0'
|
110
94
|
- !ruby/object:Gem::Dependency
|
111
|
-
name:
|
95
|
+
name: webmock
|
112
96
|
requirement: !ruby/object:Gem::Requirement
|
113
97
|
none: false
|
114
98
|
requirements:
|
@@ -124,7 +108,7 @@ dependencies:
|
|
124
108
|
- !ruby/object:Gem::Version
|
125
109
|
version: '0'
|
126
110
|
- !ruby/object:Gem::Dependency
|
127
|
-
name:
|
111
|
+
name: vcr
|
128
112
|
requirement: !ruby/object:Gem::Requirement
|
129
113
|
none: false
|
130
114
|
requirements:
|
@@ -140,7 +124,7 @@ dependencies:
|
|
140
124
|
- !ruby/object:Gem::Version
|
141
125
|
version: '0'
|
142
126
|
- !ruby/object:Gem::Dependency
|
143
|
-
name:
|
127
|
+
name: jeweler
|
144
128
|
requirement: !ruby/object:Gem::Requirement
|
145
129
|
none: false
|
146
130
|
requirements:
|
@@ -156,7 +140,7 @@ dependencies:
|
|
156
140
|
- !ruby/object:Gem::Version
|
157
141
|
version: '0'
|
158
142
|
- !ruby/object:Gem::Dependency
|
159
|
-
name:
|
143
|
+
name: debugger
|
160
144
|
requirement: !ruby/object:Gem::Requirement
|
161
145
|
none: false
|
162
146
|
requirements:
|
@@ -277,7 +261,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
277
261
|
version: '0'
|
278
262
|
segments:
|
279
263
|
- 0
|
280
|
-
hash: -
|
264
|
+
hash: -3859920276334034236
|
281
265
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
282
266
|
none: false
|
283
267
|
requirements:
|