yam 0.0.6 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data.tar.gz.sig +0 -0
  2. data/.travis.yml +5 -0
  3. data/.yardopts +10 -0
  4. data/AUTHORS +1 -0
  5. data/CHANGELOG.md +7 -0
  6. data/CONTRIBUTING.md +0 -7
  7. data/Gemfile +27 -1
  8. data/README.md +190 -67
  9. data/Rakefile +9 -3
  10. data/certs/public.pem +20 -0
  11. data/lib/yammer.rb +47 -0
  12. data/lib/yammer/api.rb +29 -0
  13. data/lib/yammer/api/autocomplete.rb +39 -0
  14. data/lib/yammer/api/group.rb +92 -0
  15. data/lib/yammer/api/group_membership.rb +46 -0
  16. data/lib/yammer/api/invitation.rb +39 -0
  17. data/lib/yammer/api/like.rb +57 -0
  18. data/lib/yammer/api/message.rb +227 -0
  19. data/lib/yammer/api/network.rb +35 -0
  20. data/lib/yammer/api/notification.rb +32 -0
  21. data/lib/yammer/api/open_graph_object.rb +92 -0
  22. data/lib/yammer/api/pending_attachment.rb +64 -0
  23. data/lib/yammer/api/search.rb +42 -0
  24. data/lib/yammer/api/subscription.rb +32 -0
  25. data/lib/yammer/api/thread.rb +37 -0
  26. data/lib/yammer/api/topic.rb +37 -0
  27. data/lib/yammer/api/user.rb +168 -0
  28. data/lib/yammer/api_handler.rb +27 -0
  29. data/lib/yammer/api_response.rb +57 -0
  30. data/lib/yammer/base.rb +208 -0
  31. data/lib/yammer/client.rb +100 -0
  32. data/lib/yammer/configurable.rb +81 -0
  33. data/lib/yammer/error.rb +75 -0
  34. data/lib/yammer/group.rb +27 -0
  35. data/lib/yammer/group_membership.rb +25 -0
  36. data/lib/yammer/http_adapter.rb +100 -0
  37. data/lib/yammer/identity_map.rb +56 -0
  38. data/lib/yammer/message.rb +32 -0
  39. data/lib/yammer/message_body.rb +27 -0
  40. data/lib/yammer/pending_attachment.rb +19 -0
  41. data/lib/yammer/thread.rb +58 -0
  42. data/lib/yammer/user.rb +66 -0
  43. data/lib/yammer/version.rb +32 -0
  44. data/{lib/yam/configuration.rb → spec/api/autocomplete_spec.rb} +18 -23
  45. data/spec/api/group_membership_spec.rb +48 -0
  46. data/spec/api/group_spec.rb +76 -0
  47. data/spec/api/invitation_spec.rb +60 -0
  48. data/spec/api/like_spec.rb +46 -0
  49. data/spec/api/message_spec.rb +136 -0
  50. data/spec/api/network_spec.rb +41 -0
  51. data/{lib/yam/client.rb → spec/api/notification_spec.rb} +22 -4
  52. data/spec/api/open_graph_object_spec.rb +67 -0
  53. data/spec/api/pending_attachment_spec.rb +56 -0
  54. data/{lib/yam/constants.rb → spec/api/search_spec.rb} +21 -8
  55. data/spec/api/subscription_spec.rb +41 -0
  56. data/{lib/yam.rb → spec/api/thread_spec.rb} +19 -12
  57. data/{lib/yam/request.rb → spec/api/topic_spec.rb} +19 -15
  58. data/spec/api/user_spec.rb +108 -0
  59. data/spec/api_response.rb +86 -0
  60. data/spec/client_spec.rb +364 -0
  61. data/spec/error_spec.rb +88 -0
  62. data/spec/fixtures/group.json +1 -0
  63. data/spec/fixtures/message.json +1 -0
  64. data/spec/fixtures/messages_in_thread.json +1 -0
  65. data/spec/fixtures/portal_thread.json +1 -0
  66. data/spec/fixtures/private_thread.json +1 -0
  67. data/spec/fixtures/public_thread.json +1 -0
  68. data/spec/fixtures/user.json +1 -0
  69. data/spec/fixtures/users_followed.json +1 -0
  70. data/spec/fixtures/users_following.json +1 -0
  71. data/spec/http_adapter_spec.rb +109 -0
  72. data/spec/identity_map_spec.rb +127 -0
  73. data/spec/mocks/attachment.txt +1 -0
  74. data/spec/model/base_spec.rb +196 -0
  75. data/spec/model/group_membership_spec.rb +57 -0
  76. data/spec/model/group_spec.rb +73 -0
  77. data/spec/model/message_spec.rb +74 -0
  78. data/spec/model/thread_spec.rb +91 -0
  79. data/spec/model/user_spec.rb +222 -0
  80. data/spec/spec_helper.rb +39 -14
  81. data/yam.gemspec +50 -28
  82. metadata +270 -187
  83. metadata.gz.sig +0 -0
  84. data/lib/yam/api.rb +0 -53
  85. data/lib/yam/connection.rb +0 -57
  86. data/lib/yam/version.rb +0 -20
  87. data/spec/yam/client_spec.rb +0 -50
  88. data/spec/yam_spec.rb +0 -87
@@ -0,0 +1,27 @@
1
+ # Copyright (c) Microsoft Corporation
2
+ # All rights reserved.
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ #
7
+ # THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
8
+ # CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
9
+ # WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE,
10
+ # FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
11
+
12
+ # See the Apache Version 2.0 License for specific language governing
13
+ # permissions and limitations under the License.
14
+
15
+ module Yammer
16
+ module ApiHandler
17
+
18
+ def api_handler
19
+ establish_api_handler
20
+ end
21
+
22
+ def establish_api_handler(opts={})
23
+ Yammer::Client.new(opts)
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,57 @@
1
+ # Copyright (c) Microsoft Corporation
2
+ # All rights reserved.
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ #
7
+ # THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
8
+ # CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
9
+ # WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE,
10
+ # FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
11
+
12
+ # See the Apache Version 2.0 License for specific language governing
13
+ # permissions and limitations under the License.
14
+
15
+ module Yammer
16
+ class ApiResponse
17
+
18
+ attr_reader :code, :headers
19
+
20
+ def initialize(headers, body, code)
21
+ @headers = headers
22
+ @body = body
23
+ @code = code.to_i
24
+ end
25
+
26
+ def raw_body
27
+ @body
28
+ end
29
+
30
+ def body
31
+ @parsed_body ||= parse(@body)
32
+ end
33
+
34
+ def empty?
35
+ @body.nil? || @body.strip.empty?
36
+ end
37
+
38
+ def success?
39
+ @code == 200
40
+ end
41
+
42
+ def created?
43
+ @code == 201
44
+ end
45
+
46
+ private
47
+
48
+ def parse(body)
49
+ case body
50
+ when /\A^\s*$\z/, nil
51
+ nil
52
+ else
53
+ MultiJson.load(body, :symbolize_keys => true)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,208 @@
1
+ # Copyright (c) Microsoft Corporation
2
+ # All rights reserved.
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ #
7
+ # THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
8
+ # CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
9
+ # WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE,
10
+ # FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
11
+
12
+ # See the Apache Version 2.0 License for specific language governing
13
+ # permissions and limitations under the License.
14
+
15
+ module Yammer
16
+ class Base
17
+ class << self
18
+ include ApiHandler
19
+
20
+ # Returns the non-qualified class name
21
+ # @!scope class
22
+ def base_name
23
+ @base_name ||= begin
24
+ word = "#{name.split(/::/).last}"
25
+ word.gsub!(/::/, '/')
26
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
27
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
28
+ word.tr!("-", "_")
29
+ word.downcase!
30
+ word
31
+ end
32
+ end
33
+
34
+ # Fetches JSON reprsentation for object model with provided `id`
35
+ # and returns a model instance with attributes
36
+ # @return [Yammer::Base]
37
+ # @param id [Integer]
38
+ # @!scope class
39
+ def get(id)
40
+ attrs = fetch(id)
41
+ attrs ? new(attrs) : nil
42
+ end
43
+
44
+
45
+ # @!scope class
46
+ def fetch(id)
47
+ return unless identity_map
48
+ attributes = identity_map.get("#{base_name}_#{id}")
49
+ unless attributes
50
+ result = api_handler.send("get_#{base_name}", id)
51
+ attributes = result.empty? ? nil : result.body
52
+ unless attributes.empty?
53
+ identity_map.put("#{base_name}_#{id}", attributes)
54
+ end
55
+ end
56
+ attributes
57
+ end
58
+
59
+ # @!scope class
60
+ def identity_map
61
+ @identity_map ||= Yammer::IdentityMap.new
62
+ end
63
+
64
+ # Returns a hash of all attributes that are meant to trigger an HTTP request
65
+ # @!scope class
66
+ def model_attributes
67
+ @model_attributes ||= {}
68
+ end
69
+
70
+ protected
71
+
72
+ def attr_accessor_deffered(*symbols)
73
+ symbols.each do |key|
74
+ # track attributes that should trigger a fetch
75
+ model_attributes[key] = false
76
+
77
+ # getter
78
+ define_method(key.to_s) do
79
+ load_deferred_attribute!(key)
80
+ instance_variable_get("@#{key}")
81
+ end
82
+
83
+ # setter
84
+ define_method("#{key}=") do |value|
85
+ load_deferred_attribute!(key)
86
+ if persisted? && loaded?
87
+ @modified_attributes[key] = value
88
+ else
89
+ @attrs[key] = value
90
+ end
91
+ instance_variable_set("@#{key}", value)
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ attr_reader :id, :attrs
98
+
99
+ def initialize(props={})
100
+ @klass = self.class
101
+ @modified_attributes = {}
102
+ @new_record = true
103
+ @loaded = false
104
+ @attrs = props
105
+ self.id = @attrs.delete(:id)
106
+ self.update(@attrs)
107
+
108
+ yield self if block_given?
109
+ end
110
+
111
+ def api_handler
112
+ @klass.api_handler
113
+ end
114
+
115
+ def base_name
116
+ @klass.base_name
117
+ end
118
+
119
+ def new_record?
120
+ @new_record
121
+ end
122
+
123
+ def persisted?
124
+ !new_record?
125
+ end
126
+
127
+ def changes
128
+ @modified_attributes
129
+ end
130
+
131
+ def modified?
132
+ !changes.empty?
133
+ end
134
+
135
+ def loaded?
136
+ @loaded
137
+ end
138
+
139
+ def load!
140
+ @attrs = @klass.fetch(@id)
141
+ @loaded = true
142
+ update(@attrs)
143
+ self
144
+ end
145
+
146
+ def reload!
147
+ reset!
148
+ load!
149
+ end
150
+
151
+ def save
152
+ return self if ((persisted? && @modified_attributes.empty?) || @attrs.empty?)
153
+
154
+ result = if new_record?
155
+ api_handler.send("create_#{base_name}", @attrs)
156
+ else
157
+ api_handler.send("update_#{base_name}", @id, @modified_attributes)
158
+ end
159
+ @modified_attributes = {}
160
+ self
161
+ end
162
+
163
+ def delete!
164
+ return if new_record?
165
+ result = api_handler.send("delete_#{base_name}", @id)
166
+ result.success?
167
+ end
168
+
169
+ private
170
+
171
+ def id=(model_id)
172
+ return if model_id.nil?
173
+ @id = model_id.to_i
174
+ @new_record = false
175
+ end
176
+
177
+ # clear the entire class
178
+ def reset!
179
+ @modified_attributes = {}
180
+ @attrs = {}
181
+ @new_record = true
182
+ @loaded = false
183
+ end
184
+
185
+ protected
186
+ # loads model
187
+ def load_deferred_attribute!(key)
188
+ if @attrs.empty? && persisted? && !loaded?
189
+ load!
190
+ if !@attrs.has_key?(key)
191
+ raise "The key: #{key} appears not to be supported for model: #{self.base_name} \n #{@attrs.keys.inspect}"
192
+ end
193
+ end
194
+ end
195
+
196
+ # set all fetchable attributes
197
+ def update(attrs={})
198
+ attrs.each do |key, value|
199
+ send("#{key}=", value)
200
+ end
201
+ if persisted? && !loaded?
202
+ @loaded = @klass.model_attributes.keys.inject(true) do |result, key|
203
+ result && @attrs.has_key?(key)
204
+ end
205
+ end
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,100 @@
1
+ # Copyright (c) Microsoft Corporation
2
+ # All rights reserved.
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ #
7
+ # THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
8
+ # CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
9
+ # WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE,
10
+ # FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
11
+
12
+ # See the Apache Version 2.0 License for specific language governing
13
+ # permissions and limitations under the License.
14
+
15
+ require 'yammer/api'
16
+ require 'yammer/configurable'
17
+ require 'yammer/http_adapter'
18
+
19
+ module Yammer
20
+ class Client
21
+
22
+ include Yammer::Configurable
23
+ include Yammer::Api::User
24
+ include Yammer::Api::Group
25
+ include Yammer::Api::GroupMembership
26
+ include Yammer::Api::Message
27
+ include Yammer::Api::Thread
28
+ include Yammer::Api::Topic
29
+ include Yammer::Api::Network
30
+ include Yammer::Api::Search
31
+ include Yammer::Api::Like
32
+ include Yammer::Api::Notification
33
+ include Yammer::Api::Autocomplete
34
+ include Yammer::Api::Invitation
35
+ include Yammer::Api::PendingAttachment
36
+ include Yammer::Api::Subscription
37
+ include Yammer::Api::OpenGraphObject
38
+
39
+ attr_reader :site_url, :default_headers, :connection_options
40
+
41
+ attr_accessor :client_id, :client_secret, :access_token
42
+
43
+ def initialize(opts={})
44
+ Yammer::Configurable.keys.each do |key|
45
+ case key
46
+ when :headers, :connection_options
47
+ value = Yammer.instance_variable_get(:"@#{key}").merge(opts.fetch(key, {}))
48
+ else
49
+ value = opts.fetch(key, Yammer.instance_variable_get(:"@#{key}"))
50
+ end
51
+ instance_variable_set(:"@#{key}", value)
52
+ end
53
+ end
54
+
55
+ # makes a GET request
56
+ def get(path, params={})
57
+ request(:get, path, params)
58
+ end
59
+
60
+ # makes a PUT request
61
+ def put(path, params={})
62
+ request(:put, path, params)
63
+ end
64
+
65
+ # makes a POST request
66
+ def post(path, params={})
67
+ request(:post, path, params)
68
+ end
69
+
70
+ # makes a DELETE request
71
+ def delete(path, params={})
72
+ request(:delete, path, params)
73
+ end
74
+
75
+ private
76
+
77
+ # returns an instance of the http adapter
78
+ # if none is specified, the default is Yammer::HttpConnection
79
+ # @!visibility private
80
+ def http_client
81
+ @http_client ||= @http_adapter.new(@site_url, @connection_options)
82
+ end
83
+
84
+ # Makes an HTTP request using the provided parameters
85
+ # @raise [Yammer::Error::Unauthorized]
86
+ # @param method [string]
87
+ # @param path [string]
88
+ # @param params [Hash]
89
+ # @return [Yammer::ApiResponse]
90
+ # @!visibility private
91
+ def request(method, path, params={})
92
+ headers = @default_headers.merge({'Authorization' => "Bearer #{@access_token}"})
93
+ result = http_client.send_request(method, path, {
94
+ :params => params,
95
+ :headers => headers
96
+ })
97
+ result
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,81 @@
1
+ # Copyright (c) Microsoft Corporation
2
+ # All rights reserved.
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ #
7
+ # THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
8
+ # CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
9
+ # WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE,
10
+ # FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
11
+
12
+ # See the Apache Version 2.0 License for specific language governing
13
+ # permissions and limitations under the License.
14
+
15
+ require 'yammer/http_adapter'
16
+
17
+ module Yammer
18
+ module Configurable
19
+
20
+ ENDPOINT = 'https://www.yammer.com' unless defined? ENDPOINT
21
+ HTTP_ADAPTER = Yammer::HttpAdapter unless defined? HTTP_CONNECTION
22
+
23
+ attr_accessor :client_id, :client_secret, :access_token, :site_url,
24
+ :connection_options, :default_headers, :http_adapter
25
+
26
+ # Return a hash with the default options
27
+ # @return [Hash]
28
+ def self.default_options
29
+ {
30
+ :site_url => ENDPOINT,
31
+ :client_id => ENV['YAMMER_CLIENT_ID'],
32
+ :client_secret => ENV['YAMMER_CLIENT_SECRET'],
33
+ :access_token => ENV['YAMMER_ACCESS_TOKEN'],
34
+ :http_adapter => HTTP_ADAPTER,
35
+ :connection_options => { :max_redirects => 5, :verify_ssl => true },
36
+ :default_headers => {
37
+ 'Accept' => 'application/json',
38
+ 'User-Agent' => "Yammer Ruby Gem #{Yammer::Version}"
39
+ }
40
+ }
41
+ end
42
+
43
+ # @return [Array<String>]
44
+ def self.keys
45
+ self.default_options.keys
46
+ end
47
+
48
+ # @return [Hash]
49
+ def options
50
+ Hash[Yammer::Configurable.keys.map{|key| [key, instance_variable_get(:"@#{key}")]}]
51
+ end
52
+
53
+ def reset!
54
+ Yammer::Configurable.keys.each do |key|
55
+ instance_variable_set(:"@#{key}", Yammer::Configurable.default_options[key.to_sym])
56
+ end
57
+ self
58
+ end
59
+
60
+ # Convenience method to allow configuration options to be set in a block
61
+ def configure
62
+ yield self if block_given?
63
+ self
64
+ end
65
+
66
+ def enable_logging(output='stdout')
67
+ self.http_adapter.log = output
68
+ end
69
+
70
+ def disable_logging
71
+ self.http_adapter.log = nil
72
+ end
73
+
74
+ def with_logging(output)
75
+ cached_output = self.http_adapter.log
76
+ enable_logging(output)
77
+ yield self if block_given?
78
+ self.http_adapter.log = cached_output
79
+ end
80
+ end
81
+ end