ticketmaster-teambox 0.1.0

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