cybercoach 0.2.0 → 0.3.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.
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