cloudapp-service 1.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/CHANGELOG.md +34 -0
  2. data/Gemfile +3 -0
  3. data/Gemfile.lock +56 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +14 -0
  6. data/Rakefile +148 -0
  7. data/cloudapp-service.gemspec +115 -0
  8. data/lib/cloudapp/collection_json.rb +3 -0
  9. data/lib/cloudapp/collection_json/item.rb +20 -0
  10. data/lib/cloudapp/collection_json/representation.rb +74 -0
  11. data/lib/cloudapp/collection_json/template.rb +17 -0
  12. data/lib/cloudapp/collection_json/tint.rb +11 -0
  13. data/lib/cloudapp/service.rb +204 -0
  14. data/lib/cloudapp/service/authorized_representation.rb +17 -0
  15. data/lib/cloudapp/service/drop.rb +44 -0
  16. data/lib/cloudapp/service/drop_collection.rb +39 -0
  17. data/spec/cassettes/account_token.yml +88 -0
  18. data/spec/cassettes/create_bookmark.yml +132 -0
  19. data/spec/cassettes/create_bookmark_with_name.yml +133 -0
  20. data/spec/cassettes/create_bookmark_with_privacy.yml +133 -0
  21. data/spec/cassettes/delete_drop.yml +215 -0
  22. data/spec/cassettes/list_drops.yml +488 -0
  23. data/spec/cassettes/list_drops_with_bad_token.yml +45 -0
  24. data/spec/cassettes/list_drops_with_filter.yml +345 -0
  25. data/spec/cassettes/list_drops_with_limit.yml +129 -0
  26. data/spec/cassettes/privatize_drop.yml +222 -0
  27. data/spec/cassettes/publicize_drop.yml +222 -0
  28. data/spec/cassettes/purge_drops.yml +764 -0
  29. data/spec/cassettes/recover_drop.yml +309 -0
  30. data/spec/cassettes/rename_drop.yml +222 -0
  31. data/spec/cassettes/token_for_account.yml +88 -0
  32. data/spec/cassettes/token_for_account_with_bad_credentials.yml +86 -0
  33. data/spec/cassettes/trash_drop.yml +222 -0
  34. data/spec/cassettes/update_drop_bookmark_url.yml +222 -0
  35. data/spec/cassettes/update_file.yml +365 -0
  36. data/spec/cassettes/upload_file.yml +276 -0
  37. data/spec/cassettes/upload_file_with_name.yml +278 -0
  38. data/spec/cassettes/upload_file_with_privacy.yml +277 -0
  39. data/spec/cassettes/view_drop.yml +174 -0
  40. data/spec/cloudapp/authorized_representation_spec.rb +32 -0
  41. data/spec/cloudapp/collection_json/item_spec.rb +45 -0
  42. data/spec/cloudapp/collection_json/representation_spec.rb +118 -0
  43. data/spec/cloudapp/collection_json/template_spec.rb +53 -0
  44. data/spec/cloudapp/drop_collection_spec.rb +148 -0
  45. data/spec/cloudapp/drop_spec.rb +186 -0
  46. data/spec/cloudapp/service_spec.rb +321 -0
  47. data/spec/helper.rb +8 -0
  48. data/spec/integration_spec.rb +77 -0
  49. data/spec/support/files/favicon.ico +0 -0
  50. data/spec/support/stub_class_or_module.rb +22 -0
  51. data/spec/support/vcr.rb +24 -0
  52. metadata +194 -0
@@ -0,0 +1,34 @@
1
+ # Change Log
2
+
3
+ Below is a complete listing of changes for each revision of `cloudapp`.
4
+
5
+ ## Unreleased
6
+
7
+ - Use new [hypermedia CloudApp API][api].
8
+ - Extract CLI into [cloudapp-cli gem][cli].
9
+ - Much refactoring
10
+
11
+ [api]: http://developer.getcloudapp.com/api-v2/
12
+ [cli]: https://github.com/cloudapp/cloudapp-cli
13
+
14
+ ## 1.1.0
15
+
16
+ - Add `download` command
17
+ - General housecleaning in `bin/cloudapp`
18
+ - Fix typo ([#22][] by [Mark Mulder][bittersweet])
19
+ - Extract Config class
20
+
21
+ [#22]: https://github.com/cloudapp/cloudapp/pull/22
22
+ [bittersweet]: https://github.com/bittersweet
23
+
24
+ ## 1.0.2
25
+
26
+ - Bump leadlight and relax highline dependencies.
27
+
28
+ ## 1.0.1
29
+
30
+ - Tightened leadlight and highline dependencies.
31
+
32
+ ## 1.0.0
33
+
34
+ - Stable release
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,56 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ cloudapp-service (1.0.0.beta.1)
5
+ leadlight (~> 0.0.7)
6
+ typhoeus (~> 0.3.3)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ addressable (2.2.8)
12
+ crack (0.3.1)
13
+ diff-lcs (1.1.3)
14
+ fail-fast (1.0.0)
15
+ faraday (0.8.1)
16
+ multipart-post (~> 1.1)
17
+ fattr (2.2.1)
18
+ hookr (1.1.1)
19
+ fail-fast (= 1.0.0)
20
+ leadlight (0.0.7)
21
+ addressable (~> 2.2.0)
22
+ faraday (= 0.8.1)
23
+ fattr
24
+ hookr
25
+ link_header
26
+ mime-types
27
+ multi_json (~> 1.0.4)
28
+ link_header (0.0.5)
29
+ mime-types (1.19)
30
+ multi_json (1.0.4)
31
+ multipart-post (1.1.5)
32
+ rake (0.9.2.2)
33
+ rspec (2.11.0)
34
+ rspec-core (~> 2.11.0)
35
+ rspec-expectations (~> 2.11.0)
36
+ rspec-mocks (~> 2.11.0)
37
+ rspec-core (2.11.1)
38
+ rspec-expectations (2.11.3)
39
+ diff-lcs (~> 1.1.3)
40
+ rspec-mocks (2.11.3)
41
+ typhoeus (0.3.3)
42
+ mime-types
43
+ vcr (2.0.1)
44
+ webmock (1.8.11)
45
+ addressable (>= 2.2.7)
46
+ crack (>= 0.1.7)
47
+
48
+ PLATFORMS
49
+ ruby
50
+
51
+ DEPENDENCIES
52
+ cloudapp-service!
53
+ rake
54
+ rspec
55
+ vcr (~> 2.0.0)
56
+ webmock
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Linebreak S.L.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
20
+
@@ -0,0 +1,14 @@
1
+ # CloudApp Ruby Client [![Build Status](https://secure.travis-ci.org/cloudapp/cloudapp.png)](http://travis-ci.org/cloudapp/cloudapp)
2
+
3
+ Interact with the [CloudApp API][] from Ruby.
4
+
5
+ [cloudapp api]: http://developer.getcloudapp.com
6
+
7
+ ## Requirements
8
+
9
+ `cloudapp` requires Ruby 1.9.2 or greater.
10
+
11
+
12
+ ## Usage
13
+
14
+ _Usage from Ruby is still a work in progress._
@@ -0,0 +1,148 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'date'
4
+
5
+ #############################################################################
6
+ #
7
+ # Helper functions
8
+ #
9
+ #############################################################################
10
+
11
+ def name
12
+ @name ||= Dir['*.gemspec'].first.split('.').first
13
+ end
14
+
15
+ def primary_file
16
+ name.tr('-', '/')
17
+ end
18
+
19
+ def version
20
+ line = File.read("lib/#{primary_file}.rb")[/^\s*VERSION\s*=\s*.*/]
21
+ line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
22
+ end
23
+
24
+ def date
25
+ Date.today.to_s
26
+ end
27
+
28
+ def rubyforge_project
29
+ name
30
+ end
31
+
32
+ def gemspec_file
33
+ "#{name}.gemspec"
34
+ end
35
+
36
+ def gem_file
37
+ "#{name}-#{version}.gem"
38
+ end
39
+
40
+ def replace_header(head, header_name)
41
+ head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
42
+ end
43
+
44
+ #############################################################################
45
+ #
46
+ # Standard tasks
47
+ #
48
+ #############################################################################
49
+
50
+ require 'rspec'
51
+ require 'rspec/core/rake_task'
52
+
53
+ desc "Run all specs"
54
+ task RSpec::Core::RakeTask.new('spec')
55
+ task :default => "spec"
56
+
57
+ desc 'Run non-integration specs'
58
+ RSpec::Core::RakeTask.new('spec:unit') do |t|
59
+ t.rspec_opts = "--tag ~integration"
60
+ end
61
+
62
+ #############################################################################
63
+ #
64
+ # Custom tasks (add your own tasks here)
65
+ #
66
+ #############################################################################
67
+
68
+
69
+
70
+ #############################################################################
71
+ #
72
+ # Packaging tasks
73
+ #
74
+ #############################################################################
75
+
76
+ desc "Create tag v#{version} and build and push #{gem_file} to Rubygems"
77
+ task :release => :build do
78
+ unless `git branch` =~ /^\* master$/
79
+ puts "You must be on the master branch to release!"
80
+ exit!
81
+ end
82
+ sh "git commit --allow-empty -a -m 'Release #{version}'"
83
+ sh "git tag v#{version}"
84
+ sh "git push origin master"
85
+ sh "git push origin v#{version}"
86
+ sh "gem push pkg/#{name}-#{version}.gem"
87
+ end
88
+
89
+ desc "Build #{gem_file} into the pkg directory"
90
+ task :build => [:gemspec, :update_bundle] do
91
+ sh "mkdir -p pkg"
92
+ sh "gem build #{gemspec_file}"
93
+ sh "mv #{gem_file} pkg"
94
+ end
95
+
96
+ desc "Generate #{gemspec_file}"
97
+ task :gemspec => :validate do
98
+ # read spec file and split out manifest section
99
+ spec = File.read(gemspec_file)
100
+ head, manifest, tail = spec.split(" # = MANIFEST =\n")
101
+
102
+ # replace name version and date
103
+ replace_header(head, :name)
104
+ replace_header(head, :version)
105
+ replace_header(head, :date)
106
+ #comment this out if your rubyforge_project has a different name
107
+ replace_header(head, :rubyforge_project)
108
+
109
+ # determine file list from git ls-files
110
+ files = `git ls-files`.
111
+ split("\n").
112
+ sort.
113
+ reject { |file| file =~ /^\./ }.
114
+ reject { |file| file =~ /^(rdoc|pkg)/ }.
115
+ map { |file| " #{file}" }.
116
+ join("\n")
117
+
118
+ # piece file back together and write
119
+ manifest = " s.files = %w[\n#{files}\n ]\n"
120
+ spec = [head, manifest, tail].join(" # = MANIFEST =\n")
121
+ File.open(gemspec_file, 'w') { |io| io.write(spec) }
122
+ puts "Updated #{gemspec_file}"
123
+ end
124
+
125
+ desc "Update #{name} in bundle"
126
+ task :update_bundle => :validate do
127
+ `bundle update #{name}`
128
+ puts "Bundled #{name} version #{version}"
129
+ end
130
+
131
+ desc "Validate #{gemspec_file}"
132
+ task :validate do
133
+ service_files = ['lib/cloudapp',
134
+ "lib/#{primary_file}",
135
+ "lib/#{primary_file}.rb"]
136
+ collection_json_files = ['lib/cloudapp/collection_json',
137
+ 'lib/cloudapp/collection_json.rb']
138
+ libfiles = Dir['lib/*'] + Dir['lib/cloudapp/*'] -
139
+ service_files - collection_json_files
140
+ unless libfiles.empty?
141
+ puts "Directory `lib` should only contain a `#{primary_file}.rb` file and `#{primary_file}` dir."
142
+ exit!
143
+ end
144
+ unless Dir['VERSION*'].empty?
145
+ puts "A `VERSION` file at root level violates Gem best practices."
146
+ exit!
147
+ end
148
+ end
@@ -0,0 +1,115 @@
1
+ ## This is the rakegem gemspec template. Make sure you read and understand
2
+ ## all of the comments. Some sections require modification, and others can
3
+ ## be deleted if you don't need them. Once you understand the contents of
4
+ ## this file, feel free to delete any comments that begin with two hash marks.
5
+ ## You can find comprehensive Gem::Specification documentation, at
6
+ ## http://docs.rubygems.org/read/chapter/20
7
+ Gem::Specification.new do |s|
8
+ s.specification_version = 2 if s.respond_to? :specification_version=
9
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
10
+ s.rubygems_version = '1.3.5'
11
+
12
+ ## Leave these as is they will be modified for you by the rake gemspec task.
13
+ ## If your rubyforge_project name is different, then edit it and comment out
14
+ ## the sub! line in the Rakefile
15
+ s.name = 'cloudapp-service'
16
+ s.version = '1.0.0.beta.1'
17
+ s.date = '2012-10-08'
18
+ s.rubyforge_project = 'cloudapp-service'
19
+
20
+ ## Make sure your summary is short. The description may be as long
21
+ ## as you like.
22
+ s.summary = "CloudApp API Client"
23
+ s.description = "CloudApp API Client"
24
+
25
+ ## List the primary authors. If there are a bunch of authors, it's probably
26
+ ## better to set the email to an email list or something. If you don't have
27
+ ## a custom homepage, consider using your GitHub URL or the like.
28
+ s.authors = ["Larry Marburger"]
29
+ s.email = 'larry@marburger.cc'
30
+ s.homepage = 'https://github.com/cloudapp/cloudapp.rb'
31
+
32
+ ## This gets added to the $LOAD_PATH so that 'lib/NAME.rb' can be required as
33
+ ## require 'NAME.rb' or'/lib/NAME/file.rb' can be as require 'NAME/file.rb'
34
+ s.require_paths = %w[lib]
35
+
36
+ ## Specify any RDoc options here. You'll want to add your README and
37
+ ## LICENSE files to the extra_rdoc_files list.
38
+ s.rdoc_options = ["--charset=UTF-8"]
39
+ s.extra_rdoc_files = %w[README.md MIT-LICENSE]
40
+
41
+ ## List your runtime dependencies here. Runtime dependencies are those
42
+ ## that are needed for an end user to actually USE your code.
43
+ s.add_dependency 'leadlight', '~> 0.0.7'
44
+ s.add_dependency 'typhoeus', '~> 0.3.3'
45
+
46
+ ## List your development dependencies here. Development dependencies are
47
+ ## those that are only needed during development
48
+ s.add_development_dependency 'rake'
49
+ s.add_development_dependency 'rspec'
50
+ s.add_development_dependency 'vcr', '~> 2.0.0'
51
+ s.add_development_dependency 'webmock'
52
+
53
+ ## Leave this section as-is. It will be automatically generated from the
54
+ ## contents of your Git repository via the gemspec task. DO NOT REMOVE
55
+ ## THE MANIFEST COMMENTS, they are used as delimiters by the task.
56
+ # = MANIFEST =
57
+ s.files = %w[
58
+ CHANGELOG.md
59
+ Gemfile
60
+ Gemfile.lock
61
+ MIT-LICENSE
62
+ README.md
63
+ Rakefile
64
+ cloudapp-service.gemspec
65
+ lib/cloudapp/collection_json.rb
66
+ lib/cloudapp/collection_json/item.rb
67
+ lib/cloudapp/collection_json/representation.rb
68
+ lib/cloudapp/collection_json/template.rb
69
+ lib/cloudapp/collection_json/tint.rb
70
+ lib/cloudapp/service.rb
71
+ lib/cloudapp/service/authorized_representation.rb
72
+ lib/cloudapp/service/drop.rb
73
+ lib/cloudapp/service/drop_collection.rb
74
+ spec/cassettes/account_token.yml
75
+ spec/cassettes/create_bookmark.yml
76
+ spec/cassettes/create_bookmark_with_name.yml
77
+ spec/cassettes/create_bookmark_with_privacy.yml
78
+ spec/cassettes/delete_drop.yml
79
+ spec/cassettes/list_drops.yml
80
+ spec/cassettes/list_drops_with_bad_token.yml
81
+ spec/cassettes/list_drops_with_filter.yml
82
+ spec/cassettes/list_drops_with_limit.yml
83
+ spec/cassettes/privatize_drop.yml
84
+ spec/cassettes/publicize_drop.yml
85
+ spec/cassettes/purge_drops.yml
86
+ spec/cassettes/recover_drop.yml
87
+ spec/cassettes/rename_drop.yml
88
+ spec/cassettes/token_for_account.yml
89
+ spec/cassettes/token_for_account_with_bad_credentials.yml
90
+ spec/cassettes/trash_drop.yml
91
+ spec/cassettes/update_drop_bookmark_url.yml
92
+ spec/cassettes/update_file.yml
93
+ spec/cassettes/upload_file.yml
94
+ spec/cassettes/upload_file_with_name.yml
95
+ spec/cassettes/upload_file_with_privacy.yml
96
+ spec/cassettes/view_drop.yml
97
+ spec/cloudapp/authorized_representation_spec.rb
98
+ spec/cloudapp/collection_json/item_spec.rb
99
+ spec/cloudapp/collection_json/representation_spec.rb
100
+ spec/cloudapp/collection_json/template_spec.rb
101
+ spec/cloudapp/drop_collection_spec.rb
102
+ spec/cloudapp/drop_spec.rb
103
+ spec/cloudapp/service_spec.rb
104
+ spec/helper.rb
105
+ spec/integration_spec.rb
106
+ spec/support/files/favicon.ico
107
+ spec/support/stub_class_or_module.rb
108
+ spec/support/vcr.rb
109
+ ]
110
+ # = MANIFEST =
111
+
112
+ ## Test files will be grabbed from the file list. Make sure the path glob
113
+ ## matches what you actually use.
114
+ # s.test_files = s.files.select { |path| path =~ /^test\/test_.*\.rb/ }
115
+ end
@@ -0,0 +1,3 @@
1
+ require 'cloudapp/collection_json/item'
2
+ require 'cloudapp/collection_json/representation'
3
+ require 'cloudapp/collection_json/template'
@@ -0,0 +1,20 @@
1
+ require 'ostruct'
2
+
3
+ module CloudApp
4
+ module CollectionJson
5
+ class Item
6
+ attr_reader :href, :links, :data
7
+ def initialize(item_data)
8
+ @href = item_data.fetch('href', nil)
9
+ @links = item_data.fetch('links', []).map {|link| OpenStruct.new(link) }
10
+ @data = DataCollection.hash_from(item_data.fetch('data'))
11
+ end
12
+ end
13
+
14
+ class DataCollection
15
+ def self.hash_from(data)
16
+ Hash[data.map {|datum| [ datum['name'], datum['value'] ]}]
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,74 @@
1
+ require 'ostruct'
2
+
3
+ module CloudApp
4
+ module CollectionJson
5
+ module Representation
6
+ def href
7
+ collection.fetch('href')
8
+ end
9
+
10
+ def collection_links
11
+ return [] unless collection.has_key?('links')
12
+ collection.fetch('links').map {|link| OpenStruct.new(link) }
13
+ end
14
+
15
+ def items(item_source = default_item_source)
16
+ collection.fetch('items').map {|item|
17
+ item_source.call(item)
18
+ }
19
+ end
20
+
21
+ # Ultimately this API would be nice:
22
+ #
23
+ # root.template(email: email, password: password).
24
+ # post do |response|
25
+ # return response
26
+ # end
27
+ #
28
+ # The Command Pattern could be nice as well. Template#[] may be a better
29
+ # solution than faux methods.
30
+ #
31
+ # root.create do |template|
32
+ # template.email = email
33
+ # template.password = password
34
+ # end
35
+ #
36
+ # Updates also use the template.
37
+ #
38
+ # root.items.first.update do |template|
39
+ # template.name.reverse!
40
+ # end
41
+ def template(template_source = default_template_source)
42
+ return unless collection.has_key?('template')
43
+ template_source.call collection.fetch('template')
44
+ end
45
+
46
+ def queries(query_source = default_query_source)
47
+ return unless collection.has_key?('queries')
48
+ collection.fetch('queries').map {|query| query_source.call(query) }
49
+ end
50
+
51
+ def query(rel, query_source = default_query_source)
52
+ Array(queries(query_source)).find {|query| query.rel == rel }
53
+ end
54
+
55
+ protected
56
+
57
+ def default_item_source
58
+ CloudApp::CollectionJson::Item.public_method(:new)
59
+ end
60
+
61
+ def default_template_source
62
+ CloudApp::CollectionJson::Template.public_method(:new)
63
+ end
64
+
65
+ def default_query_source
66
+ CloudApp::CollectionJson::Template.public_method(:new)
67
+ end
68
+
69
+ def collection
70
+ self.fetch('collection')
71
+ end
72
+ end
73
+ end
74
+ end