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.
- checksums.yaml +4 -4
- data/.gitignore +45 -0
- data/.rspec +2 -0
- data/CHANGELOG.md +8 -0
- data/Gemfile +23 -0
- data/LICENSE.txt +22 -0
- data/README.md +31 -0
- data/Rakefile +2 -0
- data/cybercoach.gemspec +27 -0
- data/lib/cybercoach/abstract_resource.rb +162 -0
- data/lib/cybercoach/entry.rb +166 -0
- data/lib/cybercoach/format_not_supported_error.rb +7 -0
- data/lib/cybercoach/http_error.rb +27 -0
- data/lib/cybercoach/pageable.rb +38 -0
- data/lib/cybercoach/partnership.rb +151 -0
- data/lib/cybercoach/post_createable.rb +49 -0
- data/lib/cybercoach/privacy_level.rb +21 -0
- data/lib/cybercoach/put_createable.rb +48 -0
- data/lib/cybercoach/resource.rb +94 -0
- data/lib/cybercoach/resource_page.rb +191 -0
- data/lib/cybercoach/settings.rb +16 -0
- data/lib/cybercoach/sport.rb +104 -0
- data/lib/cybercoach/subclass_responsibility_error.rb +7 -0
- data/lib/cybercoach/subscription.rb +145 -0
- data/lib/cybercoach/user.rb +159 -0
- data/lib/cybercoach/version.rb +10 -0
- data/lib/cybercoach.rb +19 -0
- data/spec/lib/cybercoach/entry_spec.rb +95 -0
- data/spec/lib/cybercoach/partnership_spec.rb +79 -0
- data/spec/lib/cybercoach/privacy_level_spec.rb +15 -0
- data/spec/lib/cybercoach/resource_helper.rb +11 -0
- data/spec/lib/cybercoach/resource_page_spec.rb +44 -0
- data/spec/lib/cybercoach/settings_spec.rb +10 -0
- data/spec/lib/cybercoach/sport_spec.rb +29 -0
- data/spec/lib/cybercoach/subscription_spec.rb +129 -0
- data/spec/lib/cybercoach/user_helper.rb +22 -0
- data/spec/lib/cybercoach/user_spec.rb +82 -0
- data/spec/lib/cybercoach_helper.rb +2 -0
- data/spec/lib/integration_spec.rb +56 -0
- data/spec/spec_helper.rb +19 -0
- metadata +56 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 59526a9235348317412b0f880b808b23357827aa
|
4
|
+
data.tar.gz: 77285e272d541197cd65e1752fae2d96f0ff78ce
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
data/CHANGELOG.md
ADDED
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
data/cybercoach.gemspec
ADDED
@@ -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,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
|