totter 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
data/Readme.markdown CHANGED
@@ -6,7 +6,9 @@ All networking is done with Net::HTTP so you don't have to worry about version c
6
6
 
7
7
  Read the [documentation](http://rubydoc.info/github/seesawco/totter-rb/master/frames) online.
8
8
 
9
- [![Build Status](https://travis-ci.org/seesawco/totter-rb.png?branch=master)](https://travis-ci.org/seesawco/totter-rb) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/seesawco/totter-rb)
9
+ [![Build Status](https://travis-ci.org/seesawco/totter-rb.png?branch=master)](https://travis-ci.org/seesawco/totter-rb)
10
+
11
+ [![Code Climate](https://codeclimate.com/github/seesawco/totter-rb.png)](https://codeclimate.com/github/seesawco/totter-rb)
10
12
 
11
13
  ## Installation
12
14
 
@@ -2,17 +2,22 @@ module Totter
2
2
  class Client
3
3
  # Client methods for working with timelines
4
4
  module Timelines
5
+ # Default options sent with every timeline request unless otherwise specified.
6
+ DEFAULT_TIMELINE_OPTIONS = {
7
+ limit: 20
8
+ }
9
+
5
10
  # Get recent decisions from the global timeline.
6
11
  #
7
12
  # @param options [Hash] Parameters for returning selected items
8
13
  # @option options [Numeric] :limit Number of items to return. Default is 20
9
14
  # @option options [String] :since A user_id/decision_id pair in the format '1,15' when paging forward
10
15
  # @option options [String] :until A user_id/decision_id pair in the format '1,15' when paging backwards
11
- # @return [Array]
16
+ # @return [Array] An array of `Hashie::Mash` objects representing decisions
12
17
  # @example
13
18
  # Seesaw.global_timeline(limit: 20, since: '1,15')
14
- def global_timeline(options = default_options)
15
- get "timelines/global", options
19
+ def global_timeline(options = DEFAULT_TIMELINE_OPTIONS)
20
+ get 'timelines/global', options
16
21
  end
17
22
 
18
23
  # Get recent decisions from a hashtag timeline
@@ -22,11 +27,11 @@ module Totter
22
27
  # @option options [Numeric] :limit Number of items to return. Default is 20
23
28
  # @option options [String] :since A user_id/decision_id pair in the format '1,15' when paging forward
24
29
  # @option options [String] :until A user_id/decision_id pair in the format '1,15' when paging backwards
25
- # @return [Array]
30
+ # @return [Array] An array of `Hashie::Mash` objects representing decisions
26
31
  # @example
27
32
  # Seesaw.global_timeline(limit: 20, since: '1,15')
28
- def hashtag_timeline(hashtag, options = default_options)
29
- get "timelines/global", options.merge({hashtag: hashtag})
33
+ def hashtag_timeline(hashtag, options = DEFAULT_TIMELINE_OPTIONS)
34
+ get 'timelines/global', options.merge({hashtag: hashtag})
30
35
  end
31
36
 
32
37
  # Get recent decisions from a sticker timeline
@@ -39,8 +44,8 @@ module Totter
39
44
  # @return [Array]
40
45
  # @example
41
46
  # Seesaw.global_timeline(limit: 20, since: '1,15')
42
- def sticker_timeline(sticker, options = default_options)
43
- get "timelines/global", options.merge({sticker: sticker})
47
+ def sticker_timeline(sticker, options = DEFAULT_TIMELINE_OPTIONS)
48
+ get 'timelines/global', options.merge({sticker: sticker})
44
49
  end
45
50
 
46
51
  # Search for published items
@@ -50,11 +55,11 @@ module Totter
50
55
  # @option options [Numeric] :limit Number of items to return. Default is 20
51
56
  # @option options [String] :since A user_id/decision_id pair in the format '1,15' when paging forward
52
57
  # @option options [String] :until A user_id/decision_id pair in the format '1,15' when paging backwards
53
- # @return [Array]
58
+ # @return [Array] An array of `Hashie::Mash` objects representing decisions
54
59
  # @example
55
60
  # Seesaw.global_timeline(limit: 20, since: '1,15')
56
- def search_timeline(query, options = default_options)
57
- get "timelines/search", options.merge({query: query})
61
+ def search_timeline(query, options = DEFAULT_TIMELINE_OPTIONS)
62
+ get 'timelines/search', options.merge({query: query})
58
63
  end
59
64
 
60
65
  # Get recent decisions from the flagged-for-review timeline
@@ -63,19 +68,25 @@ module Totter
63
68
  # @option options [Numeric] :limit Number of items to return. Default is 20
64
69
  # @option options [String] :since A user_id/decision_id pair in the format '1,15' when paging forward
65
70
  # @option options [String] :until A user_id/decision_id pair in the format '1,15' when paging backwards
66
- # @return [Array]
71
+ # @return [Array] An array of `Hashie::Mash` objects representing decisions
67
72
  # @example
68
73
  # Seesaw.global_timeline(limit: 20, since: '1,15')
69
- def flagged_timeline(options = default_options)
70
- get "timelines/flagged", options
74
+ def flagged_timeline(options = DEFAULT_TIMELINE_OPTIONS)
75
+ get 'timelines/flagged', options
71
76
  end
72
77
 
73
- private
74
-
75
- def default_options
76
- {
77
- limit: 20
78
- }
78
+ # Get recent decisions from a given user.
79
+ #
80
+ # @param user_id [Fixnum] The user ID for the timeline you are trying to view.
81
+ # @param options [Hash] Parameters for returning selected items
82
+ # @option options [Numeric] :limit Number of items to return. Default is 20
83
+ # @option options [String] :since A user_id/decision_id pair in the format '1,15' when paging forward
84
+ # @option options [String] :until A user_id/decision_id pair in the format '1,15' when paging backwards
85
+ # @return [Array] An array of `Hashie::Mash` objects representing decisions
86
+ # @example
87
+ # Seesaw.user_timeline(4, limit: 20, since: '1,15')
88
+ def user_timeline(user_id, options = DEFAULT_TIMELINE_OPTIONS)
89
+ get "users/#{user_id}/timelines/user", options
79
90
  end
80
91
  end
81
92
  end
data/lib/totter/client.rb CHANGED
@@ -1,21 +1,10 @@
1
- require 'net/http'
2
- require 'net/https'
3
- require 'uri'
4
- require 'multi_json'
5
- require 'hashie'
6
- require 'addressable/uri'
7
-
8
- require 'totter/client/users'
9
- require 'totter/client/decisions'
10
- require 'totter/client/slugs'
11
- require 'totter/client/timelines'
12
- require 'totter/client/choices'
13
- require 'totter/client/votes'
14
- require 'totter/client/avatars'
1
+ require 'totter/transport'
15
2
 
16
3
  module Totter
17
4
  # API client for interacting with the Seesaw API
18
5
  class Client
6
+ Dir[File.expand_path('../client/*.rb', __FILE__)].each { |f| require f }
7
+
19
8
  include Totter::Client::Decisions
20
9
  include Totter::Client::Users
21
10
  include Totter::Client::Slugs
@@ -28,10 +17,11 @@ module Totter
28
17
  attr_reader :api_scheme
29
18
  attr_reader :api_host
30
19
  attr_reader :api_version
20
+ attr_reader :transport
31
21
 
32
22
  # Initialize a new client.
33
23
  #
34
- # @param options [Hash] optionally specify `:access_token`, `:api_scheme`, `:api_host`, `:api_version`, or `:client_token`
24
+ # @param options [Hash] optionally specify `:access_token`, `:api_scheme`, `:api_host`, `:api_version`, `:client_token`, or `:transport`.
35
25
  def initialize(options = {})
36
26
  options = { access_token: options } if options.is_a? String
37
27
 
@@ -40,6 +30,12 @@ module Totter
40
30
  @api_host = (options[:api_host] or 'api.seesaw.co')
41
31
  @api_version = (options[:api_version] or 1)
42
32
  @client_token = options[:client_token] if options[:client_token]
33
+ @transport = (options[:transport] or :http)
34
+
35
+ # Include transport
36
+ transport_module = Totter::Transport::TRANSPORT_MAP[@transport]
37
+ raise 'Invalid transport' unless transport_module
38
+ self.extend transport_module
43
39
  end
44
40
 
45
41
  # API base URL.
@@ -62,105 +58,5 @@ module Totter
62
58
  def ssl?
63
59
  @api_scheme == 'https'
64
60
  end
65
-
66
- private
67
-
68
- def http
69
- return @http if @http
70
-
71
- uri = URI.parse(self.base_url)
72
- @http = Net::HTTP.new(uri.host, uri.port)
73
- @http.use_ssl = self.ssl?
74
- @http
75
- end
76
-
77
- def request(method, path, params = nil)
78
- uri = Addressable::URI.parse("#{self.base_url}#{path}")
79
-
80
- # if the request requires parameters in the query string, merge them in
81
- if params and !can_post_data?(method)
82
- uri.query_values = (uri.query_values || {}).merge(params)
83
- end
84
-
85
- # Build request
86
- request = build_request(method, uri)
87
-
88
- # Add headers
89
- request['Authorization'] = "Bearer #{self.access_token}" if authenticated?
90
- request['X-Seesaw-Client-Token'] = @client_token if @client_token
91
- request['Content-Type'] = 'application/json'
92
-
93
- # Add params as JSON if they exist
94
- request.body = MultiJson.dump(params) if can_post_data?(method) and params
95
-
96
- # Request
97
- response = http.request(request)
98
-
99
- # Check for errors
100
- handle_error(response)
101
-
102
- # Return the raw response object
103
- response
104
- end
105
-
106
- def build_request(method, uri)
107
- case method
108
- when :get
109
- Net::HTTP::Get.new(uri.request_uri)
110
- when :post
111
- Net::HTTP::Post.new(uri.request_uri)
112
- when :put
113
- Net::HTTP::Put.new(uri.request_uri)
114
- when :delete
115
- Net::HTTP::Delete.new(uri.request_uri)
116
- end
117
- end
118
-
119
- def handle_error(response)
120
- # Find error or return
121
- return unless error = Totter::ERROR_MAP[response.code.to_i]
122
-
123
- # Try to add a useful message
124
- message = nil
125
- begin
126
- message = MultiJson.load(response.body)['error_description']
127
- rescue MultiJson::DecodeError => e
128
- end
129
-
130
- # Raise error
131
- raise error.new(message)
132
- end
133
-
134
- def json_request(*args)
135
- # Preform request
136
- response = request(*args)
137
-
138
- # Parse JSON
139
- object = MultiJson.load(response.body)
140
-
141
- # Hash
142
- return Hashie::Mash.new(object) if object.is_a? Hash
143
-
144
- # Array
145
- return object.map { |h| Hashie::Mash.new(h) } if object.is_a? Array
146
-
147
- # Fallback incase it's not a hash or array
148
- object
149
- end
150
-
151
- def boolean_from_response(*args)
152
- response = request(*args)
153
- (200..299).include? response.code.to_i
154
- end
155
-
156
- def can_post_data?(method)
157
- [:post, :put].include?(method)
158
- end
159
-
160
- [:get, :post, :put, :delete].each do |method|
161
- define_method method do |*args|
162
- json_request(method, *args)
163
- end
164
- end
165
61
  end
166
62
  end
@@ -0,0 +1,113 @@
1
+ module Totter
2
+ module Transport
3
+ # Default HTTP API transport adapter
4
+ module HTTP
5
+ require 'net/http'
6
+ require 'net/https'
7
+ require 'uri'
8
+ require 'multi_json'
9
+ require 'hashie'
10
+
11
+ private
12
+
13
+ def http
14
+ return @http if @http
15
+
16
+ uri = URI.parse(self.base_url)
17
+ @http = Net::HTTP.new(uri.host, uri.port)
18
+ @http.use_ssl = self.ssl?
19
+ @http
20
+ end
21
+
22
+ def request(method, path, params = nil)
23
+ uri = URI.parse("#{self.base_url}#{path}")
24
+
25
+ # if the request requires parameters in the query string, merge them in
26
+ if params and !can_post_data?(method)
27
+ query_values = uri.query ? URI.decode_www_form(uri.query).inject({}) {|h,(k,v)| h[k]=v; h} : {}
28
+ uri.query = URI.encode_www_form (query_values || {}).merge(params)
29
+ end
30
+
31
+ # Build request
32
+ request = build_request(method, uri)
33
+
34
+ # Add headers
35
+ request['Authorization'] = "Bearer #{self.access_token}" if authenticated?
36
+ request['X-Seesaw-Client-Token'] = @client_token if @client_token
37
+ request['Content-Type'] = 'application/json'
38
+
39
+ # Add params as JSON if they exist
40
+ request.body = MultiJson.dump(params) if can_post_data?(method) and params
41
+
42
+ # Request
43
+ response = http.request(request)
44
+
45
+ # Check for errors
46
+ handle_error(response)
47
+
48
+ # Return the raw response object
49
+ response
50
+ end
51
+
52
+ def build_request(method, uri)
53
+ case method
54
+ when :get
55
+ Net::HTTP::Get.new(uri.request_uri)
56
+ when :post
57
+ Net::HTTP::Post.new(uri.request_uri)
58
+ when :put
59
+ Net::HTTP::Put.new(uri.request_uri)
60
+ when :delete
61
+ Net::HTTP::Delete.new(uri.request_uri)
62
+ end
63
+ end
64
+
65
+ def handle_error(response)
66
+ # Find error or return
67
+ return unless error = Totter::ERROR_MAP[response.code.to_i]
68
+
69
+ # Try to add a useful message
70
+ message = nil
71
+ begin
72
+ message = MultiJson.load(response.body)['error_description']
73
+ rescue MultiJson::DecodeError => e
74
+ end
75
+
76
+ # Raise error
77
+ raise error.new(message)
78
+ end
79
+
80
+ def json_request(*args)
81
+ # Preform request
82
+ response = request(*args)
83
+
84
+ # Parse JSON
85
+ object = MultiJson.load(response.body)
86
+
87
+ # Hash
88
+ return Hashie::Mash.new(object) if object.is_a? Hash
89
+
90
+ # Array
91
+ return object.map { |h| Hashie::Mash.new(h) } if object.is_a? Array
92
+
93
+ # Fallback incase it's not a hash or array
94
+ object
95
+ end
96
+
97
+ def boolean_from_response(*args)
98
+ response = request(*args)
99
+ (200..299).include? response.code.to_i
100
+ end
101
+
102
+ def can_post_data?(method)
103
+ [:post, :put].include?(method)
104
+ end
105
+
106
+ [:get, :post, :put, :delete].each do |method|
107
+ define_method method do |*args|
108
+ json_request(method, *args)
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,11 @@
1
+ module Totter
2
+ # Transports are a way for the client to communicate with the API.
3
+ module Transport
4
+ Dir[File.expand_path('../transport/*.rb', __FILE__)].each { |f| require f }
5
+
6
+ # Transport adapter map
7
+ TRANSPORT_MAP = {
8
+ http: Totter::Transport::HTTP
9
+ }
10
+ end
11
+ end
@@ -1,4 +1,4 @@
1
1
  module Totter
2
2
  # Verion of the Totter gem
3
- VERSION = '0.2.3'
3
+ VERSION = '0.2.4'
4
4
  end
@@ -0,0 +1,46 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://localhost:5000/v1/users/4/timelines/user?limit=20
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - ! '*/*'
12
+ User-Agent:
13
+ - Ruby
14
+ Authorization:
15
+ - Bearer 9774e653f7b3c1de5f21b61adc08ba24
16
+ Content-Type:
17
+ - application/json
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ X-Pusher-Channel:
24
+ - timeline-user-4
25
+ Content-Type:
26
+ - application/json; charset=utf-8
27
+ X-Ua-Compatible:
28
+ - IE=Edge
29
+ Etag:
30
+ - ! '"d751713988987e9331980363e24189ce"'
31
+ Cache-Control:
32
+ - max-age=0, private, must-revalidate
33
+ X-Request-Id:
34
+ - aeaaf8b6b674667481f04ef39c7f0812
35
+ X-Runtime:
36
+ - '0.009301'
37
+ Connection:
38
+ - close
39
+ Server:
40
+ - thin 1.5.0 codename Knife
41
+ body:
42
+ encoding: US-ASCII
43
+ string: ! '[]'
44
+ http_version:
45
+ recorded_at: Tue, 05 Feb 2013 16:21:27 GMT
46
+ recorded_with: VCR 2.4.0
@@ -34,4 +34,11 @@ class TimelinesTest < Totter::TestCase
34
34
  assert_equal 1, local_client.flagged_timeline.length
35
35
  end
36
36
  end
37
+
38
+ def test_user
39
+ VCR.use_cassette 'timelines/user' do
40
+ client = local_client
41
+ assert_equal 0, local_client.user_timeline(4).length
42
+ end
43
+ end
37
44
  end
data/totter.gemspec CHANGED
@@ -21,5 +21,4 @@ Gem::Specification.new do |gem|
21
21
  gem.required_ruby_version = '>= 1.9.2'
22
22
  gem.add_dependency 'multi_json', '~> 1.5.0'
23
23
  gem.add_dependency 'hashie', '~> 1.2.0'
24
- gem.add_dependency 'addressable', '~> 2.3.0'
25
24
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: totter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-02-04 00:00:00.000000000 Z
13
+ date: 2013-02-05 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: multi_json
@@ -44,22 +44,6 @@ dependencies:
44
44
  - - ~>
45
45
  - !ruby/object:Gem::Version
46
46
  version: 1.2.0
47
- - !ruby/object:Gem::Dependency
48
- name: addressable
49
- requirement: !ruby/object:Gem::Requirement
50
- none: false
51
- requirements:
52
- - - ~>
53
- - !ruby/object:Gem::Version
54
- version: 2.3.0
55
- type: :runtime
56
- prerelease: false
57
- version_requirements: !ruby/object:Gem::Requirement
58
- none: false
59
- requirements:
60
- - - ~>
61
- - !ruby/object:Gem::Version
62
- version: 2.3.0
63
47
  description: Ruby gem for working with the Seesaw API.
64
48
  email:
65
49
  - sam@soff.es
@@ -85,6 +69,8 @@ files:
85
69
  - lib/totter/client/users.rb
86
70
  - lib/totter/client/votes.rb
87
71
  - lib/totter/error.rb
72
+ - lib/totter/transport.rb
73
+ - lib/totter/transport/http.rb
88
74
  - lib/totter/version.rb
89
75
  - test/cassettes/avatars/create.yml
90
76
  - test/cassettes/avatars/destroy.yml
@@ -107,6 +93,7 @@ files:
107
93
  - test/cassettes/timelines/hashtags.yml
108
94
  - test/cassettes/timelines/search.yml
109
95
  - test/cassettes/timelines/stickers.yml
96
+ - test/cassettes/timelines/user.yml
110
97
  - test/cassettes/users/following.yml
111
98
  - test/cassettes/users/me.yml
112
99
  - test/cassettes/users/update.yml
@@ -143,6 +130,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
143
130
  - - ! '>='
144
131
  - !ruby/object:Gem::Version
145
132
  version: '0'
133
+ segments:
134
+ - 0
135
+ hash: 3570192698254323384
146
136
  requirements: []
147
137
  rubyforge_project:
148
138
  rubygems_version: 1.8.23
@@ -171,6 +161,7 @@ test_files:
171
161
  - test/cassettes/timelines/hashtags.yml
172
162
  - test/cassettes/timelines/search.yml
173
163
  - test/cassettes/timelines/stickers.yml
164
+ - test/cassettes/timelines/user.yml
174
165
  - test/cassettes/users/following.yml
175
166
  - test/cassettes/users/me.yml
176
167
  - test/cassettes/users/update.yml