databasedotcom-ejholmes 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,161 @@
1
+ =databasedotcom
2
+ databasedotcom is a gem to enable ruby applications to access the SalesForce REST API. If you use bundler, simply list it in your Gemfile, like so:
3
+
4
+ gem 'databasedotcom'
5
+
6
+ If you don't use bundler, install it by hand:
7
+
8
+ gem install databasedotcom
9
+
10
+ =Documentation
11
+
12
+ Reference documentation is available at rubydoc.info[http://rubydoc.info/github/heroku/databasedotcom/master/frames]
13
+
14
+ =Source
15
+
16
+ Source is available at github[http://github.com/heroku/databasedotcom]
17
+
18
+ = Contributions
19
+
20
+ To contribute, fork this repo, make changes in your fork, then send a pull request. No pull requests without accompanying tests will be accepted. To run tests in your fork, just do
21
+
22
+ bundle install
23
+ rake
24
+
25
+ = Usage
26
+ == Initialization
27
+ When you create a Databasedotcom::Client object, you need to configure it with a client id and client secret that corresponds to one of the Remote Access Applications configured within your Salesforce instance. The Salesforce UI refers to the client id as "Consumer Key", and to the client secret as "Consumer Secret".
28
+
29
+ You can configure your Client object with a client id and client secret in one of several different ways:
30
+ === Configuration from the environment
31
+ If configuration information is present in the environment, the new Client will take configuration information from there.
32
+
33
+ export DATABASEDOTCOM_CLIENT_ID=foo
34
+ export DATABASEDOTCOM_CLIENT_SECRET=bar
35
+
36
+ Then
37
+
38
+ client = Databasedotcom::Client.new
39
+ client.client_id #=> foo
40
+ client.client_secret #=> bar
41
+
42
+ === Configuration from a YAML file
43
+ If you pass the name of a YAML file when you create a Client, the new Client will read the YAML file and take the client id and client secret values from there.
44
+
45
+ # databasedotcom.yml
46
+ #
47
+ ---
48
+ client_secret: bro
49
+ client_id: baz
50
+
51
+ Then
52
+
53
+ client = Databasedotcom::Client.new("databasedotcom.yml")
54
+ client.client_id #=> bro
55
+ client.client_secret #=> baz
56
+
57
+ === Configuration from a Hash
58
+ If you pass a hash when you create a Client, the new Client will take configuration information from that Hash.
59
+
60
+ client = Databasedotcom::Client.new :client_id => "sponge", :client_secret => "bob"
61
+ client.client_id #=> sponge
62
+ client.client_secret #=> bob
63
+
64
+ === Configuration precedence
65
+ Configuration information present in the environment always takes precedence over that passed in via a YAML file or a Hash.
66
+
67
+ export DATABASEDOTCOM_CLIENT_ID=foo
68
+ export DATABASEDOTCOM_CLIENT_SECRET=bar
69
+
70
+ Then
71
+
72
+ client = Databasedotcom::Client.new :client_id => "sponge", :client_secret => "bob"
73
+ client.client_id #=> foo
74
+ client.client_secret #=> bar
75
+
76
+ === Usage in an application deployed on Heroku
77
+ You can use the <tt>heroku config:add</tt> command to set environment variables:
78
+
79
+ heroku config:add DATABASEDOTCOM_CLIENT_ID=foo
80
+ heroku config:add DATABASEDOTCOM_CLIENT_SECRET=bar
81
+
82
+ Then, when you create your client like:
83
+
84
+ client = Databasedotcom::Client.new
85
+
86
+ it will use the configuration information that you set with <tt>heroku config:add</tt>.
87
+
88
+ == Authentication
89
+ The first thing you need to do with the new Client is to authenticate with Salesforce. You can do this in one of several ways:
90
+
91
+ === Authentication via an externally-acquired OAuth access token
92
+ If you have acquired an OAuth access token for your Salesforce instance through some external means, you can use it. Note that you have to pass both the token and your Salesforce instance URL to the <tt>authenticate</tt> method:
93
+
94
+ client.authenticate :token => "my-oauth-token", :instance_url => "http://na1.salesforce.com" #=> "my-oauth-token"
95
+
96
+ === Authentication via Omniauth
97
+ If you are using the gem within the context of a web application, and your web app is using Omniauth to do OAuth with Salesforce, you can authentication the Client direction via the Hash that Omniauth passes to your OAuth callback method, like so:
98
+
99
+ client.authenticate request.env['omniauth.auth'] #=> "the-oauth-token"
100
+
101
+ === Authentication via username and password
102
+ You can authenticate your Client directly with Salesforce with a valid username and password for a user in your Salesforce instance. Note that, if access to your Salesforce instance requires a {security token}[http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_concepts_security.htm], the value that you pass for <tt>:password</tt> must be the password for the user concatenated with her security token.
103
+
104
+ client.authenticate :username => "foo@bar.com", :password => "ThePasswordTheSecurityToken" #=> "the-oauth-token"
105
+
106
+ == Accessing the Sobject API
107
+ You can retrieve a list of Sobject defined in your Salesforce instance like so:
108
+
109
+ client.list_sobjects #=> ['User', 'Group', 'Contact']
110
+
111
+ Once you have the name of an Sobject, the easiest way to interact with it is to first materialize it:
112
+
113
+ contact_class = client.materialize("Contact") #=> Contact
114
+
115
+ By default, Sobject classes are materialized into the global namespace- if you want materialize into another module, you can easily do configure this:
116
+
117
+ client.sobject_module = My::Module
118
+ client.materialize("Contact") #=> My::Module::Contact
119
+
120
+ Materialized Sobject classes behave much like ActiveRecord classes:
121
+
122
+ contact = Contact.find("contact_id") #=> #<Contact @Id="contact_id", ...>
123
+ contact = Contact.find_by_Name("John Smith") #=> dynamic finders!
124
+ contacts = Contact.all #=> a Databasedotcom::Collection of Contact instances
125
+ contacts = Contact.find_all_by_Company("IBM") #=> a Databasedotcom::Collection of matching Contacts
126
+ contact.Name #=> the contact's Name attribute
127
+ contact["Name"] #=> same thing
128
+ contact.Name = "new name" #=> change the contact's Name attribute, in memory
129
+ contact["Name"] = "new name" #=> same thing
130
+ contact.save #=> save the changes to the database
131
+ contact.update_attributes "Name" => "newer name",
132
+ "Phone" => "4156543210" #=> change several attributes at once and save them
133
+ contact.delete #=> delete the contact from the database
134
+
135
+ See the documentation[http://rubydoc.info/github/heroku/databasedotcom/master/frames] for full details.
136
+
137
+ == Accessing the Chatter API
138
+ You can easily access Chatter feeds, group, conversations, etc.:
139
+
140
+ my_feed_items = Databasedotcom::Chatter::UserProfileFeed.find(client) #=> a Databasedotcom::Collection of FeedItems
141
+
142
+ my_feed_items.each do |feed_item|
143
+ feed_item.likes #=> a Databasedotcom::Collection of Like instances
144
+ feed_item.comments #=> a Databasedotcom::Collection of Comment instances
145
+ feed_item.raw_hash #=> the hash returned from the Chatter API describing this FeedItem
146
+ feed_item.comment("This is cool") #=> create a new comment on the FeedItem
147
+ feed_item.like #=> the authenticating user likes the FeedItem
148
+ end
149
+
150
+ me = Databasedotcom::Chatter::User.find(client, "me") #=> a User for the authenticating user
151
+ me.followers #=> a Databasedotcom::Collection of Users
152
+ me.post_status("what I'm doing now") #=> post a new status
153
+
154
+ you = Databasedotcom::Chatter::User.find(client, "your-user-id")
155
+ me.follow(you) #=> start following a user
156
+
157
+ See the documentation[http://rubydoc.info/github/heroku/databasedotcom/master/frames] for full details.
158
+
159
+ = License
160
+
161
+ This gem is licensed under the MIT License.
@@ -0,0 +1,10 @@
1
+ require 'databasedotcom/chatter/record'
2
+
3
+ module Databasedotcom
4
+ module Chatter
5
+
6
+ # A comment posted on a FeedItem.
7
+ class Comment < Record
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,100 @@
1
+ require 'databasedotcom/chatter/record'
2
+
3
+ module Databasedotcom
4
+ module Chatter
5
+ # A thread of private messages. When calling +Conversation.find+ or +Conversation.all+, you must pass +:user_id => <my_user_id>+ in the _parameters_
6
+ #
7
+ # Conversation.all(@client, :user_id => "me")
8
+ # Conversation.find(@client, "conversationId", :user_id => "f80ad89f9d98d89dfd89")
9
+ class Conversation < Record
10
+
11
+ # Creates a new Conversation and sets its +id+ and +url+ to values obtained from the server response.
12
+ def initialize(client, response)
13
+ super
14
+ @id ||= @raw_hash["conversationId"]
15
+ @url ||= @raw_hash["conversationUrl"]
16
+ end
17
+
18
+ # Find the Conversation identified by _cid_ and archive it. Returns the updated Conversation.
19
+ #
20
+ # Conversation.archive(@client, "fakeid")
21
+ def self.archive(client, cid)
22
+ url = "/services/data/v#{client.version}/chatter/users/me/conversations/#{cid}"
23
+ response = client.http_patch(url, nil, :archived => "true")
24
+ Conversation.new(client, response.body)
25
+ end
26
+
27
+ # Find the Conversation identified by _cid_ and unarchive it. Returns the updated Conversation.
28
+ #
29
+ # Conversation.unarchive(@client, "fakeid")
30
+ def self.unarchive(client, cid)
31
+ url = "/services/data/v#{client.version}/chatter/users/me/conversations/#{cid}"
32
+ response = client.http_patch(url, nil, :archived => "false")
33
+ Conversation.new(client, response.body)
34
+ end
35
+
36
+ # Find the Conversation identified by _cid_ and mark it as read. Returns the updated Conversation.
37
+ #
38
+ # Conversation.mark_read(@client, "fakeid")
39
+ def self.mark_read(client, cid)
40
+ url = "/services/data/v#{client.version}/chatter/users/me/conversations/#{cid}"
41
+ response = client.http_patch(url, nil, :read => "true")
42
+ Conversation.new(client, response.body)
43
+ end
44
+
45
+ # Find the Conversation identified by _cid_ and mark it as unread. Returns the updated Conversation.
46
+ #
47
+ # Conversation.mark_unread(@client, "fakeid")
48
+ def self.mark_unread(client, cid)
49
+ url = "/services/data/v#{client.version}/chatter/users/me/conversations/#{cid}"
50
+ response = client.http_patch(url, nil, :read => "false")
51
+ Conversation.new(client, response.body)
52
+ end
53
+
54
+ # Gets all messages for the Conversation specified by _cid_ and the User specified by _uid_. Returns a Collection of Message objects.
55
+ def self.messages(client, uid, cid)
56
+ conversation = self.find(client, cid, :user_id => uid)
57
+ collection = Databasedotcom::Collection.new(client, nil, conversation.raw_hash["messages"]["nextPageUrl"], conversation.raw_hash["messages"]["previousPageUrl"], conversation.raw_hash["messages"]["currentPageUrl"])
58
+ conversation.raw_hash["messages"]["messages"].each do |item|
59
+ collection << Message.new(client, item)
60
+ end
61
+ collection
62
+ end
63
+
64
+ # Archive this Conversation.
65
+ def archive
66
+ self.class.archive(self.client, self.id)
67
+ end
68
+
69
+ # Unarchive this Conversation.
70
+ def unarchive
71
+ self.class.unarchive(self.client, self.id)
72
+ end
73
+
74
+ # Mark this Conversation as read.
75
+ def mark_read
76
+ self.class.mark_read(self.client, self.id)
77
+ end
78
+
79
+ # Mark this Conversation as unread.
80
+ def mark_unread
81
+ self.class.mark_unread(self.client, self.id)
82
+ end
83
+
84
+ # Return a Collection of messages from this Conversation.
85
+ def messages
86
+ collection = Databasedotcom::Collection.new(client, nil, self.raw_hash["messages"]["nextPageUrl"], self.raw_hash["messages"]["previousPageUrl"], self.raw_hash["messages"]["currentPageUrl"])
87
+ self.raw_hash["messages"]["messages"].each do |item|
88
+ collection << Message.new(client, item)
89
+ end
90
+ collection
91
+ end
92
+
93
+ protected
94
+
95
+ def self.search_parameter_name
96
+ :Q
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,64 @@
1
+ require 'json'
2
+
3
+ module Databasedotcom
4
+ module Chatter
5
+ # Parent class of all feeds and inherits from Collection. This class is not intended to be instantiated. Methods should be called on subclasses, which are all are dynamically defined (except for FilterFeed). Defined feeds are *NewsFeed*, *UserProfileFeed*, *RecordFeed*, *ToFeed*, *PeopleFeed*, *GroupsFeed*, *FilesFeed*, *CompanyFeed*, and *FilterFeed*.
6
+ class Feed < Collection
7
+
8
+ # Returns an enumerable Feed of FeedItem objects that make up the feed with the specified _id_. Should not be called as a class method on Feed, but as a method on subclasses.
9
+ #
10
+ # NewsFeed.find(@client) #=> [#<FeedItem ...>, #<FeedItem ...>, ...]
11
+ # PeopleFeed.find(@client, "userid") #=> [#<FeedItem ...>, #<FeedItem ...>, ...]
12
+ # FilterFeed.find(@client, "me", "000") #=> [#<FeedItem ...>, #<FeedItem ...>, ...]
13
+ #
14
+ # _id_prefix_ is only applicable for FilterFeed.
15
+ def self.find(client, id="me", id_prefix=nil)
16
+ path_components = %w(services data)
17
+ path_components << "v#{client.version}"
18
+ path_components.concat(%w(chatter feeds))
19
+ path_components << feed_type
20
+ path_components << id unless feed_type == "company"
21
+ path_components << id_prefix
22
+ path_components << "feed-items"
23
+ path = "/" + path_components.compact.join('/')
24
+ result = client.http_get(path)
25
+ response = JSON.parse(result.body)
26
+ collection = self.new(client, nil, response["nextPageUrl"], response["previousPageUrl"], response["currentPageUrl"])
27
+ response["items"].each do |item|
28
+ collection << FeedItem.new(client, item)
29
+ end
30
+ collection
31
+ end
32
+
33
+ # Posts a FeedItem to a Feed specified by _user_id_. Should not be called as a class method on Feed, but as a method on subclasses.
34
+ #
35
+ # UserProfileFeed.post(@client, "me", :text => "This is a status update about Salesforce.", :url => "http://www.salesforce.com")
36
+ #
37
+ # Returns the newly created FeedItem.
38
+ def self.post(client, user_id, parameters)
39
+ url = "/services/data/v#{client.version}/chatter/feeds/#{feed_type}/#{user_id}/feed-items"
40
+ response = client.http_post(url, nil, parameters)
41
+ Databasedotcom::Chatter::FeedItem.new(client, response.body)
42
+ end
43
+
44
+ # Posts a file to a Feed specified by _user_id_. Should not be called as a class method on Feed, but as a method on subclasses.
45
+ #
46
+ # UserProfileFeed.post_file(@client, "me", File.open("MyFile"), "text/plain", "MyFile", :desc => "This is an uploaded text file.")
47
+ #
48
+ # Returns the newly created FeedItem.
49
+ def self.post_file(client, user_id, io, file_type, file_name, parameters={})
50
+ url = "/services/data/v#{client.version}/chatter/feeds/#{feed_type}/#{user_id}/feed-items"
51
+ response = client.http_multipart_post(url, {"feedItemFileUpload" => UploadIO.new(io, file_type, file_name), "fileName" => file_name}, parameters)
52
+ Databasedotcom::Chatter::FeedItem.new(client, response.body)
53
+ end
54
+
55
+ private
56
+
57
+ def self.feed_type
58
+ self.name.match(/.+::(.+)Feed$/)[1].resourcerize
59
+ end
60
+ end
61
+
62
+ FEED_TYPES = %w(News UserProfile Record To People Groups Files Company)
63
+ end
64
+ end
@@ -0,0 +1,40 @@
1
+ require 'databasedotcom/chatter/record'
2
+
3
+ module Databasedotcom
4
+ module Chatter
5
+
6
+ # An item in a Feed.
7
+ class FeedItem < Record
8
+
9
+ # Returns a Collection of comments that were posted on this FeedItem instance.
10
+ def comments
11
+ collection = Databasedotcom::Collection.new(self.client, self.raw_hash["comments"]["total"], self.raw_hash["comments"]["nextPageUrl"], nil, self.raw_hash["comments"]["currentPageUrl"])
12
+ collection.concat(self.raw_hash["comments"]["comments"])
13
+ end
14
+
15
+ # Returns a Collection of likes for this FeedItem instance.
16
+ def likes
17
+ collection = Databasedotcom::Collection.new(self.client, self.raw_hash["likes"]["total"], self.raw_hash["likes"]["nextPageUrl"], self.raw_hash["likes"]["previousPageUrl"], self.raw_hash["likes"]["currentPageUrl"])
18
+ collection.concat(self.raw_hash["likes"]["likes"])
19
+ end
20
+
21
+ # Like this FeedItem.
22
+ def like
23
+ result = self.client.http_post("/services/data/v#{self.client.version}/chatter/feed-items/#{self.id}/likes")
24
+ Like.new(self.client, result.body)
25
+ end
26
+
27
+ # Post a Comment on this FeedItem with content _text_.
28
+ def comment(text)
29
+ result = self.client.http_post("/services/data/v#{self.client.version}/chatter/feed-items/#{self.id}/comments", nil, :text => text)
30
+ Comment.new(self.client, result.body)
31
+ end
32
+
33
+ protected
34
+
35
+ def self.collection_from_response(response)
36
+ response["items"]
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,5 @@
1
+ require 'databasedotcom/chatter/feed'
2
+
3
+ Databasedotcom::Chatter::FEED_TYPES.each do |feed_type|
4
+ Databasedotcom::Chatter.const_set("#{feed_type}Feed", Class.new(Databasedotcom::Chatter::Feed))
5
+ end
@@ -0,0 +1,14 @@
1
+ module Databasedotcom
2
+ module Chatter
3
+ # Filter feeds contain items pertaining to both a user and another specified resource.
4
+ class FilterFeed < Feed
5
+
6
+ # Lists all FilterFeeds for the user with id _user_id_.
7
+ def self.feeds(client, user_id="me")
8
+ url = "/services/data/v#{client.version}/chatter/feeds/filter/#{user_id}"
9
+ result = client.http_get(url)
10
+ JSON.parse(result.body)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,45 @@
1
+ require 'databasedotcom/chatter/record'
2
+ require 'databasedotcom/chatter/photo_methods'
3
+
4
+ module Databasedotcom
5
+ module Chatter
6
+ # A group of Users
7
+ class Group < Record
8
+ include PhotoMethods
9
+
10
+ # Returns a Collection of GroupMembership instances for the Group identified by _group_id_.
11
+ def self.members(client, group_id)
12
+ url = "/services/data/v#{client.version}/chatter/groups/#{group_id}/members"
13
+ result = client.http_get(url)
14
+ response = JSON.parse(result.body)
15
+ collection = Databasedotcom::Collection.new(client, response["totalMemberCount"], response["nextPageUrl"], response["previousPageUrl"], response["currentPageUrl"])
16
+ response["members"].each do |member|
17
+ collection << GroupMembership.new(client, member)
18
+ end
19
+ collection
20
+ end
21
+
22
+ # Join the group identified by _group_id_ as the user identified by _user_id_.
23
+ def self.join(client, group_id, user_id="me")
24
+ url = "/services/data/v#{client.version}/chatter/groups/#{group_id}/members"
25
+ response = client.http_post(url, nil, :userId => user_id)
26
+ GroupMembership.new(client, response.body)
27
+ end
28
+
29
+ # Get a Collection of GroupMembership objects for this Group. Always makes a call to the server.
30
+ def members!
31
+ self.class.members(self.client, self.id)
32
+ end
33
+
34
+ # Get a Collection of GroupMembership objects for this Group. Returns cached data if it has been called before.
35
+ def members
36
+ @members ||= members!
37
+ end
38
+
39
+ # Join this Group as the user identified by _user_id_.
40
+ def join(user_id="me")
41
+ self.class.join(self.client, self.id, user_id)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,9 @@
1
+ require 'databasedotcom/chatter/record'
2
+
3
+ module Databasedotcom
4
+ module Chatter
5
+ # A GroupMembership represents the membership of a certain User in a certain Group.
6
+ class GroupMembership < Record
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'databasedotcom/chatter/record'
2
+
3
+ module Databasedotcom
4
+ module Chatter
5
+ # A like on a FeedItem
6
+ class Like < Record
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,29 @@
1
+ require 'databasedotcom/chatter/record'
2
+
3
+ module Databasedotcom
4
+ module Chatter
5
+ # A private message between two or more Users
6
+ class Message < Record
7
+
8
+ # Send a private message with the content _text_ to each user in the _recipients_ list.
9
+ def self.send_message(client, recipients, text)
10
+ url = "/services/data/v#{client.version}/chatter/users/me/messages"
11
+ recipients = recipients.is_a?(Array) ? recipients : [recipients]
12
+ response = client.http_post(url, nil, :text => text, :recipients => recipients.join(','))
13
+ Message.new(client, response.body)
14
+ end
15
+
16
+ # Send a reply to the message identified by _in_reply_to_message_id_ with content _text_.
17
+ def self.reply(client, in_reply_to_message_id, text)
18
+ url = "/services/data/v#{client.version}/chatter/users/me/messages"
19
+ response = client.http_post(url, nil, :text => text, :inReplyTo => in_reply_to_message_id)
20
+ Message.new(client, response.body)
21
+ end
22
+
23
+ # Send a reply to this Message with content _text_.
24
+ def reply(text)
25
+ self.class.reply(self.client, self.id, text)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,55 @@
1
+ module Databasedotcom
2
+ module Chatter
3
+ # Defines methods for entities that can have photos i.e. Users, Groups.
4
+ module PhotoMethods
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ end
8
+
9
+ # Defines class methods for resources that can have photos.
10
+ module ClassMethods
11
+ # Returns a Hash with urls for the small and large versions of the photo for a resource.
12
+ def photo(client, resource_id)
13
+ url = "/services/data/v#{client.version}/chatter/#{self.resource_name}/#{resource_id}/photo"
14
+ result = client.http_get(url)
15
+ JSON.parse(result.body)
16
+ end
17
+
18
+ # Uploads a photo for a resource with id _resource_id_.
19
+ #
20
+ # User.upload_photo(@client, "me", File.open("SomePicture.png"), "image/png")
21
+ def upload_photo(client, resource_id, io, file_type)
22
+ url = "/services/data/v#{client.version}/chatter/#{self.resource_name}/#{resource_id}/photo"
23
+ result = client.http_multipart_post(url, {"fileUpload" => UploadIO.new(io, file_type)})
24
+ JSON.parse(result.body)
25
+ end
26
+
27
+ # Deletes the photo for the resource with id _resource_id_.
28
+ def delete_photo(client, resource_id)
29
+ client.http_delete "/services/data/v#{client.version}/chatter/#{self.resource_name}/#{resource_id}/photo"
30
+ end
31
+ end
32
+
33
+ # Returns a Hash with urls for the small and large versions of the photo for this resource.
34
+ #
35
+ # User.find(@client, "me").photo #=> {"smallPhotoUrl"=>"/small/photo/url", "largePhotoUrl"=>"/large/photo/url"}
36
+ def photo
37
+ self.raw_hash["photo"]
38
+ end
39
+
40
+ # Uploads a photo for this resource.
41
+ #
42
+ # me = User.find(@client)
43
+ # me.upload_photo(File.open("SomePicture.png"), "image/png")
44
+ def upload_photo(io, file_type)
45
+ self.class.upload_photo(self.client, self.id, io, file_type)
46
+ end
47
+
48
+ # Deletes the photo for this resource.
49
+ def delete_photo
50
+ self.class.delete_photo(self.client, self.id)
51
+ photo
52
+ end
53
+ end
54
+ end
55
+ end