etherpad-lite 0.0.4 → 0.1.0.rc2

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/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
-