etherpad-lite 0.0.4 → 0.1.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,11 @@
1
+ ** RELEASE 0.1.0 (Pending) **
2
+
3
+ * Requires Etherpad Lite 1.1+
4
+ * Added support for get/setHTML
5
+ * Uses POST for API calls which alter data - this allows much larger pad content to be written
6
+ * Various minor improvements and bugfixes
7
+ * More complete documentation and examples
8
+
1
9
  ** RELEASE 0.0.4 (09/12/2011) **
2
10
 
3
11
  * Bugfix to Pads. A Pad initialied with a specific revision was not returning that revision's text.
data/README.rdoc CHANGED
@@ -1,13 +1,15 @@
1
1
  = Etherpad Lite Ruby Client
2
2
 
3
- etherpad-lite is a Ruby client for Etherpad Lite's HTTP JSON API. Etherpad Lite is a collaborative editor provided by the Etherpad Foundation (http://etherpad.org).
3
+ The etherpad-lite Ruby Gem is a Ruby client for Etherpad Lite's HTTP JSON API. Etherpad Lite is a collaborative editor provided by the {Etherpad Foundation}[http://etherpad.org].
4
4
 
5
- See https://github.com/Pita/etherpad-lite for information on how to install and configure your own Etherpad Lite instance, and read https://github.com/Pita/etherpad-lite/wiki/HTTP-API for an in-depth description of Etherpad Lite's HTTP API.
5
+ See {github.com/Pita/etherpad-lite}[https://github.com/Pita/etherpad-lite] for information on how to install and configure your own Etherpad Lite instance, and read {github.com/Pita/etherpad-lite/wiki/HTTP-API}[https://github.com/Pita/etherpad-lite/wiki/HTTP-API] for an in-depth description of Etherpad Lite's HTTP API.
6
6
 
7
- == 1 Installation
7
+ == Installation
8
8
  gem install etherpad-lite
9
9
 
10
- == 2 Basic usage
10
+ *NOTE* Support for Ruby 1.8.x is deprecated and will be removed in future versions. Upgrade to Ruby 1.9.x and stop being an old fuddie-duddie. It's the IE6 of Ruby.
11
+
12
+ == Basic usage
11
13
  require 'etherpad-lite'
12
14
 
13
15
  # Connect to your Etherpad Lite instance
@@ -23,19 +25,24 @@ See https://github.com/Pita/etherpad-lite for information on how to install and
23
25
  pad.text = "What hath God wrought?"
24
26
 
25
27
  # There are now 2 revisions!
26
- puts pad.revison_numbers.size
27
- => 2
28
+ puts pad.revision_numbers
29
+ => [0, 1]
28
30
 
29
31
  # Iterate through each revision
30
32
  pad.revisions.each do |pad_rev|
31
- puts pad_rev.rev
33
+ puts "Revision #{pad_rev.rev}:"
32
34
  puts pad_rev.text
33
35
  end
34
36
 
35
- Read the full docs at http://jordanhollinger.com/docs/ruby-etherpad-lite/.
37
+ Full docs are at {jordanhollinger.com/docs/ruby-etherpad-lite/}[http://jordanhollinger.com/docs/ruby-etherpad-lite/]
38
+
39
+ == Advanced usage
40
+ The above example deals with public pads, accessible to anyone through the Web UI. There is another class of pads - group pads - which deal with groups, authors and sessions.
41
+ Examples are documented in EtherpadLite::Group, EtherpadLite::Author, and EtherpadLite::Session.
36
42
 
37
- == 3 Example use in Rails
38
- For your view, I recommend the jQuery plugin at https://github.com/johnyma22/etherpad-lite-jquery-plugin.
43
+ == Example use in Rails
44
+ For your view, I recommend the jQuery plugin at {github.com/johnyma22/etherpad-lite-jquery-plugin}[https://github.com/johnyma22/etherpad-lite-jquery-plugin].
45
+ Also, I recommend reading the docs for EtherpadLite::Group first.
39
46
 
40
47
  Add the following to your Gemfile
41
48
  gem 'etherpad-lite'
@@ -46,27 +53,28 @@ On login, create a Hash in your session to store EtherpadLite API sessions:
46
53
  Some example controller actions:
47
54
 
48
55
  class EtherpadController < ApplicationController
56
+ # /etherpad
49
57
  def index
50
58
  # The idea is that your users are probably members of some kind of groups.
51
59
  # These groups can be mapped to EtherpadLite Groups. List all the user's groups.
52
60
  @app_groups = current_user.groups
53
61
  end
54
62
 
63
+ # /etherpad/groups/:id
55
64
  def group
56
- ether = EtherpadLite.connect(:local, 'api key')
65
+ ether = EtherpadLite.connect(:local, File.new('/var/www/etherpad-lite/APIKEY.txt'))
57
66
  @app_group = YourAppGroup.find(params[:id])
58
- # Map your app's group to an EtherpadLite Group
67
+ # Map your app's group to an EtherpadLite Group, and list all its pads
59
68
  group = ether.group("my_app_group_#{@app_group.id}")
60
- # List all the pads in group
61
69
  @pads = group.pads
62
70
  end
63
71
 
72
+ # /etherpad/pads/:ep_group_id/:ep_pad_name
64
73
  def pad
65
- ether = EtherpadLite.connect(:local, 'api key')
66
- # Get the EtherpadLite Group by id
67
- @group = ether.get_group(params[:group_id])
68
- # Get the pad
69
- @pad = @group.pad(params[:pad_name])
74
+ ether = EtherpadLite.connect(:local, File.new('/var/www/etherpad-lite/APIKEY.txt'))
75
+ # Get the EtherpadLite Group and Pad by id
76
+ @group = ether.get_group(params[:ep_group_id])
77
+ @pad = @group.pad(params[:ep_pad_name])
70
78
  # Map the user to an EtherpadLite Author
71
79
  author = ether.author("my_app_user_#{current_user.id}", :name => current_user.name)
72
80
  # Get or create an hour-long session for this Author in this Group
@@ -81,24 +89,42 @@ Some example controller actions:
81
89
  end
82
90
  end
83
91
 
84
- == 4 Why is the Ruby client so different from the others? What gives you the right?!?
85
- The PHP and Python clients are extremely thin wrappers around the HTTP API; their method names map directly to urls. The Ruby client offers a slightly higher level of abstration,
86
- with the goal of making Etherpad Lite integration in Ruby projects as simple, poweful, and dare I say fun, as possible. That said, there is nothing wrong with the thinly-wrapped API.
87
- So in the interests of being a good citizen, the Ruby client is written in two layers, one conforming to the other clients, and a higher-level "models" API riding on top of it.
92
+ == Why is the Ruby client so different from the others? What gives you the right?!?
93
+ Most of the EPL clients are extremely thin wrappers around the HTTP API. The Ruby client offers a slightly higher level of abstraction,
94
+ with the goal of making it as simple, powerful, and dare I say fun, as possible. That said, there are times when a bare-bones client may be
95
+ preferable. In a hopefully not misguided attempt to please everyone, the Ruby client is written in two layers:
96
+ - A high-level "models" interface starting with EtherpadLite::Instance (above)
97
+ - A low-level client matching the HTTP API (EtherpadLite::Client, below)
88
98
 
89
- In the examples above, the "standard" client can be accessed with
99
+ In the examples above, the low-level client is accessible from the high-level interface:
90
100
  client = ether.client
91
101
  client.getText('my first etherpad lite pad')
92
102
  => {:text => "What hath God wrought?"}
93
103
 
94
- Or you can explicitly load only the standard client
104
+ or you can explicitly load just the low-level client:
95
105
  require 'etherpad-lite/client'
96
- client = EtherpadLite::Client.new('api key', 'http://beta.etherpad.org/api')
106
+ client = EtherpadLite::Client.new('http://beta.etherpad.org/api', 'api key')
107
+
108
+ The methods available to the low-level client should precisely match the HTTP API. In general, it behaves identically to the other
109
+ clients, particularly PHP's and Python's.
110
+
111
+ == Testing
112
+ Testing this library is fairly simple. It requires:
113
+ - A recent version of Rspec
114
+ - A running copy of Etherpad Lite with a fresh db for each run of the tests (configure connection in spec/config.yml)
115
+
116
+ Bring up Etherpad Lite with:
117
+
118
+ rm var/dirty.db && bin/run.sh
119
+
120
+ Run the tests with
121
+
122
+ rspec spec
97
123
 
98
- == 5 License
124
+ == License
99
125
  Copyright 2011 Jordan Hollinger
100
126
 
101
127
  Licensed under the Apache License
102
128
 
103
- == 5 Credit
104
- This Ruby client was inspired by TomNomNom's and devjones's PHP and Python clients, found at https://github.com/TomNomNom/etherpad-lite-client and https://github.com/devjones/PyEtherpadLite.
129
+ == Credit
130
+ This Ruby client was inspired by {TomNomNom's PHP client}[https://github.com/TomNomNom/etherpad-lite-client] and {devjones's Python client}[https://github.com/devjones/PyEtherpadLite].
@@ -3,46 +3,94 @@ require 'net/http'
3
3
  require 'net/https'
4
4
  require 'json'
5
5
 
6
+ # Ruby 1.8.x may not work, and I don't care
7
+ BAD_RUBY = RUBY_VERSION < '1.9.0' # :nodoc:
8
+
6
9
  module EtherpadLite
10
+ MAJOR_VERSION, MINOR_VERSION, TINY_VERSION, PRE_VERSION = 0, 1, 0, 'rc2' # :nodoc:
11
+ # The client version
12
+ VERSION = [MAJOR_VERSION, MINOR_VERSION, TINY_VERSION, PRE_VERSION].compact.join '.'
13
+
14
+ # An error returned by the server
15
+ class APIError < StandardError
16
+ MESSAGE = "Error while talking to the API (%s). Make sure you are running the latest version of the Etherpad Lite server. If that is not possible, try rolling this client back to an earlier version."
17
+ end
18
+
7
19
  # A thin wrapper around Etherpad Lite's HTTP JSON API
20
+ #
21
+ # client1 = EtherpadLite::Client.new('https://etherpad.yoursite.com[https://etherpad.yoursite.com]', 'your api key')
22
+ #
23
+ # # An alias for http://localhost:9001
24
+ # client2 = EtherpadLite::Client.new(:local, File.new('/path/to/APIKEY.txt'))
25
+ #
26
+ # # An alias for http://localhost:9001
27
+ # ether = EtherpadLite::Client.new(9001, File.new('/path/to/APIKEY.txt'))
8
28
  class Client
29
+ # Aliases to common Etherpad Lite hosts
30
+ HOST_ALIASES = {:local => 'http://localhost:9001',
31
+ :localhost => 'http://localhost:9001'}
32
+
33
+ # The Etherpad Lite HTTP API version this library version targets
9
34
  API_VERSION = 1
10
35
 
36
+ # HTTP API response code for okay
11
37
  CODE_OK = 0
38
+ # HTTP API response code for invalid method parameters
12
39
  CODE_INVALID_PARAMETERS = 1
40
+ # HTTP API response code for Etherpad Lite error
13
41
  CODE_INTERNAL_ERROR = 2
42
+ # HTTP API response code for invalid api method
14
43
  CODE_INVALID_METHOD = 3
44
+ # HTTP API response code for invalid api key
15
45
  CODE_INVALID_API_KEY = 4
16
46
 
17
- attr_reader :uri, :api_key
47
+ # A URI object containing the URL of the Etherpad Lite instance
48
+ attr_reader :uri
49
+ # The API key
50
+ attr_reader :api_key
18
51
 
19
- # Path to the system's CA cert paths (for connecting over SSL)
20
- @@ca_path = nil
21
-
22
- # Get path to the system's CA certs
23
- def self.ca_path; @@ca_path; end
24
-
25
- # Manually set path to the system's CA certs. Use this if the location couldn't be determined automatically.
26
- def self.ca_path=(path); @@ca_path = path; end
52
+ class << self
53
+ # Path to the system's CA certs (for connecting over SSL)
54
+ attr_accessor :ca_path
55
+ end
27
56
 
28
- # Instantiate a new Etherpad Lite Client. The url should include the protocol (i.e. http or https).
29
- def initialize(api_key, url='http://localhost:9001/api')
57
+ # Instantiate a new Etherpad Lite Client.
58
+ #
59
+ # client1 = EtherpadLite::Client.new('https://etherpad.yoursite.com[https://etherpad.yoursite.com]', 'your api key')
60
+ #
61
+ # # An alias for http://localhost:9001
62
+ # client2 = EtherpadLite::Client.new(:local, File.new('/path/to/APIKEY.txt'))
63
+ #
64
+ # # An alias for http://localhost:9001
65
+ # client3 = EtherpadLite::Client.new(9001, File.new('/path/to/APIKEY.txt'))
66
+ def initialize(host_or_alias, api_key_or_file)
67
+ # Parse the host
68
+ url = if host_or_alias.is_a? Symbol
69
+ raise ArgumentError, %Q|Unknown host alias "#{host_or_alias}"| unless HOST_ALIASES.has_key? host_or_alias
70
+ HOST_ALIASES[host_or_alias]
71
+ elsif host_or_alias.is_a? Fixnum
72
+ "http://localhost:#{host_or_alias}"
73
+ else
74
+ host_or_alias.clone
75
+ end
76
+ url << '/api' unless url =~ /\/api$/i
30
77
  @uri = URI.parse(url)
31
- raise ArgumentError, "#{url} is not a valid url" unless @uri.host and @uri.port
32
- @api_key = api_key
33
- connect!
34
- end
78
+ raise ArgumentError, "#{url} does not contain a valid host and port" unless @uri.host and @uri.port
79
+
80
+ # Parse the api key
81
+ if api_key_or_file.is_a? File
82
+ @api_key = begin
83
+ api_key_or_file.read
84
+ rescue IOError
85
+ api_key_or_file.reopen(api_key_or_file.path, mode='r')
86
+ api_key_or_file.read
87
+ end
88
+ api_key_or_file.close
89
+ else
90
+ @api_key = api_key_or_file
91
+ end
35
92
 
36
- # Calls the EtherpadLite API and returns the :data portion of the response Hash.
37
- def call(method, params={})
38
- # Build path
39
- params[:apikey] = @api_key
40
- params = params.map { |p| p.join('=') }.join('&').gsub(/\s/, '%20')
41
- path = [@uri.path, API_VERSION, method].compact.join('/') << '?' << params
42
- # Send request
43
- get = Net::HTTP::Get.new(path)
44
- response = @http.request(get)
45
- handleResult response.body
93
+ connect!
46
94
  end
47
95
 
48
96
  # Groups
@@ -50,29 +98,29 @@ module EtherpadLite
50
98
 
51
99
  # Creates a new Group
52
100
  def createGroup
53
- call :createGroup
101
+ post :createGroup
54
102
  end
55
103
 
56
104
  # Creates a new Group for groupMapper if one doesn't already exist. Helps you map your application's groups to Etherpad Lite's groups.
57
105
  def createGroupIfNotExistsFor(groupMapper)
58
- call :createGroupIfNotExistsFor, :groupMapper => groupMapper
106
+ post :createGroupIfNotExistsFor, :groupMapper => groupMapper
59
107
  end
60
108
 
61
109
  # Deletes a group
62
110
  def deleteGroup(groupID)
63
- call :deleteGroup, :groupID => groupID
111
+ post :deleteGroup, :groupID => groupID
64
112
  end
65
113
 
66
114
  # Returns all the Pads in the given Group
67
115
  def listPads(groupID)
68
- call :listPads, :groupID => groupID
116
+ get :listPads, :groupID => groupID
69
117
  end
70
118
 
71
119
  # Creates a new Pad in the given Group
72
120
  def createGroupPad(groupID, padName, text=nil)
73
121
  params = {:groupID => groupID, :padName => padName}
74
122
  params[:text] = text unless text.nil?
75
- call :createGroupPad, params
123
+ post :createGroupPad, params
76
124
  end
77
125
 
78
126
  # Authors
@@ -82,14 +130,14 @@ module EtherpadLite
82
130
  def createAuthor(name=nil)
83
131
  params = {}
84
132
  params[:name] = name unless name.nil?
85
- call :createAuthor, params
133
+ post :createAuthor, params
86
134
  end
87
135
 
88
136
  # Creates a new Author for authorMapper if one doesn't already exist. Helps you map your application's authors to Etherpad Lite's authors.
89
137
  def createAuthorIfNotExistsFor(authorMapper, name=nil)
90
138
  params = {:authorMapper => authorMapper}
91
139
  params[:name] = name unless name.nil?
92
- call :createAuthorIfNotExistsFor, params
140
+ post :createAuthorIfNotExistsFor, params
93
141
  end
94
142
 
95
143
  # Sessions
@@ -99,27 +147,27 @@ module EtherpadLite
99
147
 
100
148
  # Creates a new Session for the given Author in the given Group
101
149
  def createSession(groupID, authorID, validUntil)
102
- call :createSession, :groupID => groupID, :authorID => authorID, :validUntil => validUntil
150
+ post :createSession, :groupID => groupID, :authorID => authorID, :validUntil => validUntil
103
151
  end
104
152
 
105
153
  # Deletes the given Session
106
154
  def deleteSession(sessionID)
107
- call :deleteSession, :sessionID => sessionID
155
+ post :deleteSession, :sessionID => sessionID
108
156
  end
109
157
 
110
158
  # Returns information about the Session
111
159
  def getSessionInfo(sessionID)
112
- call :getSessionInfo, :sessionID => sessionID
160
+ get :getSessionInfo, :sessionID => sessionID
113
161
  end
114
162
 
115
163
  # Returns all Sessions in the given Group
116
164
  def listSessionsOfGroup(groupID)
117
- call :listSessionsOfGroup, :groupID => groupID
165
+ get :listSessionsOfGroup, :groupID => groupID
118
166
  end
119
167
 
120
168
  # Returns all Sessions belonging to the given Author
121
169
  def listSessionsOfAuthor(authorID)
122
- call :listSessionsOfAuthor, :authorID => authorID
170
+ get :listSessionsOfAuthor, :authorID => authorID
123
171
  end
124
172
 
125
173
  # Pad content
@@ -129,12 +177,24 @@ module EtherpadLite
129
177
  def getText(padID, rev=nil)
130
178
  params = {:padID => padID}
131
179
  params[:rev] = rev unless rev.nil?
132
- call :getText, params
180
+ get :getText, params
133
181
  end
134
182
 
135
183
  # Sets the text of the given Pad
136
184
  def setText(padID, text)
137
- call :setText, :padID => padID, :text => text
185
+ post :setText, :padID => padID, :text => text
186
+ end
187
+
188
+ # Returns the text of the given Pad as HTML. Optionally pass a revision number to get the HTML for that revision.
189
+ def getHTML(padID, rev=nil)
190
+ params = {:padID => padID}
191
+ params[:rev] = rev unless rev.nil?
192
+ get :getHTML, params
193
+ end
194
+
195
+ # Sets the HTML text of the given Pad
196
+ def setHTML(padID, html)
197
+ post :setHTML, :padID => padID, :html => html
138
198
  end
139
199
 
140
200
  # Pad
@@ -146,42 +206,42 @@ module EtherpadLite
146
206
  def createPad(padID, text=nil)
147
207
  params = {:padID => padID}
148
208
  params[:text] = text unless text.nil?
149
- call :createPad, params
209
+ post :createPad, params
150
210
  end
151
211
 
152
212
  # Returns the number of revisions the given Pad contains
153
213
  def getRevisionsCount(padID)
154
- call :getRevisionsCount, :padID => padID
214
+ get :getRevisionsCount, :padID => padID
155
215
  end
156
216
 
157
217
  # Delete the given Pad
158
218
  def deletePad(padID)
159
- call :deletePad, :padID => padID
219
+ post :deletePad, :padID => padID
160
220
  end
161
221
 
162
222
  # Returns the Pad's read-only id
163
223
  def getReadOnlyID(padID)
164
- call :getReadOnlyID, :padID => padID
224
+ get :getReadOnlyID, :padID => padID
165
225
  end
166
226
 
167
227
  # Sets a boolean for the public status of a Pad
168
228
  def setPublicStatus(padID, publicStatus)
169
- call :setPublicStatus, :padID => padID, :publicStatus => publicStatus
229
+ post :setPublicStatus, :padID => padID, :publicStatus => publicStatus
170
230
  end
171
231
 
172
232
  # Gets a boolean for the public status of a Pad
173
233
  def getPublicStatus(padID)
174
- call :getPublicStatus, :padID => padID
234
+ get :getPublicStatus, :padID => padID
175
235
  end
176
236
 
177
237
  # Sets the password on a pad
178
238
  def setPassword(padID, password)
179
- call :setPassword, :padID => padID, :password => password
239
+ post :setPassword, :padID => padID, :password => password
180
240
  end
181
241
 
182
242
  # Returns true if the Pad has a password, false if not
183
243
  def isPasswordProtected(padID)
184
- call :isPasswordProtected, :padID => padID
244
+ get :isPasswordProtected, :padID => padID
185
245
  end
186
246
 
187
247
  # Returns true if the connection to the Etherpad Lite instance is using SSL/HTTPS.
@@ -191,16 +251,54 @@ module EtherpadLite
191
251
 
192
252
  protected
193
253
 
254
+ # Alias to "call" using the GET HTTP method
255
+ def get(method, params={})
256
+ call method, params, :get
257
+ end
258
+
259
+ # Alias to "call" using the POST HTTP method
260
+ def post(method, params={})
261
+ call method, params, :post
262
+ end
263
+
264
+ # Calls the EtherpadLite API and returns the :data portion of the response Hash.
265
+ #
266
+ # "method" should be a valid API method name, as a String or Symbol.
267
+ #
268
+ # "params" should be any URL or form parameters as a Hash.
269
+ #
270
+ # "http_method" should be :get or :post, defaults to :get.
271
+ #
272
+ def call(method, params={}, http_method=:get)
273
+ params[:apikey] = @api_key
274
+ uri = [@uri.path, API_VERSION, method].compact.join('/')
275
+ http_method = :post if BAD_RUBY # XXX A horrible, horrible hack for Ruby 1.8
276
+ req = case http_method
277
+ when :get then Net::HTTP::Get.new(uri << '?' << URI.encode_www_form(params))
278
+ when :post
279
+ post = Net::HTTP::Post.new(uri)
280
+ post.set_form_data(params)
281
+ post
282
+ else raise ArgumentError, "#{http_method} is not a valid HTTP method"
283
+ end
284
+ response = @http.request(req)
285
+ handleResult response.body
286
+ end
287
+
194
288
  # Parses the JSON response from the server, returning the data object as a Hash with symbolized keys.
195
289
  # If the API response contains an error code, an exception is raised.
196
290
  def handleResult(response)
197
- response = JSON.parse(response, :symbolize_names => true)
291
+ begin
292
+ response = JSON.parse(response, :symbolize_names => true)
293
+ rescue JSON::ParserError
294
+ raise APIError, APIError::MESSAGE % response
295
+ end
198
296
  case response[:code]
199
297
  when CODE_OK then response[:data]
200
298
  when CODE_INVALID_PARAMETERS, CODE_INVALID_API_KEY, CODE_INVALID_METHOD
201
299
  raise ArgumentError, response[:message]
202
300
  else
203
- raise StandardError, "An unknown error ocurrced while handling the response: #{response.to_s}"
301
+ raise APIError, "An unknown error ocurrced while handling the response: #{response.to_s}"
204
302
  end
205
303
  end
206
304
 
@@ -211,9 +309,9 @@ module EtherpadLite
211
309
  @http = Net::HTTP.new(@uri.host, @uri.port)
212
310
  if secure?
213
311
  @http.use_ssl = true
214
- if @@ca_path
312
+ if self.class.ca_path
215
313
  @http.verify_mode = OpenSSL::SSL::VERIFY_PEER
216
- @http.ca_path = @@ca_path
314
+ @http.ca_path = self.class.ca_path
217
315
  else
218
316
  @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
219
317
  end
@@ -227,3 +325,6 @@ end
227
325
  EtherpadLite::Client.ca_path = path and break if File.exists? path
228
326
  end
229
327
  $stderr.puts %q|WARNING Ruby etherpad-lite client was unable to find your CA Certificates; HTTPS connections will *not* be verified! You may remedy this with "EtherpadLite::Client.ca_path = '/path/to/certs'"| unless EtherpadLite::Client.ca_path
328
+
329
+ # Warn about old Ruby versions
330
+ $stderr.puts "WARNING You are using an ancient version of Ruby which may not be supported. Upgrade Ruby!" if BAD_RUBY
@@ -1,7 +1,54 @@
1
1
  module EtherpadLite
2
2
  # An Author of Pad content
3
+ #
4
+ # Authors are used to create a Session in a Group. Authors may be created with
5
+ # a name and a mapper. A mapper is usually an identifier stored in your third-party system,
6
+ # like a foreign key or username.
7
+ #
8
+ # Author Examples:
9
+ #
10
+ # @ether = EtherpadLite.connect(:local, 'api key')
11
+ #
12
+ # # Create a new author with both a name and a mapper
13
+ # author1 = @ether.create_author(:name => 'Theodor Seuss Geisel', :mapper => 'author_1')
14
+ #
15
+ # # Load (and create, if necessary) a mapped author with a name
16
+ # author2 = @ether.author('author_2', :name => 'Richard Bachman')
17
+ #
18
+ # # Load (and create, if necessary) a author by mapper
19
+ # author3 = @ether.author('author_3')
20
+ #
21
+ # # Load author1 by id
22
+ # author4 = @ether.get_author(author1.id)
23
+ #
24
+ # Session examples:
25
+ #
26
+ # # Create two hour-long session for author 1 in two different groups
27
+ # group1 = @ether.group('my awesome group')
28
+ # group2 = @ether.group('my other awesome group')
29
+ #
30
+ # session1 = author1.create_session(group1, 60)
31
+ # session2 = author1.create_session(group2, 60)
32
+ #
33
+ # Attribute examples:
34
+ #
35
+ # author1.name #> "Theodor Seuss Geisel"
36
+ #
37
+ # author1.mapper #> "author_1"
38
+ #
39
+ # author2.sessions #> [#<EtherpadLite::Session>, #<EtherpadLite::Session>]
40
+ #
41
+ # author2.session_ids.include? session1.id #> true
42
+ #
3
43
  class Author
4
- attr_reader :id, :instance, :name, :mapper
44
+ # The EtherpadLite::Instance object
45
+ attr_reader :instance
46
+ # The author's id
47
+ attr_reader :id
48
+ # The author's name (if any)
49
+ attr_reader :name
50
+ # The author's foreign mapper (if any)
51
+ attr_reader :mapper
5
52
 
6
53
  # Creates a new Author. Optionally, you may pass the :mapper option your third party system's author id.
7
54
  # This will allow you to find the Author again later using the same identifier as your foreign system.
@@ -9,9 +56,9 @@ module EtherpadLite
9
56
  #
10
57
  # Options:
11
58
  #
12
- # mapper => uid of Author from another system
59
+ # mapper => uid of Author from another system
13
60
  #
14
- # name => Author's name
61
+ # name => Author's name
15
62
  def self.create(instance, options={})
16
63
  result = options[:mapper] \
17
64
  ? instance.client.createAuthorIfNotExistsFor(options[:mapper], options[:name]) \
@@ -23,9 +70,9 @@ module EtherpadLite
23
70
  #
24
71
  # Options:
25
72
  #
26
- # mapper => the foreign author id it's mapped to
73
+ # mapper => the foreign author id it's mapped to
27
74
  #
28
- # name => the Author's name
75
+ # name => the Author's name
29
76
  def initialize(instance, id, options={})
30
77
  @instance = instance
31
78
  @id = id
@@ -1,10 +1,59 @@
1
1
  module EtherpadLite
2
- # A Group of Pads
2
+ # A Group serves as a container for related pads. Only an Author with a Session can access a group Pad.
3
+ #
4
+ # Group examples:
5
+ #
6
+ # # Create a new group
7
+ # group1 = @ether.create_group
8
+ # # Etherpad Lite will assign it an internal id
9
+ # group.id #> 'g.asdflsadf7w9823kjlasdf'
10
+ #
11
+ # # Create a new group with a mapper, so it can be easily found again
12
+ # group2 = @ether.create_group :mapper => 'Blurg'
13
+ #
14
+ # # Load (or create, if it doesn't exist) a group mapped to "Flarb"
15
+ # group3 = @ether.group('Flarb')
16
+ #
17
+ # # Load an existing group based on its internal id
18
+ # group4 = @ether.get_group('g.823lasdlfj98asdfj')
19
+ #
20
+ # Group pad examples:
21
+ #
22
+ # # Create a new pad in this group, optionally specifying its initial text
23
+ # pad1 = group1.create_pad('group 1 pad', :text => 'Words!')
24
+ #
25
+ # # Load (or create, if it doesn't exist) a pad in this group
26
+ # pad2 = group2.pad('group 2 pad')
27
+ #
28
+ # # Load an existing pad from group 2
29
+ # pad3 = group2.get_pad('important pad')
30
+ #
31
+ # Session examples:
32
+ #
33
+ # # Create two hour-long session for an author in group 1
34
+ # author = @ether.author('author_1')
35
+ # session = group1.create_session(author, 60)
36
+ #
37
+ # Understand how ids work. A group pad's id is the group_id + '$' + pad_name:
38
+ #
39
+ # pad2.group_id == group2.id #> true
40
+ #
41
+ # pad2.id == group2.id + '$' + pad2.name #> true
42
+ #
43
+ # pad2 == group2.pad('group 2 pad') == @ether.get_pad("#{group2.id}$group 2 pad") == @ether.get_pad('group 2 pad', :groupID => group2.id) #> true
44
+ #
45
+ # group2.mapper #> "Blurg"
46
+ #
3
47
  class Group
4
48
  GROUP_ID_REGEX = /^g\.[^\$]+/
5
49
  include Padded
6
50
 
7
- attr_reader :id, :instance, :mapper
51
+ # The EtherpadLite::Instance object
52
+ attr_reader :instance
53
+ # The group id
54
+ attr_reader :id
55
+ # An optional identifier used to map the group to something outside Etherpad Lite
56
+ attr_reader :mapper
8
57
 
9
58
  # Creates a new Group. Optionally, you may pass the :mapper option your third party system's group id.
10
59
  # This will allow you to find your Group again later using the same identifier as your foreign system.
@@ -12,7 +61,7 @@ module EtherpadLite
12
61
  #
13
62
  # Options:
14
63
  #
15
- # mapper => your foreign group id
64
+ # mapper => your foreign group id
16
65
  def self.create(instance, options={})
17
66
  result = options[:mapper] \
18
67
  ? instance.client.createGroupIfNotExistsFor(options[:mapper]) \
@@ -24,7 +73,7 @@ module EtherpadLite
24
73
  #
25
74
  # Options:
26
75
  #
27
- # mapper => the foreign id it's mapped to
76
+ # mapper => the foreign id it's mapped to
28
77
  def initialize(instance, id, options={})
29
78
  @instance = instance
30
79
  @id = id
@@ -49,7 +98,7 @@ module EtherpadLite
49
98
  #
50
99
  # Options:
51
100
  #
52
- # text => 'initial Pad text'
101
+ # text => 'initial Pad text'
53
102
  def create_pad(id, options={})
54
103
  options[:groupID] = @id
55
104
  super groupify_pad_id(id), options
@@ -62,7 +111,7 @@ module EtherpadLite
62
111
 
63
112
  # Returns an array of all the Pad ids in this Group.
64
113
  def pad_ids
65
- @instance.client.listPads(@id)[:padIDs].keys
114
+ @instance.client.listPads(@id)[:padIDs]
66
115
  end
67
116
 
68
117
  # Create a new session for author that will last length_in_minutes.
@@ -91,7 +140,7 @@ module EtherpadLite
91
140
 
92
141
  # Prepend the group_id to the pad name
93
142
  def groupify_pad_id(pad_id)
94
- "#{@id}$#{pad_id}"
143
+ pad_id =~ GROUP_ID_REGEX ? pad_id : "#{@id}$#{pad_id}"
95
144
  end
96
145
  end
97
146
  end
@@ -1,43 +1,35 @@
1
1
  module EtherpadLite
2
- # Aliases to common Etherpad Lite hosts
3
- HOST_ALIASES = {:local => 'http://localhost:9001',
4
- :public => 'http://beta.etherpad.org'}
5
-
6
2
  # Returns an EtherpadLite::Instance object.
7
3
  #
8
- # ether1 = EtherpadLite.connect('https://etherpad.yoursite.com[https://etherpad.yoursite.com]', 'your api key')
4
+ # ether1 = EtherpadLite.connect('https://etherpad.yoursite.com[https://etherpad.yoursite.com]', 'your api key')
5
+ #
6
+ # # An alias for http://localhost:9001
7
+ # ether2 = EtherpadLite.connect(:local, File.new('/path/to/APIKEY.txt'))
9
8
  #
10
- # ether2 = EtherpadLite.connect(:local, File.new('/file/path/to/APIKEY.txt'))
9
+ # # An alias for http://localhost:9001
10
+ # ether3 = EtherpadLite.connect(9001, File.new('/path/to/APIKEY.txt'))
11
11
  def self.connect(host_or_alias, api_key_or_file)
12
- # Parse the host
13
- host = if host_or_alias.is_a? Symbol
14
- raise ArgumentError, %Q|Unknown host alias "#{host_or_alias}"| unless HOST_ALIASES.has_key? host_or_alias
15
- HOST_ALIASES[host_or_alias]
16
- else
17
- host_or_alias
18
- end
19
-
20
- # Parse the api key
21
- if api_key_or_file.is_a? File
22
- api_key = api_key_or_file.read
23
- api_key_or_file.close
24
- else
25
- api_key = api_key_or_file
26
- end
27
-
28
- Instance.new(host, api_key)
12
+ Instance.new(host_or_alias, api_key_or_file)
29
13
  end
30
14
 
31
- # An EtherpadLite::Instance provides a hight-level interface to an Etherpad Lite system.
15
+ # EtherpadLite::Instance provides a high-level interface to the EtherpadLite::Client class. See the EtherpadLite module
16
+ # for examples of how to establish a connection.
32
17
  class Instance
33
18
  include Padded
34
- API_ROOT = 'api'
35
-
19
+ # Stores the EtherpadLite::Client object used to power this Instance
36
20
  attr_reader :client
37
21
 
38
22
  # Instantiate a new Etherpad Lite Instance. The url should include the protocol (i.e. http or https).
39
- def initialize(url, api_key)
40
- @client = Client.new(api_key, url + "/#{API_ROOT}")
23
+ #
24
+ # ether1 = EtherpadLite::Instance.new('https://etherpad.yoursite.com[https://etherpad.yoursite.com]', 'your api key')
25
+ #
26
+ # # An alias for http://localhost:9001
27
+ # ether2 = EtherpadLite::Instance.new(:local, File.new('/path/to/APIKEY.txt'))
28
+ #
29
+ # # An alias for http://localhost:9001
30
+ # ether3 = EtherpadLite::Instance.new(9001, File.new('/path/to/APIKEY.txt'))
31
+ def initialize(host_or_alias, api_key_or_file)
32
+ @client = Client.new(host_or_alias, api_key_or_file)
41
33
  end
42
34
 
43
35
  # Returns, creating if necessary, a Group mapped to your foreign system's group
@@ -55,7 +47,7 @@ module EtherpadLite
55
47
  #
56
48
  # Options:
57
49
  #
58
- # mapper => your foreign group id
50
+ # mapper => your foreign group id
59
51
  def create_group(options={})
60
52
  Group.create self, options
61
53
  end
@@ -64,7 +56,7 @@ module EtherpadLite
64
56
  #
65
57
  # Options:
66
58
  #
67
- # name => the Author's name
59
+ # name => the Author's name
68
60
  def author(mapper, options={})
69
61
  options[:mapper] = mapper
70
62
  create_author options
@@ -80,7 +72,7 @@ module EtherpadLite
80
72
  #
81
73
  # Options:
82
74
  #
83
- # mapper => your foreign author id
75
+ # mapper => your foreign author id
84
76
  #
85
77
  # name => the Author's name
86
78
  def create_author(options={})
@@ -92,6 +84,7 @@ module EtherpadLite
92
84
  Session.new self, session_id
93
85
  end
94
86
 
87
+ # Returns itself
95
88
  def instance; self; end
96
89
  end
97
90
  end
@@ -1,15 +1,26 @@
1
1
  module EtherpadLite
2
2
  # An Etherpad Lite Pad
3
+ #
4
+ # This class allows you to interact with pads stored in an Etherpad Lite server. The README
5
+ # has some basic examples.
6
+ #
7
+ # Note that some functions are restricted to Group pads.
8
+ #
3
9
  class Pad
4
- attr_reader :id, :instance, :rev
10
+ # The EtherpadLite::Instance object
11
+ attr_reader :instance
12
+ # The pad id
13
+ attr_reader :id
14
+ # An optional pad revision number
15
+ attr_reader :rev
5
16
 
6
17
  # Creates and returns a new Pad.
7
18
  #
8
19
  # Options:
9
20
  #
10
- # text => 'initial Pad text'
21
+ # text => 'initial Pad text'
11
22
  #
12
- # groupID => group id of Group new Pad should belong to
23
+ # groupID => group id of Group new Pad should belong to
13
24
  def self.create(instance, id, options={})
14
25
  if options[:groupID]
15
26
  group = Group.new instance, options[:groupID]
@@ -18,7 +29,7 @@ module EtherpadLite
18
29
  group = nil
19
30
  instance.client.createPad(id, options[:text])
20
31
  end
21
- new instance, id, :group => group
32
+ new instance, id, :groupID => options[:groupID], :group => group
22
33
  end
23
34
 
24
35
  # Remove the group id portion of a Group Pad's id
@@ -30,12 +41,18 @@ module EtherpadLite
30
41
  #
31
42
  # Options:
32
43
  #
33
- # group
44
+ # groupID => a group id
34
45
  #
35
- # rev
46
+ # group => an EtherpadLite::Group object
47
+ #
48
+ # rev => a pad revision number
36
49
  def initialize(instance, id, options={})
37
50
  @instance = instance
38
51
  @id = id.to_s
52
+ if options[:groupID]
53
+ @group_id = options[:groupID]
54
+ @id = "#{@group_id}$#{@id}" unless @id =~ Group::GROUP_ID_REGEX
55
+ end
39
56
  @group = options[:group]
40
57
  @rev = options[:rev]
41
58
  end
@@ -65,7 +82,7 @@ module EtherpadLite
65
82
  #
66
83
  # Options:
67
84
  #
68
- # rev => revision_number
85
+ # rev => revision_number
69
86
  def text(options={})
70
87
  options[:rev] ||= @rev unless @rev.nil?
71
88
  @instance.client.getText(@id, options[:rev])[:text]
@@ -76,6 +93,21 @@ module EtherpadLite
76
93
  @instance.client.setText(@id, txt)
77
94
  end
78
95
 
96
+ # Returns the Pad's text as HTML. Unless you specified a :rev when instantiating the Pad, or specify one here, this will return the latest revision.
97
+ #
98
+ # Options:
99
+ #
100
+ # rev => revision_number
101
+ def html(options={})
102
+ options[:rev] ||= @rev unless @rev.nil?
103
+ @instance.client.getHTML(@id, options[:rev])[:html]
104
+ end
105
+
106
+ # Writes HTML to the Pad. There is no 'save' method; it is written immediately.
107
+ def html=(html)
108
+ @instance.client.setHTML(@id, html)
109
+ end
110
+
79
111
  # Returns an Array of all this Pad's revision numbers
80
112
  def revision_numbers
81
113
  max = @instance.client.getRevisionsCount(@id)[:revisions]
@@ -5,7 +5,12 @@ module EtherpadLite
5
5
  # Returns the Pad with the given id, creating it if it doesn't already exist.
6
6
  # This requires an HTTP request, so if you *know* the Pad already exists, use Instance#get_pad instead.
7
7
  def pad(id, options={})
8
- Pad.create(instance, id, options) rescue Pad.new(instance, id, options)
8
+ begin
9
+ Pad.create(instance, id, options)
10
+ # Pad alreaded exists
11
+ rescue ArgumentError
12
+ Pad.new(instance, id, options)
13
+ end
9
14
  end
10
15
 
11
16
  # Returns the Pad with the given id (presumed to already exist).
@@ -18,7 +23,7 @@ module EtherpadLite
18
23
  #
19
24
  # Options:
20
25
  #
21
- # text => 'initial Pad text'
26
+ # text => 'initial Pad text'
22
27
  def create_pad(id, options={})
23
28
  Pad.create instance, id, options
24
29
  end
@@ -1,7 +1,17 @@
1
1
  module EtherpadLite
2
- # An Etherpad Lite Session between a Group and an Author
2
+ # An Etherpad Lite Session between a Group and an Author. See those classes for examples of how to create a session.
3
+ #
4
+ # Sessions are useful for embedding an Etherpad Lite Pad into a external application. For public pads, sessions
5
+ # are not necessary. However Group pads require a Session to access to the pad via the Web UI.
6
+ #
7
+ # Generally, you will create the session server side, then pass its id to the embedded pad using a cookie. See the README
8
+ # for an example in a Rails app.
9
+ #
3
10
  class Session
4
- attr_reader :id, :instance
11
+ # The EtherpadLite::Instance object
12
+ attr_reader :instance
13
+ # The session id
14
+ attr_reader :id
5
15
 
6
16
  # Creates a new Session between a Group and an Author. The session will expire after length_in_min.
7
17
  def self.create(instance, group_id, author_id, length_in_min)
data/spec/author_spec.rb CHANGED
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/spec_helper'
2
2
 
3
3
  describe EtherpadLite::Author do
4
4
  before do
5
- @eth = EtherpadLite.connect TEST_CONFIG[:instances][:http][:url], TEST_CONFIG[:instances][:http][:api_key]
5
+ @eth = EtherpadLite.connect TEST_CONFIG[:url], TEST_CONFIG[:api_key_file] || TEST_CONFIG[:api_key]
6
6
  end
7
7
 
8
8
  it "should be created" do
data/spec/config.yml CHANGED
@@ -1,9 +1,4 @@
1
- :instances:
2
- :http:
3
- :url: http://localhost:9003
4
- :api_key: faia3X2dT0u57Du6io44h4WKvePnUltg
5
-
6
- # Uncomment to test https connections
7
- #:https:
8
- # :url: https://localhost:9001
9
- # :api_key: api key
1
+ :url: 9001
2
+ :api_key: #kvwTIROV9p2h2gjNRCrO8fVa6pNXSqOc
3
+ # Full filesystem path to APIKEY.txt, may be used instead of the above :api_key setting
4
+ :api_key_file: /home/jhollinger/devel/etherpad-lite/APIKEY.txt
@@ -1,9 +1,4 @@
1
- :instances:
2
- :http:
3
- :url: http://localhost:9001
4
- :api_key: your api key
5
-
6
- # Uncomment to test https connections
7
- #:https:
8
- # :url: https://localhost:9001
9
- # :api_key: api key
1
+ :url: http://localhost:9001
2
+ :api_key: your api key
3
+ # Full filesystem path to APIKEY.txt, may be used instead of the above :api_key setting
4
+ :api_key_file:
data/spec/group_spec.rb CHANGED
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/spec_helper'
2
2
 
3
3
  describe EtherpadLite::Group do
4
4
  before do
5
- @eth = EtherpadLite.connect TEST_CONFIG[:instances][:http][:url], TEST_CONFIG[:instances][:http][:api_key]
5
+ @eth = EtherpadLite.connect TEST_CONFIG[:url], TEST_CONFIG[:api_key_file] || TEST_CONFIG[:api_key]
6
6
  end
7
7
 
8
8
  it "should be created" do
@@ -28,6 +28,12 @@ describe EtherpadLite::Group do
28
28
  pad.id.should == "#{group.id}$Important Group Stuff"
29
29
  end
30
30
 
31
+ it "should create another Group Pad" do
32
+ group = @eth.group 'Group A'
33
+ pad = @eth.create_pad 'Other Important Group Stuff', :groupID => group.id, :text => 'foo'
34
+ pad.text.should == "foo\n"
35
+ end
36
+
31
37
  it "should create a Group Pad with the right name" do
32
38
  group = @eth.group 'Group A'
33
39
  pad = group.pad 'Important Group Stuff'
@@ -39,14 +45,34 @@ describe EtherpadLite::Group do
39
45
  group.get_pad('Important Group Stuff').group_id.should == group.id
40
46
  end
41
47
 
42
- it "should find a Group Pad with the right id" do
48
+ it "should find another Group Pad with the right group" do
49
+ group = @eth.group 'Group A'
50
+ @eth.get_pad('Other Important Group Stuff', :groupID => group.id).group_id.should == group.id
51
+ end
52
+
53
+ it "should find yet another Group Pad with the right group" do
54
+ group = @eth.group 'Group A'
55
+ @eth.get_pad("Other Important Group Stuff", :groupID => group.id).text.should == "foo\n"
56
+ end
57
+
58
+ it "should find another Group Pad with the right text" do
59
+ group = @eth.group 'Group A'
60
+ @eth.get_pad("#{group.id}$Other Important Group Stuff").text.should == "foo\n"
61
+ end
62
+
63
+ it "should find yet another Group Pad with the right text" do
64
+ group = @eth.group 'Group A'
65
+ @eth.get_pad("#{group.id}$Other Important Group Stuff").text.should == "foo\n"
66
+ end
67
+
68
+ it "should find a Group Pad with the right ids" do
43
69
  group = @eth.group 'Group A'
44
- group.pad_ids.should == [:"#{group.id}$Important Group Stuff"]
70
+ group.pad_ids.should == ["#{group.id}$Important_Group_Stuff", "#{group.id}$Other_Important_Group_Stuff"]
45
71
  end
46
72
 
47
73
  it "should find a Group Pad with the right name" do
48
74
  group = @eth.group 'Group A'
49
- group.pads.first.name.should == "Important Group Stuff"
75
+ group.pads.first.name.should == "Important_Group_Stuff"
50
76
  end
51
77
 
52
78
  it "should explicitly create a Group Pad" do
@@ -2,11 +2,21 @@ require File.dirname(__FILE__) + '/spec_helper'
2
2
 
3
3
  describe EtherpadLite::Instance do
4
4
  before do
5
- @eth = EtherpadLite.connect TEST_CONFIG[:instances][:http][:url], TEST_CONFIG[:instances][:http][:api_key]
5
+ @eth = EtherpadLite.connect TEST_CONFIG[:url], TEST_CONFIG[:api_key_file] || TEST_CONFIG[:api_key]
6
6
  end
7
7
 
8
8
  it "should have the right API key" do
9
- @eth.client.api_key.should == TEST_CONFIG[:instances][:http][:api_key]
9
+ api_key = if TEST_CONFIG[:api_key_file]
10
+ begin
11
+ TEST_CONFIG[:api_key_file].read
12
+ rescue IOError
13
+ TEST_CONFIG[:api_key_file].reopen(TEST_CONFIG[:api_key_file].path, mode='r')
14
+ TEST_CONFIG[:api_key_file].read
15
+ end
16
+ else
17
+ TEST_CONFIG[:api_key]
18
+ end
19
+ @eth.client.api_key.should == api_key
10
20
  end
11
21
 
12
22
  it "shouldn't be secure" do
data/spec/pad_spec.rb CHANGED
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/spec_helper'
2
2
 
3
3
  describe EtherpadLite::Pad do
4
4
  before do
5
- @eth = EtherpadLite.connect TEST_CONFIG[:instances][:http][:url], TEST_CONFIG[:instances][:http][:api_key]
5
+ @eth = EtherpadLite.connect TEST_CONFIG[:url], TEST_CONFIG[:api_key_file] || TEST_CONFIG[:api_key]
6
6
  end
7
7
 
8
8
  it "should blow up when querying a non-existing pad" do
@@ -54,6 +54,12 @@ describe EtherpadLite::Pad do
54
54
  pad.revision_numbers.last == 2
55
55
  end
56
56
 
57
+ it "should set HTML" do
58
+ pad = @eth.get_pad 'another new pad'
59
+ pad.html = "<div><p>Here's some HTML.</p>\n<p>Please rewind it when you're finished.</p></div>"
60
+ pad.html.should == "Here&#x27;s some HTML.<br>Please rewind it when you&#x27;re finished.<br>"
61
+ end
62
+
57
63
  it "should have the first revision" do
58
64
  pad = @eth.get_pad 'another new pad'
59
65
  pad.text(:rev => 1).should == "The initial text\n"
@@ -64,6 +70,11 @@ describe EtherpadLite::Pad do
64
70
  pad.revisions[1].text.should == "The initial text\n"
65
71
  end
66
72
 
73
+ it "should have the first revision as HTML" do
74
+ pad = @eth.get_pad 'another new pad'
75
+ pad.revisions[1].html.should == "The initial text<br>"
76
+ end
77
+
67
78
  it "should have the same name and id" do
68
79
  pad = @eth.get_pad 'another new pad'
69
80
  pad.name.should == pad.id
data/spec/session_spec.rb CHANGED
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/spec_helper'
2
2
 
3
3
  describe EtherpadLite::Session do
4
4
  before do
5
- @eth = EtherpadLite.connect TEST_CONFIG[:instances][:http][:url], TEST_CONFIG[:instances][:http][:api_key]
5
+ @eth = EtherpadLite.connect TEST_CONFIG[:url], TEST_CONFIG[:api_key_file] || TEST_CONFIG[:api_key]
6
6
  end
7
7
 
8
8
  it "should be created for a Group" do
data/spec/spec_helper.rb CHANGED
@@ -1,18 +1,14 @@
1
1
  require 'rspec'
2
2
 
3
3
  # Load etherpad-lite
4
- require File.dirname(__FILE__) + '/../lib/etherpad-lite/client'
5
- require File.dirname(__FILE__) + '/../lib/etherpad-lite/models/padded'
6
- require File.dirname(__FILE__) + '/../lib/etherpad-lite/models/instance'
7
- require File.dirname(__FILE__) + '/../lib/etherpad-lite/models/pad'
8
- require File.dirname(__FILE__) + '/../lib/etherpad-lite/models/group'
9
- require File.dirname(__FILE__) + '/../lib/etherpad-lite/models/author'
10
- require File.dirname(__FILE__) + '/../lib/etherpad-lite/models/session'
4
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/..'
5
+ require 'etherpad-lite'
11
6
 
12
- Rspec.configure do |c|
7
+ RSpec.configure do |c|
13
8
  c.mock_with :rspec
14
9
  end
15
10
 
16
11
  # Load test config
17
12
  require 'yaml'
18
13
  TEST_CONFIG = YAML.load_file(File.dirname(__FILE__) + '/config.yml')
14
+ TEST_CONFIG[:api_key_file] = File.new(TEST_CONFIG[:api_key_file]) unless TEST_CONFIG[:api_key_file].nil?
metadata CHANGED
@@ -1,83 +1,65 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: etherpad-lite
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 4
9
- version: 0.0.4
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.rc2
5
+ prerelease: 6
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Jordan Hollinger
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2011-09-12 00:00:00 -04:00
18
- default_executable:
12
+ date: 2012-06-20 00:00:00.000000000 Z
19
13
  dependencies: []
20
-
21
14
  description: etherpad-lite is a Ruby interface to Etherpad Lite's HTTP JSON API
22
15
  email: jordan@jordanhollinger.com
23
16
  executables: []
24
-
25
17
  extensions: []
26
-
27
- extra_rdoc_files:
18
+ extra_rdoc_files:
28
19
  - README.rdoc
29
- files:
20
+ files:
30
21
  - lib/etherpad-lite.rb
31
- - lib/etherpad-lite/models.rb
32
- - lib/etherpad-lite/models/session.rb
33
22
  - lib/etherpad-lite/models/padded.rb
23
+ - lib/etherpad-lite/models/group.rb
24
+ - lib/etherpad-lite/models/pad.rb
34
25
  - lib/etherpad-lite/models/author.rb
35
26
  - lib/etherpad-lite/models/instance.rb
36
- - lib/etherpad-lite/models/pad.rb
37
- - lib/etherpad-lite/models/group.rb
27
+ - lib/etherpad-lite/models/session.rb
38
28
  - lib/etherpad-lite/client.rb
29
+ - lib/etherpad-lite/models.rb
30
+ - spec/pad_spec.rb
31
+ - spec/config.yml.example
32
+ - spec/config.yml
39
33
  - spec/spec_helper.rb
40
34
  - spec/instance_spec.rb
41
35
  - spec/session_spec.rb
42
- - spec/group_spec.rb
43
- - spec/config.yml
44
- - spec/config.yml.example
45
36
  - spec/author_spec.rb
46
- - spec/pad_spec.rb
37
+ - spec/group_spec.rb
47
38
  - README.rdoc
48
39
  - CHANGELOG
49
40
  - LICENSE
50
- has_rdoc: true
51
41
  homepage: http://github.com/jhollinger/ruby-etherpad-lite
52
42
  licenses: []
53
-
54
43
  post_install_message:
55
44
  rdoc_options: []
56
-
57
- require_paths:
45
+ require_paths:
58
46
  - lib
59
- required_ruby_version: !ruby/object:Gem::Requirement
47
+ required_ruby_version: !ruby/object:Gem::Requirement
60
48
  none: false
61
- requirements:
62
- - - ">="
63
- - !ruby/object:Gem::Version
64
- segments:
65
- - 0
66
- version: "0"
67
- required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
54
  none: false
69
- requirements:
70
- - - ">="
71
- - !ruby/object:Gem::Version
72
- segments:
73
- - 0
74
- version: "0"
55
+ requirements:
56
+ - - ! '>'
57
+ - !ruby/object:Gem::Version
58
+ version: 1.3.1
75
59
  requirements: []
76
-
77
60
  rubyforge_project:
78
- rubygems_version: 1.3.7
61
+ rubygems_version: 1.8.21
79
62
  signing_key:
80
63
  specification_version: 3
81
64
  summary: A Ruby client library for Etherpad Lite
82
65
  test_files: []
83
-