teamsnap_rb 0.0.8 → 1.0.0.beta1

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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +13 -0
  3. data/Gemfile +2 -1
  4. data/LICENSE +1 -1
  5. data/README.md +31 -79
  6. data/Rakefile +19 -1
  7. data/lib/teamsnap/version.rb +3 -0
  8. data/lib/teamsnap.rb +270 -0
  9. data/spec/cassettes/apiv3-init.yml +1963 -0
  10. data/spec/cassettes/teamsnap_rb/adds_find_if_search_is_available.yml +56 -0
  11. data/spec/cassettes/teamsnap_rb/can_follow_plural_links.yml +111 -0
  12. data/spec/cassettes/teamsnap_rb/can_follow_singular_links.yml +105 -0
  13. data/spec/cassettes/teamsnap_rb/can_handle_an_empty_bulk_load.yml +52 -0
  14. data/spec/cassettes/teamsnap_rb/can_handle_an_error_with_bulk_load.yml +50 -0
  15. data/spec/cassettes/teamsnap_rb/can_handle_errors_generated_by_command.yml +50 -0
  16. data/spec/cassettes/teamsnap_rb/can_handle_links_with_no_data.yml +101 -0
  17. data/spec/cassettes/teamsnap_rb/can_use_bulk_load.yml +61 -0
  18. data/spec/cassettes/teamsnap_rb/handles_executing_an_action_via_commands.yml +54 -0
  19. data/spec/cassettes/teamsnap_rb/handles_fetching_data_via_queries.yml +56 -0
  20. data/spec/cassettes/teamsnap_rb/handles_queries_with_no_data.yml +53 -0
  21. data/spec/cassettes/teamsnap_rb/raises_an_exception_if_find_returns_nothing.yml +53 -0
  22. data/spec/spec_helper.rb +18 -13
  23. data/spec/teamsnap_spec.rb +125 -0
  24. data/teamsnap_rb.gemspec +17 -15
  25. metadata +100 -84
  26. data/lib/teamsnap_rb/client.rb +0 -8
  27. data/lib/teamsnap_rb/collection.rb +0 -179
  28. data/lib/teamsnap_rb/command.rb +0 -39
  29. data/lib/teamsnap_rb/commands.rb +0 -40
  30. data/lib/teamsnap_rb/config.rb +0 -14
  31. data/lib/teamsnap_rb/exceptions.rb +0 -3
  32. data/lib/teamsnap_rb/item.rb +0 -136
  33. data/lib/teamsnap_rb/link.rb +0 -24
  34. data/lib/teamsnap_rb/links_proxy.rb +0 -40
  35. data/lib/teamsnap_rb/models/event.rb +0 -4
  36. data/lib/teamsnap_rb/models/user.rb +0 -4
  37. data/lib/teamsnap_rb/queries_proxy.rb +0 -68
  38. data/lib/teamsnap_rb/request_builder.rb +0 -67
  39. data/lib/teamsnap_rb/template.rb +0 -37
  40. data/lib/teamsnap_rb/version.rb +0 -3
  41. data/lib/teamsnap_rb.rb +0 -22
  42. data/spec/client_spec.rb +0 -39
  43. data/spec/collection_spec.rb +0 -175
  44. data/spec/command_spec.rb +0 -60
  45. data/spec/commands_spec.rb +0 -35
  46. data/spec/config_spec.rb +0 -16
  47. data/spec/fixtures/cassettes/production_root.yml +0 -59
  48. data/spec/fixtures/cassettes/root.yml +0 -573
  49. data/spec/fixtures/cassettes/team.yml +0 -4858
  50. data/spec/fixtures/cassettes/teams.yml +0 -160
  51. data/spec/item_spec.rb +0 -133
  52. data/spec/link_spec.rb +0 -43
  53. data/spec/links_proxy_spec.rb +0 -32
  54. data/spec/queries_proxy_spec.rb +0 -31
  55. data/spec/template_spec.rb +0 -57
@@ -1,179 +0,0 @@
1
- module TeamsnapRb
2
- class Collection
3
- include Enumerable
4
-
5
- attr_reader :errors
6
-
7
- TYPE_TO_CLASS = {
8
- "Event" => Event
9
- }
10
-
11
- def initialize(url, query_parameters, config, options = {})
12
- request = options.fetch(:request, nil)
13
-
14
- self.config = config
15
- data = request || get(url, query_parameters)
16
- self.errors = []
17
- self.url = data.env["url"]
18
- body = data.body
19
-
20
- if data.success?
21
- deserializer = Conglomerate::TreeDeserializer.new(JSON.parse(body))
22
- self.collection_json = deserializer.deserialize
23
- self.items = collection_json.items.map do |item|
24
- type_name = item.data.find do |datum|
25
- datum.name == "type"
26
- end.value
27
-
28
- klass = TYPE_TO_CLASS[type_name] || Item
29
- klass.new(item, config)
30
- end
31
-
32
- if collection_json.error
33
- errors << collection_json.error.message
34
- end
35
- else
36
- errors << data.status.to_s
37
- end
38
-
39
- handle_error(errors)
40
- end
41
-
42
- def [](index)
43
- items[index]
44
- end
45
-
46
- def each
47
- items.each do |item|
48
- yield item
49
- end
50
- end
51
-
52
- def where(attribute_hash)
53
- CollectionWhereProxy.new(items).where(attribute_hash)
54
- end
55
-
56
- def href
57
- collection_json.href
58
- end
59
-
60
- def method_missing(method, *args)
61
- if links.respond_to?(method)
62
- links.send(method)
63
- elsif queries.respond_to?(method)
64
- queries.send(method, *args)
65
- else
66
- super
67
- end
68
- end
69
-
70
- def respond_to?(method)
71
- links.respond_to?(method) || queries.respond_to?(method)
72
- end
73
-
74
- def links
75
- @links ||= LinksProxy.new(collection_json.links, config)
76
- end
77
-
78
- def queries
79
- @queries ||= QueriesProxy.new(collection_json.queries, config)
80
- end
81
-
82
- def template
83
- @template ||= Template.new(collection_json.template, config, href)
84
- end
85
-
86
- def commands
87
- @commands ||= CommandsProxy.new(collection_json.commands, config)
88
- end
89
-
90
- def error
91
- errors
92
- end
93
-
94
- def error?
95
- errors.count > 0
96
- end
97
-
98
- def size
99
- items.size
100
- end
101
-
102
- def present?
103
- items.size > 0
104
- end
105
-
106
- def blank?
107
- items.size == 0
108
- end
109
-
110
- private
111
-
112
- attr_accessor :collection_json, :config, :items, :url
113
- attr_writer :errors
114
-
115
- def get(url, query_parameters = {})
116
- RequestBuilder.new(config, url).connection.get do |conn|
117
- query_parameters.each do |key, value|
118
- conn.params[key] = value
119
- end
120
- end
121
- end
122
-
123
- def this_href
124
- collection_json.links.find { |l| l.rel == "self" }.href
125
- end
126
-
127
- def handle_error(errors)
128
- if errors.include?("401")
129
- raise HttpError, "401 Unauthorized for #{url}"
130
- end
131
- end
132
-
133
- class CollectionWhereProxy
134
- include Enumerable
135
-
136
- def initialize(items)
137
- self.items = items
138
- end
139
-
140
- def [](index)
141
- items[index]
142
- end
143
-
144
- def each
145
- items.each do |item|
146
- yield item
147
- end
148
- end
149
-
150
- def size
151
- items.size
152
- end
153
-
154
- def present?
155
- items.size > 0
156
- end
157
-
158
- def blank?
159
- items.size == 0
160
- end
161
-
162
- def where(attribute_hash)
163
- CollectionWhereProxy.new(find_all do |item|
164
- attribute_hash.keys.all? do |key|
165
- if item.respond_to?(key)
166
- attribute_hash[key] == item.send(key)
167
- else
168
- false
169
- end
170
- end
171
- end)
172
- end
173
-
174
- private
175
-
176
- attr_accessor :items
177
- end
178
- end
179
- end
@@ -1,39 +0,0 @@
1
- module TeamsnapRb
2
- class Command
3
- def initialize(command, config)
4
- self.command = command
5
- self.config = config
6
- end
7
-
8
- def execute(attrs = {})
9
- post(attrs.flatten.first)
10
- end
11
-
12
- def rel
13
- command.rel
14
- end
15
-
16
- def href
17
- command.href
18
- end
19
-
20
- def prompt
21
- command.prompt
22
- end
23
-
24
- def data
25
- command.data.map(&:name)
26
- end
27
-
28
- private
29
-
30
- def post(attrs = {})
31
- RequestBuilder.new(config, href).connection.post do |conn|
32
- conn.body = attrs.to_json
33
- conn.headers['Content-Type'] = 'application/json'
34
- end
35
- end
36
-
37
- attr_accessor :command, :config
38
- end
39
- end
@@ -1,40 +0,0 @@
1
- module TeamsnapRb
2
- class CommandsProxy
3
- include Enumerable
4
-
5
- def initialize(commands, config)
6
- self.config = config
7
- self.commands = commands.inject({}) do |h, command|
8
- h.tap do |hash|
9
- hash[command.rel.to_sym] = Command.new(command, config)
10
- end
11
- end
12
- end
13
-
14
- def method_missing(method, *args)
15
- if command = commands[method.to_sym]
16
- command.execute(args)
17
- else
18
- super
19
- end
20
- end
21
-
22
- def respond_to?(method)
23
- commands.include?(method.to_sym) || super
24
- end
25
-
26
- def each
27
- commands.values.each do |command|
28
- yield command
29
- end
30
- end
31
-
32
- def rels
33
- commands.keys
34
- end
35
-
36
- private
37
-
38
- attr_accessor :commands, :config
39
- end
40
- end
@@ -1,14 +0,0 @@
1
- module TeamsnapRb
2
- class Config
3
- attr_accessor :access_token, :client_id, :client_secret, :request_middleware, :response_middleware, :authorization
4
-
5
- def initialize(options = {})
6
- self.authorization = options.fetch(:authorization, nil)
7
- self.access_token = options.fetch(:access_token, nil)
8
- self.client_secret = options.fetch(:client_secret, nil)
9
- self.client_id = options.fetch(:client_id, nil)
10
- self.response_middleware = []
11
- self.request_middleware = []
12
- end
13
- end
14
- end
@@ -1,3 +0,0 @@
1
- module TeamsnapRb
2
- class HttpError < StandardError; end
3
- end
@@ -1,136 +0,0 @@
1
- module TeamsnapRb
2
- class Item
3
- class << self
4
- attr_accessor :templates
5
- end
6
- @templates = {}
7
-
8
- def initialize(item, config)
9
- self.config = config
10
- self.item = item
11
- end
12
-
13
- def href
14
- item.href
15
- end
16
-
17
- def data
18
- item.data
19
- end
20
-
21
- def template
22
- self.class.templates[type] ||= fetch_template
23
- end
24
-
25
- def this
26
- @this ||= Collection.new(href, {}, config)
27
- end
28
-
29
- def links
30
- @links ||= LinksProxy.new(item.links, config)
31
- end
32
-
33
- def commands
34
- @commands ||= CommandsProxy.new(this.commands, config)
35
- end
36
-
37
- def delete
38
- response = delete_href(href)
39
- if response.status == 204
40
- true
41
- else
42
- raise FailedToDelete
43
- end
44
- end
45
-
46
- def with(attrs)
47
- attrs = Hash[attrs.map{ |k, v| [k.to_s, v] }]
48
- dirtied_attrs = attrs.keys
49
- attrs = attributes.merge(attrs)
50
-
51
- new_data = attrs.inject([]) do |arr, (key, value)|
52
- arr << Conglomerate::Datum.new(:name => key, :value => value)
53
- end
54
-
55
- item = Conglomerate::Item.new(
56
- :href => href,
57
- :data => new_data
58
- )
59
-
60
- Item.new(item, config).tap do |it|
61
- it.send(:dirty, dirtied_attrs)
62
- end
63
- end
64
-
65
- def save
66
- attrs_to_update = dirty_attributes.inject({}) do |h, attr|
67
- h.tap do |hash|
68
- hash[attr] = attributes[attr]
69
- end
70
- end
71
-
72
- request = RequestBuilder.new(config, href).connection.patch do |conn|
73
- conn.body = template.build(attrs_to_update).to_json
74
- conn.headers["Content-Type"] = "application/json"
75
- end
76
-
77
- Collection.new(nil, nil, config, :request => request)
78
- end
79
-
80
- def method_missing(method, *args)
81
- if datum = data.find { |d| d.name == method.to_s }
82
- unless instance_variable_get("@#{method}_datum")
83
- instance_variable_set("@#{method}_datum", datum.value)
84
- end
85
-
86
- instance_variable_get("@#{method}_datum")
87
- elsif links.respond_to?(method)
88
- links.send(method)
89
- elsif commands.respond_to?(method)
90
- commands.send(method, args)
91
- else
92
- super
93
- end
94
- end
95
-
96
- def respond_to?(method)
97
- if data.find { |d| d.name == method.to_s }
98
- true
99
- elsif
100
- links.respond_to?(method)
101
- elsif
102
- commands.respond_to?(method)
103
- end
104
- end
105
-
106
- private
107
-
108
- def attributes
109
- @attributes ||= data.inject({}) do |h, datum|
110
- h.tap do |hash|
111
- hash[datum.name] = datum.value
112
- end
113
- end
114
- end
115
-
116
- def delete_href(href)
117
- RequestBuilder.new(config, href).connection.delete
118
- end
119
-
120
- def dirty(attrs)
121
- self.dirty_attributes = attrs
122
- end
123
-
124
- def fetch_template
125
- this.template
126
- end
127
-
128
- def fetch_commands
129
- this.commands
130
- end
131
-
132
- attr_accessor :item, :config, :dirty_attributes
133
- end
134
-
135
- class FailedToDelete < StandardError;end;
136
- end
@@ -1,24 +0,0 @@
1
- module TeamsnapRb
2
- class Link
3
- def initialize(link, config)
4
- self.config = config
5
- self.link = link
6
- end
7
-
8
- def follow
9
- @collection ||= Collection.new(href, {}, config)
10
- end
11
-
12
- def rel
13
- link.rel
14
- end
15
-
16
- def href
17
- link.href
18
- end
19
-
20
- private
21
-
22
- attr_accessor :config, :link
23
- end
24
- end
@@ -1,40 +0,0 @@
1
- module TeamsnapRb
2
- class LinksProxy
3
- include Enumerable
4
-
5
- def initialize(links, config)
6
- self.config = config
7
- self.links = links.inject({}) do |h, link|
8
- h.tap do |hash|
9
- hash[link.rel.to_sym] = Link.new(link, config)
10
- end
11
- end
12
- end
13
-
14
- def method_missing(method, *args)
15
- if link = links[method.to_sym]
16
- link.follow
17
- else
18
- super
19
- end
20
- end
21
-
22
- def respond_to?(method)
23
- links.include?(method.to_sym) || super
24
- end
25
-
26
- def each
27
- links.values.each do |link|
28
- yield link
29
- end
30
- end
31
-
32
- def rels
33
- links.keys
34
- end
35
-
36
- private
37
-
38
- attr_accessor :links, :config
39
- end
40
- end
@@ -1,4 +0,0 @@
1
- module TeamsnapRb
2
- class Event < Item
3
- end
4
- end
@@ -1,4 +0,0 @@
1
- module TeamsnapRb
2
- class User
3
- end
4
- end
@@ -1,68 +0,0 @@
1
- module TeamsnapRb
2
- class QueriesProxy
3
- include Enumerable
4
-
5
- def initialize(queries, config)
6
- self.config = config
7
- self.queries = queries.inject({}) do |h, query|
8
- h.tap do |hash|
9
- hash[query.rel.to_sym] = Query.new(query.href, query.data, config)
10
- end
11
- end
12
- end
13
-
14
- def method_missing(method, *args)
15
- if query = queries[method.to_sym]
16
- query.get(*args)
17
- else
18
- super
19
- end
20
- end
21
-
22
- def respond_to?(method)
23
- queries.include?(method.to_sym) || super
24
- end
25
-
26
- def each
27
- queries.values.each do |query|
28
- yield query
29
- end
30
- end
31
-
32
- def rels
33
- queries.keys
34
- end
35
-
36
- private
37
-
38
- attr_accessor :queries, :config
39
- end
40
-
41
- class Query
42
- MissingQueryParameter = Class.new(StandardError)
43
-
44
- def initialize(url, data, config)
45
- self.url = url
46
- self.data = data
47
- self.config = config
48
- end
49
-
50
- def get(query_parameters={})
51
- possible_params = data.map(&:name).map(&:to_sym)
52
- query_parameters.reject! { |key, value| !possible_params.include?(key) }
53
-
54
- if query_parameters.empty?
55
- raise(
56
- MissingQueryParameter,
57
- "You must provide at least one of the following parameters: #{possible_params}"
58
- )
59
- end
60
-
61
- Collection.new(url, query_parameters, config)
62
- end
63
-
64
- private
65
-
66
- attr_accessor :url, :data, :config
67
- end
68
- end
@@ -1,67 +0,0 @@
1
- require "openssl"
2
-
3
- module TeamsnapRb
4
- class RequestBuilder
5
- attr_reader :connection
6
-
7
- def initialize(config, url)
8
- self.config = config
9
- self.connection = Faraday::Connection.new(:url => url) do |faraday|
10
- config.request_middleware.each do |m|
11
- faraday.request(m)
12
- end
13
-
14
- config.response_middleware.each do |m|
15
- faraday.response(m)
16
- end
17
-
18
- faraday.request :teamsnap_config_middleware, config
19
- faraday.adapter Faraday.default_adapter
20
- end
21
- end
22
-
23
- private
24
-
25
- attr_accessor :config
26
- attr_writer :connection
27
- end
28
-
29
- class TeamsnapAuthMiddleware < Faraday::Middleware
30
- def initialize(app, *args, &block)
31
- self.config = args[0]
32
- super(app)
33
- end
34
-
35
- def call(env)
36
- if config.access_token
37
- env.request_headers["X-Teamsnap-Access-Token"] = config.access_token
38
- elsif config.authorization
39
- env.request_headers["Authorization"] = "Bearer #{config.authorization}"
40
- elsif config.client_id && config.client_secret
41
- query_params = Hash[URI.decode_www_form(env.url.query || "")]
42
- query_params.merge!({
43
- hmac_client_id: config.client_id,
44
- hmac_nonce: SecureRandom.uuid,
45
- hmac_timestamp: Time.now.to_i
46
- })
47
- env.url.query = URI.encode_www_form(query_params)
48
-
49
- message = "/?" + env.url.query.to_s + (env.body || "")
50
- digest = OpenSSL::Digest.new('sha256')
51
- message_hash = digest.hexdigest(message)
52
-
53
- env.request_headers["X-Teamsnap-Hmac"] = OpenSSL::HMAC.hexdigest(digest, config.client_secret, message_hash)
54
- end
55
-
56
- @app.call(env)
57
- end
58
-
59
- private
60
-
61
- attr_accessor :config
62
- end
63
-
64
- Faraday::Request.register_middleware(
65
- :teamsnap_config_middleware => lambda { TeamsnapAuthMiddleware }
66
- )
67
- end
@@ -1,37 +0,0 @@
1
- module TeamsnapRb
2
- class Template
3
- def initialize(template, config, url)
4
- self.config = config
5
- self.template = template
6
- self.url = url
7
- end
8
-
9
- def build(attrs={})
10
- @data = template.build(attrs)
11
- end
12
-
13
- def push(attrs={})
14
- build(attrs)
15
- publish
16
- end
17
-
18
- def data
19
- template.data
20
- end
21
-
22
- def publish
23
- post(url, @data) if @data
24
- end
25
-
26
- private
27
-
28
- attr_accessor :template, :config, :url
29
-
30
- def post(url, query_parameters = {})
31
- RequestBuilder.new(config, url).connection.post do |conn|
32
- conn.body = @data.to_json
33
- conn.headers['Content-Type'] = 'application/json'
34
- end
35
- end
36
- end
37
- end
@@ -1,3 +0,0 @@
1
- module TeamsnapRb
2
- VERSION = "0.0.8"
3
- end
data/lib/teamsnap_rb.rb DELETED
@@ -1,22 +0,0 @@
1
- require "conglomerate"
2
- require "json"
3
- require "faraday"
4
- require "securerandom"
5
-
6
- require_relative "teamsnap_rb/version"
7
- require_relative "teamsnap_rb/exceptions"
8
- require_relative "teamsnap_rb/config"
9
- require_relative "teamsnap_rb/request_builder"
10
- require_relative "teamsnap_rb/link"
11
- require_relative "teamsnap_rb/links_proxy"
12
- require_relative "teamsnap_rb/queries_proxy"
13
- require_relative "teamsnap_rb/item"
14
- require_relative "teamsnap_rb/template"
15
- require_relative "teamsnap_rb/command"
16
- require_relative "teamsnap_rb/commands"
17
- require_relative "teamsnap_rb/models/event"
18
- require_relative "teamsnap_rb/collection"
19
- require_relative "teamsnap_rb/client"
20
-
21
- module TeamsnapRb
22
- end