cybercoach 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +45 -0
  3. data/.rspec +2 -0
  4. data/CHANGELOG.md +8 -0
  5. data/Gemfile +23 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +31 -0
  8. data/Rakefile +2 -0
  9. data/cybercoach.gemspec +27 -0
  10. data/lib/cybercoach/abstract_resource.rb +162 -0
  11. data/lib/cybercoach/entry.rb +166 -0
  12. data/lib/cybercoach/format_not_supported_error.rb +7 -0
  13. data/lib/cybercoach/http_error.rb +27 -0
  14. data/lib/cybercoach/pageable.rb +38 -0
  15. data/lib/cybercoach/partnership.rb +151 -0
  16. data/lib/cybercoach/post_createable.rb +49 -0
  17. data/lib/cybercoach/privacy_level.rb +21 -0
  18. data/lib/cybercoach/put_createable.rb +48 -0
  19. data/lib/cybercoach/resource.rb +94 -0
  20. data/lib/cybercoach/resource_page.rb +191 -0
  21. data/lib/cybercoach/settings.rb +16 -0
  22. data/lib/cybercoach/sport.rb +104 -0
  23. data/lib/cybercoach/subclass_responsibility_error.rb +7 -0
  24. data/lib/cybercoach/subscription.rb +145 -0
  25. data/lib/cybercoach/user.rb +159 -0
  26. data/lib/cybercoach/version.rb +10 -0
  27. data/lib/cybercoach.rb +19 -0
  28. data/spec/lib/cybercoach/entry_spec.rb +95 -0
  29. data/spec/lib/cybercoach/partnership_spec.rb +79 -0
  30. data/spec/lib/cybercoach/privacy_level_spec.rb +15 -0
  31. data/spec/lib/cybercoach/resource_helper.rb +11 -0
  32. data/spec/lib/cybercoach/resource_page_spec.rb +44 -0
  33. data/spec/lib/cybercoach/settings_spec.rb +10 -0
  34. data/spec/lib/cybercoach/sport_spec.rb +29 -0
  35. data/spec/lib/cybercoach/subscription_spec.rb +129 -0
  36. data/spec/lib/cybercoach/user_helper.rb +22 -0
  37. data/spec/lib/cybercoach/user_spec.rb +82 -0
  38. data/spec/lib/cybercoach_helper.rb +2 -0
  39. data/spec/lib/integration_spec.rb +56 -0
  40. data/spec/spec_helper.rb +19 -0
  41. metadata +56 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ad6ac23fea3b1fa04a72a28e36810290d1cc9186
4
- data.tar.gz: 02d1a6e7ca0dfa735fc8e503216803b3320800b6
3
+ metadata.gz: 59526a9235348317412b0f880b808b23357827aa
4
+ data.tar.gz: 77285e272d541197cd65e1752fae2d96f0ff78ce
5
5
  SHA512:
6
- metadata.gz: 86a230ed3186e6c1c6f6cbc3725815703f8ab460a9ef38720013e71950aedd35a5d953ffd7b522521a6f696163e1a5d3dea3bb57a4b45966013014f330d6441c
7
- data.tar.gz: 096007e2140994a8af7dd3a0ffad2d6f690c8b95e4357b26bfaa76f7902a0c079fb51ec13df8e53faf8c10d4d43c22ba2337792b4bff82f38e75482d6fea0fff
6
+ metadata.gz: fe5ffcf504246b9f3ac0b9203f3d5457676ab3cdee654b6cc4d5c85cabac93e63e6f08d1b9e3b9f4f7384254be23e8b57ca4a3bbae0a8bce4d4b84c0bd323be5
7
+ data.tar.gz: 29f7d4a1542fccd1ce2ec78c14112c8aa55ec34b0492ff2963c82e347135e8acdb6fac6bd2bf5eef4a4888db5b659a92988687330f2de93499e1bbcf6127544a
data/.gitignore ADDED
@@ -0,0 +1,45 @@
1
+ *.so
2
+ *.o
3
+ *.a
4
+ mkmf.log
5
+ /.idea/
6
+ .DS_STORE
7
+
8
+ # Created by https://www.gitignore.io
9
+
10
+ ### Ruby ###
11
+ *.gem
12
+ *.rbc
13
+ /.config
14
+ /coverage/
15
+ /InstalledFiles
16
+ /pkg/
17
+ /spec/reports/
18
+ /test/tmp/
19
+ /test/version_tmp/
20
+ /tmp/
21
+
22
+ ## Specific to RubyMotion:
23
+ .dat*
24
+ .repl_history
25
+ build/
26
+
27
+ ## Documentation cache and generated files:
28
+ /.yardoc/
29
+ /_yardoc/
30
+ /doc/
31
+ /rdoc/
32
+
33
+ ## Environment normalisation:
34
+ /.bundle/
35
+ /lib/bundler/man/
36
+
37
+ # for a library or gem, you might want to ignore these files since the code is
38
+ # intended to run in multiple environments; otherwise, check them in:
39
+ Gemfile.lock
40
+ .ruby-version
41
+ .ruby-gemset
42
+
43
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
44
+ .rvmrc
45
+
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ # Changelog
2
+
3
+ ## v0.3.0
4
+
5
+ - `public_visble` -> `privacy_level`
6
+ - `PrivacyLevel`s introduced
7
+ - added `User.authentication()` to get authentication options
8
+ - Gem is actually a Gem...
data/Gemfile ADDED
@@ -0,0 +1,23 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cybercoach.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem 'rubocop', '~> 0.26', require: false
8
+ end
9
+
10
+ group :test do
11
+ gem 'rspec', '~> 3.1'
12
+ gem 'simplecov', '~> 0.9', require: false
13
+ end
14
+
15
+ group :development, :test do
16
+ gem 'pry', '~> 0.10'
17
+ gem 'pry-byebug', '~> 2.0'
18
+ gem 'pry-stack_explorer', '~> 0.4'
19
+ end
20
+
21
+ group :doc do
22
+ gem 'sdoc', '~> 0.4'
23
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 NewYorkFalcons
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # CyberCoach
2
+
3
+ Proxies the CyberCoach service.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'cybercoach'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install cybercoach
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it ( https://github.com/[my-github-username]/cybercoach/fork )
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'cybercoach/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'cybercoach'
8
+ spec.version = CyberCoach::VERSION
9
+ spec.authors = ['Manuel Leuenberger']
10
+ spec.email = ['manuel.leu@students.unibe.ch']
11
+ spec.summary = 'CyberCoach proxy'
12
+ spec.description = 'Wraps the CyberCoach resources and their CRUD methods.'
13
+ spec.homepage = 'https://github.com/New-York-Falcons/cybercoach'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.required_ruby_version = '>= 2.0'
22
+
23
+ spec.add_runtime_dependency 'httparty', '~> 0.13'
24
+
25
+ spec.add_development_dependency 'bundler', '~> 1.7'
26
+ spec.add_development_dependency 'rake', '~> 10.0'
27
+ end
@@ -0,0 +1,162 @@
1
+ module CyberCoach
2
+ #
3
+ # An AbstractResource can be read.
4
+ # Sets up serialization and deserialization using JSON.
5
+ #
6
+ class AbstractResource < Object
7
+ #
8
+ # Installs utilities to handle HTTP request and response.
9
+ # See {API doc}[http://www.rubydoc.info/github/jnunemaker/httparty] and
10
+ # {examples}[https://github.com/jnunemaker/httparty/tree/master/examples].
11
+ #
12
+ include HTTParty
13
+
14
+ #
15
+ # :private_attr: options
16
+ # The options that are always sent with each request, e.g. :basic_auth.
17
+ #
18
+
19
+ #
20
+ # The URI, the global identifier of it.
21
+ #
22
+ attr_accessor :uri
23
+
24
+ headers 'content-type' => 'application/json', 'accept' => 'application/json'
25
+ format :json
26
+ base_uri CyberCoach::Settings::SERVER_URI
27
+
28
+ #
29
+ # Creates an AbstractResource.
30
+ #
31
+ def initialize
32
+ super
33
+ @uri = nil
34
+ @options = {}
35
+ end
36
+
37
+ #
38
+ # :category: CRUD
39
+ #
40
+ # Reads it.
41
+ # Gets the URI from the response and reads itself again.
42
+ # Raises HttpError if the request is unsuccessful.
43
+ # options:: A hash of options to send with the request.
44
+ #
45
+ def read(options = {})
46
+ invalidate_uri
47
+ invalidate_options
48
+ options = @options.merge(options)
49
+ response = self.class.get(@uri, options)
50
+ if response.success?
51
+ deserialize(response)
52
+ else
53
+ raise HttpError.new(response.response)
54
+ end
55
+ end
56
+
57
+ #
58
+ # :category: Serialization
59
+ #
60
+ # Returns a text based representations.
61
+ #
62
+ def serialize
63
+ format = self.class.default_options[:format]
64
+ if format.nil?
65
+ to_serializable
66
+ elsif format == :json
67
+ to_serializable.to_json
68
+ else
69
+ raise FormatNotSupportedError.new
70
+ end
71
+ end
72
+
73
+ #
74
+ # :category: Serialization
75
+ #
76
+ # Deserializes it from a text based representation.
77
+ # serialization:: A text based representation.
78
+ #
79
+ def deserialize(serialization)
80
+ from_serializable(serialization)
81
+ end
82
+
83
+ #
84
+ # :category: Serialization
85
+ #
86
+ # Creates itself from a serializable representation, which only contains
87
+ # simple data types.
88
+ # serializable:: A hash with the keys:
89
+ # * uri:: The URI.
90
+ #
91
+ def from_serializable(serializable)
92
+ @uri = serializable['uri']
93
+ end
94
+
95
+ #
96
+ # :category: Serialization
97
+ #
98
+ # Returns a serializable representation, which only contains simple data
99
+ # types.
100
+ # The hash has the keys:
101
+ # * uri:: The URI.
102
+ #
103
+ def to_serializable
104
+ serializable = {}
105
+ serializable['uri'] = @uri
106
+ serializable
107
+ end
108
+
109
+ #
110
+ # :category: Configuration
111
+ #
112
+ # Returns the singular name of the resource.
113
+ # E.g. 'user' or 'entry'.
114
+ # This is used for parsing.
115
+ # Must be overridden in a subclass.
116
+ #
117
+ def singular_name
118
+ raise SubclassResponsibilityError.new
119
+ end
120
+
121
+ #
122
+ # :category: Configuration
123
+ #
124
+ # Returns the plural name of the resource.
125
+ # E.g. 'users' or 'entries'.
126
+ # This is used for parsing.
127
+ # Must be overridden in a subclass.
128
+ #
129
+ def plural_name
130
+ raise SubclassResponsibilityError.new
131
+ end
132
+
133
+ #
134
+ # :category: Configuration
135
+ #
136
+ # Returns the base URI relative to the server.
137
+ #
138
+ def resource_base_uri
139
+ "#{Settings::BASE_URI}/#{plural_name}/"
140
+ end
141
+
142
+ protected
143
+
144
+ #
145
+ # :category: Invalidation
146
+ #
147
+ # Recalculates the URI from the attributes.
148
+ # A template method called before a request is made.
149
+ #
150
+ def invalidate_uri
151
+ end
152
+
153
+ #
154
+ # :category: Invalidation
155
+ #
156
+ # Recalculates the request options from the attributes.
157
+ # A template method called before a request is made.
158
+ #
159
+ def invalidate_options
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,166 @@
1
+ module CyberCoach
2
+ #
3
+ # An Entry is submitted to a Subscription to represent a finished activity of
4
+ # a specific duration at a specific location.
5
+ #
6
+ class Entry < Resource
7
+ #
8
+ # It is creatable by POST.
9
+ #
10
+ include PostCreateable
11
+
12
+ #
13
+ # :attr: subscription
14
+ # The Subscription it belongs to.
15
+ #
16
+
17
+ #
18
+ # :attr: comment
19
+ # A comment.
20
+ #
21
+
22
+ #
23
+ # :attr: location
24
+ # A description of the location.
25
+ #
26
+
27
+ #
28
+ # :attr: duration
29
+ # The duration.
30
+ # Nobody knows its unit (seconds/minutes).
31
+ #
32
+
33
+ #
34
+ # :attr: privacy_level
35
+ # The privacy level, see PrivacyLevel constants.
36
+ #
37
+
38
+ #
39
+ # :attr: date_created
40
+ # The date it was created.
41
+ #
42
+
43
+ #
44
+ # :attr: date_modified
45
+ # The date it was modified the last time.
46
+ #
47
+
48
+ attr_accessor :subscription,
49
+ :comment,
50
+ :location,
51
+ :duration,
52
+ :privacy_level,
53
+ :date_created,
54
+ :date_modified
55
+
56
+ #
57
+ # :category: Serialization
58
+ #
59
+ # Creates itself from a serializable representation, which only contains
60
+ # simple data types.
61
+ # serializable:: A hash with a single key named like "entry#{@sport.name}" with another hash as value with the keys:
62
+ # * uri:: The URI.
63
+ # * id:: The identifier.
64
+ # * subscription:: A Subscription serializable.
65
+ # * comment:: A comment.
66
+ # * entrylocation:: A description of the location.
67
+ # * entryduration:: The duration. Nobody knows its unit (seconds/minutes).
68
+ # * publicvisible:: The privacy level, see PrivacyLevel constants.
69
+ # * datecreated:: The date it was created.
70
+ # * datemodified:: The date it was modified the last time.
71
+ #
72
+ def from_serializable(serializable)
73
+ # for some reason, the serializable is wrapped another level
74
+ serializable = serializable.values[0]
75
+ super(serializable)
76
+ @subscription = nil
77
+ unless serializable['subscription'].nil?
78
+ @subscription = Subscription.new
79
+ @subscription.from_serializable(serializable['subscription'])
80
+ end
81
+ @comment = serializable['comment']
82
+ @location = serializable['entrylocation']
83
+ @duration = serializable['entryduration']
84
+ @privacy_level = serializable['publicvisible']
85
+ @date_created = nil
86
+ unless serializable['datecreated'].nil?
87
+ @date_created = Time.at(serializable['datecreated']).to_datetime
88
+ end
89
+ @date_modified = nil
90
+ unless serializable['datemodified'].nil?
91
+ @date_modified = Time.at(serializable['datemodified']).to_datetime
92
+ end
93
+ end
94
+
95
+ #
96
+ # :category: Serialization
97
+ #
98
+ # Returns a serializable representation, which only contains simple data
99
+ # types.
100
+ # The hash has a single key named like "entry#{@sport.name}" with another hash as value with the keys:
101
+ # * uri:: The URI.
102
+ # * id:: The identifier.
103
+ # * comment:: A comment.
104
+ # * entrylocation:: A description of the location.
105
+ # * entryduration:: The duration. Nobody knows its unit (seconds/minutes).
106
+ # * publicvisible:: The privacy level, see PrivacyLevel constants.
107
+ #
108
+ def to_serializable
109
+ serializable = super
110
+ serializable['comment'] = @comment
111
+ serializable['entrylocation'] = @location
112
+ serializable['entryduration'] = @duration
113
+ serializable['publicvisible'] = @privacy_level
114
+ # cyber coach, you cunt!
115
+ sport = nil
116
+ if @id.nil?
117
+ sport = @subscription.uri.split('/')[-1].downcase
118
+ else
119
+ sport = @uri.split('/')[-2].downcase
120
+ end
121
+ {
122
+ "#{singular_name}#{sport}" => serializable
123
+ }
124
+ end
125
+
126
+ #
127
+ # :category: Configuration
128
+ #
129
+ # Returns 'entry'.
130
+ #
131
+ def singular_name
132
+ 'entry'
133
+ end
134
+
135
+ #
136
+ # :category: Configuration
137
+ #
138
+ # Returns 'entries'.
139
+ #
140
+ def plural_name
141
+ 'entries'
142
+ end
143
+
144
+ #
145
+ # :category: Configuration
146
+ #
147
+ # Return the URI of its subscription.
148
+ #
149
+ def resource_base_uri
150
+ @subscription.uri
151
+ end
152
+
153
+ protected
154
+
155
+ #
156
+ # :category: Invalidation
157
+ #
158
+ # Sets the uri to the base uri and the id, if it is not nil.
159
+ #
160
+ def invalidate_uri
161
+ unless @id.nil?
162
+ @uri = "#{resource_base_uri}#{@id}/"
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,7 @@
1
+ module CyberCoach
2
+ #
3
+ # Raised when a format to parse from or encode to is not supported.
4
+ #
5
+ class FormatNotSupportedError < RuntimeError
6
+ end
7
+ end
@@ -0,0 +1,27 @@
1
+ module CyberCoach
2
+ #
3
+ # Raised when a response is unsuccessful.
4
+ #
5
+ class HttpError < RuntimeError
6
+ #
7
+ # The response that caused it.
8
+ #
9
+ attr_accessor :cause
10
+
11
+ #
12
+ # Creates a HttpError.
13
+ # cause:: The response that caused it.
14
+ #
15
+ def initialize(cause)
16
+ super
17
+ @cause = cause
18
+ end
19
+
20
+ #
21
+ # Returns a string representation including the cause's header and body.
22
+ #
23
+ def to_s
24
+ "#{super}\n\t#{@cause.to_hash}\n\t#{@cause.body}"
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,38 @@
1
+ module CyberCoach
2
+ #
3
+ # Mixin to make a resource readable in pages.
4
+ # Include it in a class by to use it.
5
+ #
6
+ module Pageable
7
+ #
8
+ # Installs class and instance methods in the class it is included in.
9
+ #
10
+ def self.included(base)
11
+ base.extend ClassMethods
12
+ base.send :include, InstanceMethods
13
+ end
14
+
15
+ #
16
+ # The class methods to install.
17
+ #
18
+ module ClassMethods
19
+ #
20
+ # :category: CRUD
21
+ #
22
+ # Returns the first page of resources.
23
+ # options:: A hash of options to send with the request.
24
+ #
25
+ def read_all(options = {})
26
+ page = ResourcePage.new(self)
27
+ page.read(options)
28
+ page
29
+ end
30
+ end
31
+
32
+ #
33
+ # The instance methods to install.
34
+ #
35
+ module InstanceMethods
36
+ end
37
+ end
38
+ end