mavenlink 0.0.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +10 -3
  4. data/Gemfile.lock +38 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.rdoc +69 -0
  7. data/Rakefile +50 -24
  8. data/TODO +18 -0
  9. data/VERSION +1 -0
  10. data/lib/mavenlink.rb +2 -134
  11. data/lib/mavenlink/base.rb +184 -0
  12. data/lib/mavenlink/client.rb +202 -96
  13. data/mavenlink.gemspec +85 -19
  14. data/spec/mavenlink/base_spec.rb +223 -0
  15. data/spec/mavenlink/client_spec.rb +183 -0
  16. data/spec/spec_helper.rb +13 -25
  17. metadata +243 -232
  18. checksums.yaml +0 -7
  19. data/.gitignore +0 -11
  20. data/.ruby-gemset +0 -1
  21. data/.ruby-version +0 -1
  22. data/README.md +0 -241
  23. data/bin/mavenlink-console +0 -18
  24. data/doc/ml_logo_lb-primary.png +0 -0
  25. data/lib/config/specification.yml +0 -1665
  26. data/lib/mavenlink/account_invitation.rb +0 -4
  27. data/lib/mavenlink/account_membership.rb +0 -4
  28. data/lib/mavenlink/additional_item.rb +0 -4
  29. data/lib/mavenlink/assignment.rb +0 -5
  30. data/lib/mavenlink/attachment.rb +0 -11
  31. data/lib/mavenlink/backup_approver_association.rb +0 -4
  32. data/lib/mavenlink/concerns/custom_fieldable.rb +0 -9
  33. data/lib/mavenlink/concerns/indestructible.rb +0 -11
  34. data/lib/mavenlink/concerns/locked_record.rb +0 -30
  35. data/lib/mavenlink/cost_rate.rb +0 -4
  36. data/lib/mavenlink/custom_field.rb +0 -4
  37. data/lib/mavenlink/custom_field_choice.rb +0 -5
  38. data/lib/mavenlink/custom_field_value.rb +0 -4
  39. data/lib/mavenlink/errors.rb +0 -47
  40. data/lib/mavenlink/expense.rb +0 -4
  41. data/lib/mavenlink/expense_category.rb +0 -4
  42. data/lib/mavenlink/expense_report_submission.rb +0 -7
  43. data/lib/mavenlink/external_payment.rb +0 -4
  44. data/lib/mavenlink/external_reference.rb +0 -24
  45. data/lib/mavenlink/fixed_fee_item.rb +0 -4
  46. data/lib/mavenlink/holiday.rb +0 -4
  47. data/lib/mavenlink/holiday_calendar.rb +0 -4
  48. data/lib/mavenlink/holiday_calendar_association.rb +0 -4
  49. data/lib/mavenlink/holiday_calendar_membership.rb +0 -4
  50. data/lib/mavenlink/invoice.rb +0 -4
  51. data/lib/mavenlink/logger.rb +0 -62
  52. data/lib/mavenlink/model.rb +0 -279
  53. data/lib/mavenlink/organization.rb +0 -4
  54. data/lib/mavenlink/organization_membership.rb +0 -4
  55. data/lib/mavenlink/participation.rb +0 -4
  56. data/lib/mavenlink/post.rb +0 -4
  57. data/lib/mavenlink/project_template.rb +0 -4
  58. data/lib/mavenlink/project_template_assignment.rb +0 -4
  59. data/lib/mavenlink/railtie.rb +0 -7
  60. data/lib/mavenlink/rate_card.rb +0 -4
  61. data/lib/mavenlink/rate_card_role.rb +0 -4
  62. data/lib/mavenlink/rate_card_set.rb +0 -4
  63. data/lib/mavenlink/rate_card_set_version.rb +0 -30
  64. data/lib/mavenlink/rate_card_version.rb +0 -4
  65. data/lib/mavenlink/request.rb +0 -241
  66. data/lib/mavenlink/resolution.rb +0 -4
  67. data/lib/mavenlink/response.rb +0 -22
  68. data/lib/mavenlink/role.rb +0 -5
  69. data/lib/mavenlink/settings.rb +0 -11
  70. data/lib/mavenlink/skill.rb +0 -4
  71. data/lib/mavenlink/skill_category.rb +0 -4
  72. data/lib/mavenlink/skill_membership.rb +0 -4
  73. data/lib/mavenlink/specificators/association.rb +0 -13
  74. data/lib/mavenlink/specificators/attribute.rb +0 -13
  75. data/lib/mavenlink/specificators/base.rb +0 -24
  76. data/lib/mavenlink/specificators/validation.rb +0 -27
  77. data/lib/mavenlink/status_report.rb +0 -4
  78. data/lib/mavenlink/story.rb +0 -8
  79. data/lib/mavenlink/story_allocation_day.rb +0 -5
  80. data/lib/mavenlink/story_dependency.rb +0 -5
  81. data/lib/mavenlink/story_task.rb +0 -5
  82. data/lib/mavenlink/tag.rb +0 -5
  83. data/lib/mavenlink/time_adjustment.rb +0 -4
  84. data/lib/mavenlink/time_entry.rb +0 -4
  85. data/lib/mavenlink/time_off_entry.rb +0 -4
  86. data/lib/mavenlink/timesheet_submission.rb +0 -4
  87. data/lib/mavenlink/user.rb +0 -5
  88. data/lib/mavenlink/vendor.rb +0 -4
  89. data/lib/mavenlink/workspace.rb +0 -21
  90. data/lib/mavenlink/workspace_group.rb +0 -5
  91. data/lib/mavenlink/workspace_invoice_preference.rb +0 -4
  92. data/lib/mavenlink/workweek.rb +0 -4
  93. data/lib/mavenlink/workweek_membership.rb +0 -4
  94. data/spec/lib/mavenlink/account_membership_spec.rb +0 -8
  95. data/spec/lib/mavenlink/assignment_spec.rb +0 -17
  96. data/spec/lib/mavenlink/attachment_spec.rb +0 -30
  97. data/spec/lib/mavenlink/backup_approver_association_spec.rb +0 -9
  98. data/spec/lib/mavenlink/client_spec.rb +0 -187
  99. data/spec/lib/mavenlink/concerns/indestructible_spec.rb +0 -13
  100. data/spec/lib/mavenlink/concerns/locked_record_spec.rb +0 -28
  101. data/spec/lib/mavenlink/cost_rate_spec.rb +0 -9
  102. data/spec/lib/mavenlink/custom_field_value_spec.rb +0 -10
  103. data/spec/lib/mavenlink/expense_report_submission_spec.rb +0 -16
  104. data/spec/lib/mavenlink/expense_spec.rb +0 -23
  105. data/spec/lib/mavenlink/external_references_spec.rb +0 -144
  106. data/spec/lib/mavenlink/holiday_calendar_association_spec.rb +0 -8
  107. data/spec/lib/mavenlink/holiday_calendar_membership_spec.rb +0 -8
  108. data/spec/lib/mavenlink/holiday_spec.rb +0 -7
  109. data/spec/lib/mavenlink/invalid_request_error_spec.rb +0 -9
  110. data/spec/lib/mavenlink/invoice_spec.rb +0 -176
  111. data/spec/lib/mavenlink/model_spec.rb +0 -439
  112. data/spec/lib/mavenlink/post_spec.rb +0 -23
  113. data/spec/lib/mavenlink/rate_card_set_version_spec.rb +0 -119
  114. data/spec/lib/mavenlink/record_invalid_error_spec.rb +0 -16
  115. data/spec/lib/mavenlink/record_not_found_error_spec.rb +0 -9
  116. data/spec/lib/mavenlink/request_spec.rb +0 -381
  117. data/spec/lib/mavenlink/response_spec.rb +0 -50
  118. data/spec/lib/mavenlink/role_spec.rb +0 -9
  119. data/spec/lib/mavenlink/settings_spec.rb +0 -23
  120. data/spec/lib/mavenlink/skill_category_spec.rb +0 -7
  121. data/spec/lib/mavenlink/skill_membership_spec.rb +0 -9
  122. data/spec/lib/mavenlink/skill_spec.rb +0 -8
  123. data/spec/lib/mavenlink/specificators/association_spec.rb +0 -25
  124. data/spec/lib/mavenlink/specificators/attribute_spec.rb +0 -25
  125. data/spec/lib/mavenlink/specificators/validation_spec.rb +0 -39
  126. data/spec/lib/mavenlink/story_allocation_day_spec.rb +0 -64
  127. data/spec/lib/mavenlink/story_dependency_spec.rb +0 -16
  128. data/spec/lib/mavenlink/story_spec.rb +0 -69
  129. data/spec/lib/mavenlink/time_adjustment_spec.rb +0 -13
  130. data/spec/lib/mavenlink/time_entry_spec.rb +0 -43
  131. data/spec/lib/mavenlink/time_off_entry_spec.rb +0 -9
  132. data/spec/lib/mavenlink/user_spec.rb +0 -138
  133. data/spec/lib/mavenlink/workspace_group_spec.rb +0 -25
  134. data/spec/lib/mavenlink/workspace_spec.rb +0 -431
  135. data/spec/lib/mavenlink_spec.rb +0 -43
  136. data/spec/support/shared_examples.rb +0 -148
@@ -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 CHANGED
@@ -1,3 +1,10 @@
1
- source 'http://rubygems.org'
2
- gemspec
3
- gem 'rake'
1
+ source "http://rubygems.org"
2
+
3
+ #gemspec
4
+
5
+ gem "httparty", "0.7.4"
6
+ gem "webmock", "~> 1.6.2"
7
+ gem "rspec", "~> 2.3.0"
8
+ gem "jeweler", "~> 1.5.2"
9
+ gem "rr", "~> 1.0.2"
10
+ gem "json", "~> 1.5.1"
@@ -0,0 +1,38 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ addressable (2.2.4)
5
+ crack (0.1.8)
6
+ diff-lcs (1.1.2)
7
+ git (1.2.5)
8
+ httparty (0.7.4)
9
+ crack (= 0.1.8)
10
+ jeweler (1.5.2)
11
+ bundler (~> 1.0.0)
12
+ git (>= 1.2.5)
13
+ rake
14
+ json (1.5.1)
15
+ rake (0.8.7)
16
+ rr (1.0.2)
17
+ rspec (2.3.0)
18
+ rspec-core (~> 2.3.0)
19
+ rspec-expectations (~> 2.3.0)
20
+ rspec-mocks (~> 2.3.0)
21
+ rspec-core (2.3.1)
22
+ rspec-expectations (2.3.0)
23
+ diff-lcs (~> 1.1.2)
24
+ rspec-mocks (2.3.0)
25
+ webmock (1.6.2)
26
+ addressable (>= 2.2.2)
27
+ crack (>= 0.1.7)
28
+
29
+ PLATFORMS
30
+ ruby
31
+
32
+ DEPENDENCIES
33
+ httparty (= 0.7.4)
34
+ jeweler (~> 1.5.2)
35
+ json (~> 1.5.1)
36
+ rr (~> 1.0.2)
37
+ rspec (~> 2.3.0)
38
+ webmock (~> 1.6.2)
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Mavenlink, LLC.
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,69 @@
1
+ = Mavenlink Ruby API Client
2
+
3
+ The Mavenlink API provides programmatic access to many of Mavenlink's capabilities, including projects, posts, tasks, and time entries. This is a full-featured Ruby client to the Mavenlink REST API.
4
+
5
+ {Mavenlink's}[http://mavenlink.com] project collaboration suite allows you to manage your business relationships, share files, and track project activity online from anywhere in the world. Within a project workspace in Mavenlink, you can agree on budget & schedule, track time, send invoices, get paid via PayPal, and complete work.
6
+
7
+ == The REST API
8
+
9
+ We have full {REST API and Ruby client documentation on the wiki}[https://github.com/mavenlink/mavenlink_ruby_api/wiki].
10
+
11
+ == Example Usage
12
+
13
+ (sudo) gem install mavenlink
14
+ > require 'rubygems'
15
+ > require 'mavenlink'
16
+ > client = Mavenlink::Client.new(<user_id>, '<api_token>')
17
+ > workspaces = client.workspaces(:per_page => 10)
18
+ > workspaces.first.title
19
+ "This is my workspace!"
20
+ > workspaces.first.time_entries.length
21
+ 20
22
+ > workspaces.first.expenses.length
23
+ 4
24
+ > workspaces.first.stories.length
25
+ 4
26
+ > posts = workspaces.first.posts
27
+ > posts.length
28
+ 5
29
+ > posts.first.message
30
+ "This is an example message."
31
+ > post = workspaces.first.create_post(:message => "Hello!")
32
+ > post.message
33
+ "Hello!"
34
+ > post.update(:message => "I edited my post")
35
+ true
36
+ > post.message
37
+ "I edited my post"
38
+ > post.update(:message => "")
39
+ false
40
+ > post.errors
41
+ ["A message is required"]
42
+ > post.destroy
43
+ true
44
+
45
+ == Credentials
46
+
47
+ === Finding your User ID and API Token
48
+
49
+ Your User ID and API Token are both available on your Mavenlink account page at the bottom of the first tab.
50
+
51
+ === Security
52
+
53
+ For security, the API is provided over SSL only. Additionally, you should consider your API Token to be much like a password. Someone with your token can make changes to your Mavenlink account and perform actions in your name. If you believe that your token has been compromised, login to Mavenlink and reset your token from your account page.
54
+
55
+ == Contributing to the Mavenlink Ruby API Client
56
+
57
+ We strive to keep the Ruby API up-to-date with our REST API. However, if you find a feature missing, feel free to contribute it.
58
+
59
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
60
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
61
+ * Fork the project
62
+ * Start a feature/bugfix branch
63
+ * Write a failing rspec test case, write code until your test passes, rinse, repeat.
64
+ * Commit and push until you are happy with your contribution
65
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or it is otherwise necessary, that is fine, but please isolate it to its own commit so that we can cherry-pick around it as needed.
66
+
67
+ == Copyright
68
+
69
+ Copyright (c) 2011 Mavenlink, LLC. See LICENSE.txt for further details.
data/Rakefile CHANGED
@@ -1,28 +1,54 @@
1
- #!/usr/bin/env rake
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "mavenlink"
16
+ gem.homepage = "http://github.com/mavenlink/mavenlink_ruby_api"
17
+ gem.license = "MIT"
18
+ gem.summary = %Q{Ruby client for Mavenlink's API}
19
+ gem.description = %Q{This is a Ruby API client for Mavenlink. Mavenlink's project collaboration suite allows you to manage your business relationships, share files, and track project activity online from anywhere in the world. Within a project workspace in Mavenlink, you can agree on budget & schedule, track time, send invoices, get paid via PayPal, and complete work.}
20
+ gem.email = "support@mavenlink.com"
21
+ gem.authors = ["Roger Neel", "Andrew Cantino"]
22
+
23
+ gem.add_runtime_dependency "httparty", "0.7.4"
24
+
25
+ gem.add_development_dependency "webmock", "~> 1.6.2"
26
+ gem.add_development_dependency "rspec", "~> 2.3.0"
27
+ gem.add_development_dependency "jeweler", "~> 1.5.2"
28
+ gem.add_development_dependency "rr", "~> 1.0.2"
29
+ gem.add_development_dependency "json", "~> 1.5.1"
30
+ end
31
+ Jeweler::RubygemsDotOrgTasks.new
2
32
 
33
+ require 'rspec/core'
3
34
  require 'rspec/core/rake_task'
35
+ RSpec::Core::RakeTask.new(:spec) do |spec|
36
+ spec.pattern = FileList['spec/**/*_spec.rb']
37
+ end
38
+
39
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
40
+ spec.pattern = 'spec/**/*_spec.rb'
41
+ spec.rcov = true
42
+ end
43
+
44
+ task :default => :spec
45
+
46
+ require 'rake/rdoctask'
47
+ Rake::RDocTask.new do |rdoc|
48
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
4
49
 
5
- RSpec::Core::RakeTask.new :spec
6
- task default: :spec
7
-
8
- desc 'Runs irb console and initializes the API'
9
- task :console, :token do |_, args|
10
- require 'irb'
11
- require 'mavenlink'
12
- require 'awesome_print'
13
-
14
- token = ENV['TOKEN'] || args[:token]
15
- Mavenlink.oauth_token = token
16
-
17
- Mavenlink.logger = Mavenlink::Logger.new(STDOUT)
18
- Mavenlink.logger.level = Logger::DEBUG # Change to Logger::INFO not to display responses
19
- if token
20
- Mavenlink.logger.hint "Using #{token} token."
21
- else
22
- Mavenlink.logger.disappointment 'No token set! Please put TOKEN=xxxx into your .env file or set manually.'
23
- end
24
-
25
- AwesomePrint.irb!
26
- ARGV.clear
27
- IRB.start
50
+ rdoc.rdoc_dir = 'rdoc'
51
+ rdoc.title = "mavenlink #{version}"
52
+ rdoc.rdoc_files.include('README*')
53
+ rdoc.rdoc_files.include('lib/**/*.rb')
28
54
  end
data/TODO ADDED
@@ -0,0 +1,18 @@
1
+ ## CLIENT TODO
2
+ - Document expenses on the wiki (/expenses and /workspaces/2/expenses).
3
+ - Document reload available on all models.
4
+ - Document error responses, such as:
5
+ => expense
6
+ => #<Mavenlink::Expense:0x101aeb760 @json={"category"=>"Some Category", "created_at"=>"2011...
7
+ expense.destroy
8
+ => false
9
+ expense.errors
10
+ => ["Expense 23456 cannot be deleted because it is in an active invoice"]
11
+ expense.update :foo => :bar
12
+ => false
13
+ expense.errors
14
+ => ["Unknown params: expense[foo]. Known params: expense[date] is the expense date in the form MM/DD/YYYY, expense[amount_in_cents] is the amount of this expense in the base units of the workspace currency (i.e., cents for USD), expense[notes] are the notes, if any, associated with this expense, expense[category] is the expense category"]
15
+
16
+ ## API TODO
17
+ - Add user endpoint
18
+ - Add invoices endpoint
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
@@ -1,134 +1,2 @@
1
- require 'active_support/core_ext/hash/indifferent_access'
2
- require 'active_support/core_ext/hash/slice'
3
- require 'active_support/core_ext/object/try'
4
- require 'active_support/core_ext/string/inflections'
5
- require 'active_model'
6
- require 'yaml'
7
- require 'json'
8
- require 'brainstem-adaptor'
9
- require 'faraday'
10
-
11
- module Mavenlink
12
- VERSION = '0.0.1'
13
-
14
- # Returns HTTP framework
15
- def self.adapter
16
- @adapter || Faraday.default_adapter
17
- end
18
-
19
- # @param value Any valid Faraday adapter
20
- def self.adapter=(value)
21
- @adapter = value
22
- end
23
-
24
- def self.client
25
- @client ||= Mavenlink::Client.new
26
- end
27
-
28
- # @return [Mavenlink::Settings]
29
- def self.default_settings
30
- Mavenlink::Settings[:default]
31
- end
32
-
33
- def self.logger
34
- @logger ||= Mavenlink::Logger.new(nil)
35
- end
36
-
37
- def self.logger=(value)
38
- @logger = value
39
- end
40
-
41
- # @param token [String]
42
- def self.oauth_token=(token)
43
- default_settings[:oauth_token] = token
44
- end
45
-
46
- # Forces models to perform validations if true
47
- # If false performs requests without running validations described in specification file
48
- # Default behavior is not to validate anything
49
- # @param enabled [true, false]
50
- def self.perform_validations=(enabled)
51
- default_settings[:perform_validations] = enabled
52
- end
53
-
54
- # @param [String] version
55
- # @return [Api]
56
- def self.specification
57
- @specification ||= BrainstemAdaptor::Specification.new(YAML.load_file(File.join(File.dirname(__FILE__), 'config', 'specification.yml')))
58
- end
59
-
60
- def self.stub_requests(&block)
61
- stubbed_requests = Faraday::Adapter::Test::Stubs.new(&block)
62
- self.adapter = [:test, stubbed_requests]
63
- end
64
- end
65
-
66
- require 'mavenlink/settings'
67
- require 'mavenlink/errors'
68
- require 'mavenlink/request'
69
- require 'mavenlink/response'
70
- require 'mavenlink/client'
71
- require 'mavenlink/logger'
72
- require 'mavenlink/concerns/custom_fieldable'
73
- require 'mavenlink/concerns/indestructible'
74
- require 'mavenlink/concerns/locked_record'
75
- require 'mavenlink/specificators/base'
76
- require 'mavenlink/specificators/attribute'
77
- require 'mavenlink/specificators/association'
78
- require 'mavenlink/specificators/validation'
79
- require 'mavenlink/model'
80
- require 'mavenlink/account_invitation'
81
- require 'mavenlink/account_membership'
82
- require 'mavenlink/additional_item'
83
- require 'mavenlink/assignment'
84
- require 'mavenlink/attachment'
85
- require 'mavenlink/backup_approver_association'
86
- require 'mavenlink/cost_rate'
87
- require 'mavenlink/custom_field'
88
- require 'mavenlink/custom_field_value'
89
- require 'mavenlink/custom_field_choice'
90
- require 'mavenlink/expense'
91
- require 'mavenlink/expense_category'
92
- require 'mavenlink/expense_report_submission'
93
- require 'mavenlink/external_payment'
94
- require 'mavenlink/fixed_fee_item'
95
- require 'mavenlink/external_reference'
96
- require 'mavenlink/holiday'
97
- require 'mavenlink/holiday_calendar'
98
- require 'mavenlink/holiday_calendar_association'
99
- require 'mavenlink/holiday_calendar_membership'
100
- require 'mavenlink/invoice'
101
- require 'mavenlink/organization'
102
- require 'mavenlink/organization_membership'
103
- require 'mavenlink/participation'
104
- require 'mavenlink/post'
105
- require 'mavenlink/project_template'
106
- require 'mavenlink/project_template_assignment'
107
- require 'mavenlink/skill'
108
- require 'mavenlink/skill_category'
109
- require 'mavenlink/skill_membership'
110
- require 'mavenlink/status_report'
111
- require 'mavenlink/story'
112
- require 'mavenlink/story_allocation_day'
113
- require 'mavenlink/story_dependency'
114
- require 'mavenlink/story_task'
115
- require 'mavenlink/tag'
116
- require 'mavenlink/time_adjustment'
117
- require 'mavenlink/time_entry'
118
- require 'mavenlink/time_off_entry'
119
- require 'mavenlink/timesheet_submission'
120
- require 'mavenlink/rate_card'
121
- require 'mavenlink/rate_card_role'
122
- require 'mavenlink/rate_card_set'
123
- require 'mavenlink/rate_card_set_version'
124
- require 'mavenlink/rate_card_version'
125
- require 'mavenlink/resolution'
126
- require 'mavenlink/role' # NOTE(SZ): remove
127
- require 'mavenlink/user'
128
- require 'mavenlink/vendor'
129
- require 'mavenlink/workspace'
130
- require 'mavenlink/workspace_invoice_preference'
131
- require 'mavenlink/workspace_group'
132
- require 'mavenlink/workweek'
133
- require 'mavenlink/workweek_membership'
134
- require 'mavenlink/railtie' if defined?(Rails)
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'mavenlink', 'base'))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), 'mavenlink', 'client'))
@@ -0,0 +1,184 @@
1
+ require 'httparty'
2
+
3
+ module Mavenlink
4
+ class Base
5
+ include HTTParty
6
+ headers 'Accept' => 'application/json'
7
+ format :json
8
+
9
+ attr_accessor :json, :path_params, :basic_auth, :errors
10
+
11
+ def initialize(json, options = {})
12
+ self.path_params = options[:path_params] || {}
13
+ self.basic_auth = options[:basic_auth]
14
+ set_json json
15
+ end
16
+
17
+ def id
18
+ json['id']
19
+ end
20
+
21
+ def request_path
22
+ p = self.class.request_path.to_s
23
+ params = path_params.dup
24
+ params[:id] = id if id
25
+ params.each do |key, value|
26
+ p = p.gsub(key.inspect, value.to_s)
27
+ end
28
+ p
29
+ end
30
+
31
+ def join_paths(original, append)
32
+ original = original + "/" unless original =~ /\/$/
33
+ original = "/" + original unless original =~ /^\//
34
+ append = append.gsub(/^\//, '')
35
+ uri = URI.parse("http://www.example.com#{original}")
36
+ (uri + append).path.gsub(/\/$/, '')
37
+ end
38
+
39
+ def get_request(path, options = {})
40
+ puts "GET #{path}" if self.class.debug
41
+ self.class.get path, :query => options, :basic_auth => basic_auth
42
+ end
43
+
44
+ def put_request(path, options = {})
45
+ puts "PUT #{path}" if self.class.debug
46
+ self.class.put path, :body => options, :basic_auth => basic_auth
47
+ end
48
+
49
+ def post_request(path, options = {})
50
+ puts "POST #{path}" if self.class.debug
51
+ self.class.post path, :body => options, :basic_auth => basic_auth
52
+ end
53
+
54
+ def delete_request(path, options = {})
55
+ puts "DELETE #{path}" if self.class.debug
56
+ self.class.delete path, :query => options, :basic_auth => basic_auth
57
+ end
58
+
59
+ def update(changes)
60
+ response = put_request(request_path, self.class.class_name => changes)
61
+ if response.code == 200
62
+ set_json response.parsed_response
63
+ true
64
+ elsif response.code == 422
65
+ self.errors = response.parsed_response['errors']
66
+ false
67
+ else
68
+ raise "Server error code #{response.code}"
69
+ end
70
+ end
71
+
72
+ def destroy
73
+ response = delete_request(request_path)
74
+ if response.code == 200
75
+ true
76
+ elsif response.code == 422
77
+ self.errors = response.parsed_response['errors']
78
+ false
79
+ else
80
+ raise "Server error code #{response.code}"
81
+ end
82
+ end
83
+
84
+ def reload(options = {})
85
+ result = get_request(request_path, options)
86
+ if result.code == 200
87
+ set_json result.parsed_response
88
+ else
89
+ raise "Server error code #{result.code}"
90
+ end
91
+ self
92
+ end
93
+
94
+ protected
95
+
96
+ def set_json(j)
97
+ self.errors = []
98
+ self.json = j
99
+ wrap_contained_objects
100
+ end
101
+
102
+ def wrap_contained_objects
103
+ (self.class.contains || {}).keys.each do |method|
104
+ json[method.to_s] = if !json.has_key?(method.to_s)
105
+ nil
106
+ elsif json[method.to_s].is_a?(Array)
107
+ json[method.to_s].map do |data|
108
+ options = get_contains_options(method.to_sym, data)
109
+ options[:class].new(data, :basic_auth => basic_auth, :path_params => options[:path_params] || {})
110
+ end
111
+ else
112
+ options = get_contains_options(method.to_sym, json[method.to_s])
113
+ options[:class].new(json[method.to_s], :basic_auth => basic_auth, :path_params => options[:path_params] || {})
114
+ end
115
+ end
116
+ end
117
+
118
+ def build(path, klass, options, new_path_params = {})
119
+ response = post_request(join_paths(request_path, path), klass.class_name => options)
120
+ if response.code == 200
121
+ klass.new(response.parsed_response, :basic_auth => basic_auth, :path_params => handle_proc(new_path_params, response.parsed_response))
122
+ elsif response.code == 422
123
+ k = klass.new(response.parsed_response, :basic_auth => basic_auth, :path_params => handle_proc(new_path_params, response.parsed_response))
124
+ k.errors = response.parsed_response['errors']
125
+ k
126
+ else
127
+ raise "Server error code #{response.code}"
128
+ end
129
+ end
130
+
131
+ def fetch(path, klass, options, new_path_params = {})
132
+ result = get_request(join_paths(request_path, path), options)
133
+ if result.code == 200
134
+ if result.parsed_response.is_a?(Array)
135
+ result.parsed_response.map { |data| klass.new(data, :basic_auth => basic_auth, :path_params => handle_proc(new_path_params, data)) }
136
+ else
137
+ klass.new(result.parsed_response, :basic_auth => basic_auth, :path_params => handle_proc(new_path_params, result.parsed_response))
138
+ end
139
+ else
140
+ raise "Server error code #{result.code}"
141
+ end
142
+ end
143
+
144
+ def handle_proc(possibly_proc, *args)
145
+ (possibly_proc && possibly_proc.is_a?(Proc) && possibly_proc.call(*args)) || possibly_proc
146
+ end
147
+
148
+ def get_contains_options(method, data)
149
+ if self.class.contains[method].is_a?(Class)
150
+ { :class => self.class.contains[method] }
151
+ elsif self.class.contains[method].is_a?(Proc)
152
+ self.class.contains[method].call(self, data)
153
+ elsif self.class.contains[method].is_a?(Hash)
154
+ self.class.contains[method]
155
+ else
156
+ nil
157
+ end
158
+ end
159
+
160
+ def method_missing(method)
161
+ json.has_key?(method.to_s) ? json[method.to_s] : super
162
+ end
163
+
164
+ def self.contains(c = nil)
165
+ @contains = c if c
166
+ @contains
167
+ end
168
+
169
+ def self.request_path(p = nil)
170
+ @request_path = p if p
171
+ @request_path
172
+ end
173
+
174
+ def self.class_name(c = nil)
175
+ @class_name = c if c
176
+ @class_name
177
+ end
178
+
179
+ def self.debug(state = :not_set)
180
+ @@debug = state unless state == :not_set
181
+ @@debug
182
+ end
183
+ end
184
+ end