teamsnap_rb 0.0.8 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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