ticketmaster-teambox 0.1.0

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.
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "ticketmaster", "0.5.6"
4
+ gem "oauth2"
5
+
6
+ group :development do
7
+ gem "bundler", "~> 1.0.0"
8
+ gem "jeweler", "~> 1.5.1"
9
+ gem "rcov", ">= 0"
10
+ gem "rspec", "= 1.2.9"
11
+ end
12
+
@@ -0,0 +1,52 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activemodel (3.0.7)
5
+ activesupport (= 3.0.7)
6
+ builder (~> 2.1.2)
7
+ i18n (~> 0.5.0)
8
+ activeresource (3.0.7)
9
+ activemodel (= 3.0.7)
10
+ activesupport (= 3.0.7)
11
+ activesupport (3.0.7)
12
+ addressable (2.2.6)
13
+ builder (2.1.2)
14
+ faraday (0.6.1)
15
+ addressable (~> 2.2.4)
16
+ multipart-post (~> 1.1.0)
17
+ rack (< 2, >= 1.1.0)
18
+ git (1.2.5)
19
+ hashie (1.0.0)
20
+ i18n (0.5.0)
21
+ jeweler (1.5.1)
22
+ bundler (~> 1.0.0)
23
+ git (>= 1.2.5)
24
+ rake
25
+ multi_json (1.0.3)
26
+ multipart-post (1.1.1)
27
+ oauth2 (0.4.1)
28
+ faraday (~> 0.6.1)
29
+ multi_json (>= 0.0.5)
30
+ rack (1.3.0)
31
+ rake (0.8.7)
32
+ rcov (0.9.9)
33
+ rspec (1.2.9)
34
+ ticketmaster (0.5.6)
35
+ activeresource
36
+ activeresource (>= 2.3.2)
37
+ activesupport
38
+ activesupport (>= 2.3.2)
39
+ hashie (= 1.0.0)
40
+ hashie
41
+ jeweler
42
+
43
+ PLATFORMS
44
+ ruby
45
+
46
+ DEPENDENCIES
47
+ bundler (~> 1.0.0)
48
+ jeweler (~> 1.5.1)
49
+ oauth2
50
+ rcov
51
+ rspec (= 1.2.9)
52
+ ticketmaster (= 0.5.6)
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Hybridgroup
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.
@@ -0,0 +1,70 @@
1
+ # ticketmaster-teambox
2
+
3
+ This is a provider for [ticketmaster](http://ticketrb.com). It provides interoperability with [Teambox](http://www.teambox.com).
4
+
5
+ # Usage and Examples
6
+
7
+ First we have to instantiate a new ticketmaster instance:
8
+ teambox = TicketMaster.new(:teambox, {:username => "foo", :password => "bar", :client_id => "your_client_id", :client_secret => "your_client_secret"})
9
+
10
+ If you do not pass in username, password, client id and client secret you won't get any information.
11
+
12
+ == Finding Projects
13
+
14
+ You can find your own projects by doing:
15
+
16
+ projects = teambox.projects # Will return all your projects
17
+ projects = teambox.projects([12345, 67890]) # You must use your projects identifier
18
+ project = teambox.project(12345) # Also use project identifier in here
19
+
20
+ == Finding Tickets
21
+
22
+ tickets = project.tickets # All open issues
23
+ ticket = project.ticket(<ticket_number>)
24
+
25
+ == Open Tickets
26
+
27
+ ticket = project.ticket!({:name => "New ticket", :task_list_id => 23232})
28
+
29
+ = Update a ticket
30
+
31
+ ticket.name = "New ticket name"
32
+ ticket.save
33
+
34
+ == Finding Comments
35
+
36
+ comments = ticket.comments #All comments
37
+
38
+ == Create Comments
39
+
40
+ comment = ticket.comment!(:body => "this is a new comment")
41
+
42
+ ## Requirements
43
+
44
+ * rubygems (obviously)
45
+ * ticketmaster gem (latest version preferred)
46
+ * jeweler gem and bundler gem (only if you want to repackage and develop)
47
+ * OAuth2 gem
48
+
49
+ The ticketmaster gem and OAuth2 gem should automatically be installed during the installation of these gems if it is not already installed.
50
+
51
+ ## Other Notes
52
+
53
+ Since this and the ticketmaster gem is still primarily a work-in-progress, minor changes may be incompatible with previous versions. Please be careful about using and updating this gem in production.
54
+
55
+ If you see or find any issues, feel free to open up an issue report.
56
+
57
+
58
+ ## Note on Patches/Pull Requests
59
+
60
+ * Fork the project.
61
+ * Make your feature addition or bug fix.
62
+ * Add tests for it. This is important so I don't break it in a
63
+ future version unintentionally.
64
+ * Commit, do not mess with rakefile, version, or history.
65
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
66
+ * Send me a pull request. Bonus points for topic branches.
67
+
68
+ ## Copyright
69
+
70
+ Copyright (c) 2011 [Hybrid Group](http://hybridgroup.com). See LICENSE for details.
@@ -0,0 +1,48 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "ticketmaster-teambox"
16
+ gem.homepage = "http://ticketrb.com"
17
+ gem.summary = %Q{Ticketmaster Provider for Teambox}
18
+ gem.description = %Q{Allows ticketmaster to interact with Teambox}
19
+ gem.email = "ana@hybridgroup.com"
20
+ gem.authors = ["Hybridgroup"]
21
+ gem.add_dependency "activesupport", ">= 3.0.4"
22
+ gem.add_dependency "activeresource", ">= 3.0.4"
23
+ end
24
+ Jeweler::RubygemsDotOrgTasks.new
25
+
26
+ require 'spec/rake/spectask'
27
+ Spec::Rake::SpecTask.new(:spec) do |spec|
28
+ spec.libs << 'lib' << 'spec'
29
+ spec.spec_files = FileList['spec/**/*_spec.rb']
30
+ end
31
+
32
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
33
+ spec.libs << 'lib' << 'spec'
34
+ spec.pattern = 'spec/**/*_spec.rb'
35
+ spec.rcov = true
36
+ end
37
+
38
+ task :default => :spec
39
+
40
+ require 'rake/rdoctask'
41
+ Rake::RDocTask.new do |rdoc|
42
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
43
+
44
+ rdoc.rdoc_dir = 'rdoc'
45
+ rdoc.title = "ticketmaster-teambox #{version}"
46
+ rdoc.rdoc_files.include('README*')
47
+ rdoc.rdoc_files.include('lib/**/*.rb')
48
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,63 @@
1
+ module TicketMaster::Provider
2
+ module Teambox
3
+ # The comment class for ticketmaster-teambox
4
+ #
5
+ # Do any mapping between Ticketmaster and your system's comment model here
6
+ # versions of the ticket.
7
+ #
8
+ class Comment < TicketMaster::Provider::Base::Comment
9
+ API = TeamboxAPI::Comment # The class to access the api's comments
10
+ # declare needed overloaded methods here
11
+ #
12
+ def initialize(*object)
13
+ if object.first
14
+ object = object.first
15
+ @system_data = {:client => object}
16
+ unless object.is_a? Hash
17
+ hash = {:body => object.body,
18
+ :user_id => object.user_id,
19
+ :target_id => object.target_id,
20
+ :created_at => object.created_at,
21
+ :updated_at => object.updated_at,
22
+ :id => object.id,
23
+ :project_id => object.prefix_options[:project_id]}
24
+ else
25
+ hash = object
26
+ end
27
+ super hash
28
+ end
29
+ end
30
+
31
+
32
+ def self.find_by_id(project_id, task_id, id)
33
+ self.search(project_id, task_id).select { |task| task.id == id }.first
34
+ end
35
+
36
+ def self.find_by_attributes(project_id, task_id, attributes = {})
37
+ search_by_attribute(self.search(project_id, task_id), attributes)
38
+ end
39
+
40
+ def self.search(project_id, task_id, options = {}, limit = 1000)
41
+ comments = API.find(:all, :params => {:project_id => project_id, :task_id => task_id, :count => 0}).collect { |comment| self.new comment }
42
+ end
43
+
44
+ def updated_at
45
+ @updated_at ||= begin
46
+ Time.parse(self[:updated_at])
47
+ rescue
48
+ self[:updated_at]
49
+ end
50
+ end
51
+
52
+ def created_at
53
+ @updated_at ||= begin
54
+ Time.parse(self[:created_at])
55
+ rescue
56
+ self[:created_at]
57
+ end
58
+ end
59
+
60
+
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,50 @@
1
+ module TicketMaster::Provider
2
+ module Teambox
3
+ # Project class for ticketmaster-teambox
4
+ #
5
+ #
6
+ class Project < TicketMaster::Provider::Base::Project
7
+ API = TeamboxAPI::Project # The class to access the api's projects
8
+ # declare needed overloaded methods here
9
+
10
+ def tickets(*options)
11
+ begin
12
+ if options.first.is_a? Hash
13
+ #options[0].merge!(:params => {:id => id})
14
+ super(*options)
15
+ elsif options.empty?
16
+ tickets = TeamboxAPI::Task.find(:all, :params => {:project_id => id}).collect { |ticket| TicketMaster::Provider::Teambox::Ticket.new ticket }
17
+ else
18
+ super(*options)
19
+ end
20
+ rescue
21
+ []
22
+ end
23
+ end
24
+
25
+ def ticket!(*options)
26
+ options[0].merge!(:project_id => id) if options.first.is_a?(Hash)
27
+ provider_parent(self.class)::Ticket.create(*options)
28
+ end
29
+
30
+ # copy from this.copy(that) copies that into this
31
+ def copy(project)
32
+ project.tickets.each do |ticket|
33
+ copy_ticket = self.ticket!(:title => ticket.name)
34
+ ticket.comments.each do |comment|
35
+ copy_ticket.comment!(:body => comment.body)
36
+ sleep 1
37
+ end
38
+ end
39
+ end
40
+
41
+ def id
42
+ self[:id]
43
+ end
44
+
45
+
46
+ end
47
+ end
48
+ end
49
+
50
+
@@ -0,0 +1,38 @@
1
+ module TicketMaster::Provider
2
+ # This is the Teambox Provider for ticketmaster
3
+ module Teambox
4
+ include TicketMaster::Provider::Base
5
+ TICKET_API = TeamboxAPI::Task # The class to access the api's tickets
6
+ PROJECT_API = TeamboxAPI::Project # The class to access the api's projects
7
+
8
+ # This is for cases when you want to instantiate using TicketMaster::Provider::Teambox.new(auth)
9
+ def self.new(auth = {})
10
+ TicketMaster.new(:teambox, auth)
11
+ end
12
+
13
+ # Providers must define an authorize method. This is used to initialize and set authentication
14
+ # parameters to access the API
15
+ def authorize(auth = {})
16
+ @authentication ||= TicketMaster::Authenticator.new(auth)
17
+ auth = @authentication
18
+ if auth.username.blank? and auth.password.blank? and auth.client_id.nil? and auth.client_secret.nil?
19
+ raise "Please provide username, password, client id and client secret"
20
+ end
21
+ TeamboxAPI.authenticate(auth.client_id, auth.client_secret, auth.username, auth.password)
22
+ end
23
+
24
+ # declare needed overloaded methods here
25
+ #
26
+ def valid?
27
+ begin
28
+ PROJECT_API.find(:first)
29
+ true
30
+ rescue
31
+ false
32
+ end
33
+ end
34
+
35
+ end
36
+ end
37
+
38
+
@@ -0,0 +1,66 @@
1
+ module TicketMaster::Provider
2
+ module Teambox
3
+ # Ticket class for ticketmaster-teambox
4
+ API = TeamboxAPI::Task # The class to access the api's tickets
5
+
6
+ class Ticket < TicketMaster::Provider::Base::Ticket
7
+ # declare needed overloaded methods here
8
+
9
+ def initialize(*object)
10
+ if object.first
11
+ args = object
12
+ object = args.shift
13
+ project_id = args.shift
14
+ @system_data = {:client => object}
15
+ unless object.is_a? Hash
16
+ hash = {:status => object.status,
17
+ :name => object.name,
18
+ :updated_at => object.updated_at,
19
+ :id => object.id,
20
+ :project_id => project_id.nil? ? object.prefix_options[:project_id] : project_id}
21
+ else
22
+ hash = object
23
+ end
24
+ super hash
25
+ end
26
+ end
27
+
28
+ def self.create(*options)
29
+ task = API.new(options.first.merge!(:status => 1,
30
+ :updated_at => Time.now
31
+ ))
32
+ ticket = self.new task
33
+ task.save
34
+ ticket
35
+ end
36
+
37
+ def self.find_by_id(project_id, task_id)
38
+ self.search(project_id, {:id => task_id}).first
39
+ end
40
+
41
+ def self.search(project_id, options = {}, limit = 1000)
42
+ tickets = API.find(:all, :params => {:project_id => project_id}).collect { |ticket| self.new ticket, project_id }
43
+ self.search_by_attribute(tickets, options, limit)
44
+ end
45
+
46
+ def self.find_by_attributes(project_id, attributes = {})
47
+ self.search(project_id, attributes)
48
+ end
49
+
50
+ def project_id
51
+ self[:project_id]
52
+ end
53
+
54
+ def task_id
55
+ self[:id]
56
+ end
57
+
58
+ def comment!(*options)
59
+ options[0].update(:project_id => project_id, :task_id => task_id) if options.first.is_a?(Hash)
60
+ provider_parent(self.class)::Comment.create(*options)
61
+ end
62
+
63
+
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,274 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+ require 'active_resource'
4
+ require 'oauth2'
5
+
6
+ # Ruby lib for working with the Teambox API's JSON interface.
7
+ # You should set the authentication using your login
8
+ # credentials, client_id and client_secret (OAuth2).
9
+
10
+ # This library is a small wrapper around the REST interface
11
+
12
+ module TeamboxAPI
13
+ class Error < StandardError; end
14
+ class << self
15
+ attr_accessor :client_id, :client_secret, :site, :username, :password, :token
16
+ def authenticate(client_id, client_secret, username, password)
17
+ @username = username
18
+ @password = password
19
+ @site = 'https://teambox.com/'
20
+ @client_id = client_id
21
+ @client_secret = client_secret
22
+
23
+ self::Base.user = username
24
+ self::Base.password = password
25
+ self.token = access_token(self)
26
+
27
+ end
28
+
29
+ def access_token(master)
30
+ @auth_url = '/oauth/token'
31
+ consumer = OAuth2::Client.new(master.client_id,
32
+ master.client_secret,
33
+ {:site =>
34
+ {:url => master.site,
35
+ :ssl => {:verify => OpenSSL::SSL::VERIFY_NONE,
36
+ :ca_file => nil
37
+ }
38
+ },
39
+ :authorize_url => @auth_url,
40
+ :parse_json => true})
41
+
42
+ response = consumer.request(:post, @auth_url, {:grant_type => 'password',
43
+ :client_id => master.client_id,
44
+ :client_secret => master.client_secret,
45
+ :username => master.username,
46
+ :password => master.password,
47
+ :scope => 'read_projects write_projects'},
48
+ 'Content-Type' => 'application/x-www-form-urlencoded')
49
+
50
+ OAuth2::AccessToken.new(consumer, response['access_token']).token
51
+
52
+ end
53
+
54
+ def token=(value)
55
+ resources.each do |klass|
56
+ klass.headers['Authorization'] = 'OAuth ' + value.to_s
57
+ end
58
+ @token = value
59
+ end
60
+
61
+ def resources
62
+ @resources ||= []
63
+ end
64
+ end
65
+
66
+ class Base < ActiveResource::Base
67
+ self.site = 'https://teambox.com/api/1/'
68
+ self.format = :json
69
+ def self.inherited(base)
70
+ TeamboxAPI.resources << base
71
+ super
72
+ end
73
+ end
74
+
75
+ # Find projects
76
+ #
77
+ # TeamboxAPI::Project.find(:all) # find all projects for the current account.
78
+ # TeamboxAPI::Project.find(12345) # find individual project by ID
79
+ #
80
+ # Creating a Project
81
+ #
82
+ # project = TeamboxAPI::Project.new(:name => 'Ninja Whammy Jammy')
83
+ # project.save
84
+ # # => true
85
+ #
86
+ #
87
+ # Updating a Project
88
+ #
89
+ # project = TeamboxAPI::Project.find(12345)
90
+ # project.name = "A new name"
91
+ # project.save
92
+ #
93
+ # Finding tickets
94
+ #
95
+ # project = TeamboxAPI::Project.find(12345)
96
+ # project.tickets
97
+ #
98
+
99
+
100
+ class Project < Base
101
+
102
+ def self.collection_path(organization_path, prefix_options = {}, query_options = nil)
103
+ prefix_options, query_options = split_options(prefix_options) if query_options.nil?
104
+ "#{prefix(prefix_options)}#{organization_path}#{collection_name}.#{format.extension}#{query_string(query_options)}"
105
+ end
106
+
107
+ def collection_path(options = nil)
108
+ organization_path = "organizations/#{attributes[:organization_id].to_s}/"
109
+ self.class.collection_path(organization_path, options || prefix_options)
110
+ end
111
+
112
+ def self.instantiate_collection(collection, prefix_options = {})
113
+ objects = collection["objects"]
114
+ objects.collect! { |record| instantiate_record(record, prefix_options) }
115
+ end
116
+
117
+ def tickets(options = {})
118
+ Task.find(:all, :params => options.update(:project_id => project_id))
119
+ end
120
+
121
+ def project_id
122
+ self[:id]
123
+ end
124
+
125
+ def encode(options={})
126
+ val = []
127
+ attributes.each_pair do |key, value|
128
+ val << "#{URI.escape key}=#{URI.escape value}" rescue nil
129
+ end
130
+ val.join('&')
131
+ end
132
+
133
+ def update
134
+ connection.put(element_path(prefix_options) + '?' + encode, nil, self.class.headers).tap do |response|
135
+ load_attributes_from_response(response)
136
+ end
137
+ end
138
+
139
+ def create
140
+ connection.post(collection_path + '?' + encode, nil, self.class.headers).tap do |response|
141
+ self.id = id_from_response(response)
142
+ load_attributes_from_response(response)
143
+ end
144
+ end
145
+
146
+ def organization_id
147
+ attributes[:organization_id]
148
+ end
149
+
150
+
151
+ def self.find_every(options)
152
+ #add :count => 0 in order to retrieve objects with no limits. Default is 20 objects per request.
153
+ options.merge!(:params => {:count => 0})
154
+ begin
155
+ case from = options[:from]
156
+ when Symbol
157
+ self.instantiate_collection(get(from, options[:params]))
158
+ when String
159
+ path = "#{from}#{query_string(options[:params])}"
160
+ self.instantiate_collection(connection.get(path, headers) || [])
161
+ else
162
+ prefix_options, query_options = split_options(options[:params])
163
+ path = self.collection_path(nil, prefix_options, query_options)
164
+ self.instantiate_collection( (connection.get(path, headers) || []), prefix_options )
165
+ end
166
+ rescue ActiveResource::ResourceNotFound
167
+ # Swallowing ResourceNotFound exceptions and return nil - as per
168
+ # ActiveRecord.
169
+ nil
170
+ end
171
+ end
172
+
173
+
174
+ end
175
+
176
+ # Find tickets
177
+ #
178
+ # TeamboxAPI::Task.find(:all, :params => { :name => 'my_project' })
179
+ #
180
+ # project = TeamboxAPI::Project.find('my_project')
181
+ # project.tickets
182
+ # project.tickets(:name => 'a new name')
183
+ #
184
+
185
+
186
+ class Task < Base
187
+
188
+ self.site += 'projects/:project_id/'
189
+
190
+ def self.collection_path(task_list_path, prefix_options = {}, query_options = nil)
191
+ prefix_options, query_options = split_options(prefix_options) if query_options.nil?
192
+ "#{prefix(prefix_options)}#{task_list_path}#{collection_name}.#{format.extension}#{query_string(query_options)}"
193
+ end
194
+
195
+ def collection_path(options = nil)
196
+ task_list_path = "task_lists/#{attributes[:task_list_id]}/"
197
+ self.class.collection_path(task_list_path, options || prefix_options)
198
+ end
199
+
200
+ def self.instantiate_collection(collection, prefix_options = {})
201
+ objects = collection["objects"]
202
+ objects.collect! { |record| instantiate_record(record, prefix_options) }
203
+ end
204
+
205
+ def encode(options={})
206
+ val = []
207
+ attributes.each_pair do |key, value|
208
+ val << "#{URI.escape key}=#{URI.escape value}" rescue nil
209
+ end
210
+ val.join('&')
211
+ end
212
+
213
+ def update
214
+ connection.put(element_path(prefix_options) + '?' + encode, nil, self.class.headers).tap do |response|
215
+ load_attributes_from_response(response)
216
+ end
217
+ end
218
+
219
+ def create
220
+ connection.post(collection_path + '?' + encode, nil, self.class.headers).tap do |response|
221
+ self.id = id_from_response(response)
222
+ load_attributes_from_response(response)
223
+ end
224
+ end
225
+
226
+ def self.find_every(options)
227
+ #add :count => 0 in order to retrieve objects with no limits. Default is 20 objects per request.
228
+ options[:params].merge!(:count => 0)
229
+ begin
230
+ case from = options[:from]
231
+ when Symbol
232
+ self.instantiate_collection(get(from, options[:params]))
233
+ when String
234
+ path = "#{from}#{query_string(options[:params])}"
235
+ self.instantiate_collection(connection.get(path, headers) || [])
236
+ else
237
+ prefix_options, query_options = split_options(options[:params])
238
+ path = self.collection_path(nil, prefix_options, query_options)
239
+ self.instantiate_collection( (connection.get(path, headers) || []), prefix_options )
240
+ end
241
+ rescue ActiveResource::ResourceNotFound
242
+ # Swallowing ResourceNotFound exceptions and return nil - as per
243
+ # ActiveRecord.
244
+ nil
245
+ end
246
+ end
247
+
248
+ end
249
+
250
+ class Comment < Base
251
+ self.site += 'projects/:project_id/tasks/:task_id/'
252
+
253
+ def self.instantiate_collection(collection, prefix_options = {})
254
+ objects = collection["objects"]
255
+ objects.collect! { |record| instantiate_record(record, prefix_options) }
256
+ end
257
+
258
+ def create
259
+ connection.post(collection_path + '?' + encode, nil, self.class.headers).tap do |response|
260
+ load_attributes_from_response(response)
261
+ end
262
+ end
263
+
264
+ def encode(options={})
265
+ val=[]
266
+ attributes.each_pair do |key, value|
267
+ val << "#{URI.escape key}=#{URI.escape value}" rescue nil
268
+ end
269
+ val.join('&')
270
+ end
271
+
272
+ end
273
+
274
+ end