durran-carrierwave 0.3.2.3 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/Generators +1 -1
  2. data/History.txt +39 -2
  3. data/Manifest.txt +19 -5
  4. data/README.rdoc +180 -55
  5. data/Rakefile +11 -4
  6. data/features/grid_fs_storage.feature +32 -0
  7. data/features/step_definitions/general_steps.rb +6 -1
  8. data/features/support/activerecord.rb +1 -1
  9. data/features/support/env.rb +3 -16
  10. data/lib/carrierwave.rb +19 -74
  11. data/lib/carrierwave/compatibility/paperclip.rb +2 -2
  12. data/lib/carrierwave/core_ext/inheritable_attributes.rb +3 -3
  13. data/lib/carrierwave/mount.rb +36 -27
  14. data/lib/carrierwave/orm/activerecord.rb +3 -3
  15. data/lib/carrierwave/orm/datamapper.rb +2 -2
  16. data/lib/carrierwave/orm/mongoid.rb +23 -0
  17. data/lib/carrierwave/orm/mongomapper.rb +1 -1
  18. data/lib/carrierwave/orm/sequel.rb +4 -16
  19. data/lib/carrierwave/processing/image_science.rb +54 -25
  20. data/lib/carrierwave/processing/mini_magick.rb +269 -0
  21. data/lib/carrierwave/processing/rmagick.rb +4 -6
  22. data/lib/carrierwave/sanitized_file.rb +7 -6
  23. data/lib/carrierwave/storage/abstract.rb +0 -2
  24. data/lib/carrierwave/storage/file.rb +3 -5
  25. data/lib/carrierwave/storage/grid_fs.rb +92 -0
  26. data/lib/carrierwave/storage/right_s3.rb +183 -0
  27. data/lib/carrierwave/storage/s3.rb +37 -69
  28. data/lib/carrierwave/test/matchers.rb +22 -8
  29. data/lib/carrierwave/uploader.rb +2 -2
  30. data/lib/carrierwave/uploader/cache.rb +21 -18
  31. data/lib/carrierwave/uploader/configuration.rb +122 -0
  32. data/lib/carrierwave/uploader/default_url.rb +19 -0
  33. data/lib/carrierwave/uploader/processing.rb +4 -2
  34. data/lib/carrierwave/uploader/remove.rb +0 -1
  35. data/lib/carrierwave/uploader/store.rb +1 -68
  36. data/lib/carrierwave/uploader/url.rb +1 -1
  37. data/lib/carrierwave/uploader/versions.rb +3 -4
  38. data/{lib/generators → merb_generators}/uploader_generator.rb +0 -0
  39. data/rails_generators/uploader/templates/uploader.rb +4 -4
  40. data/spec/compatibility/paperclip_spec.rb +11 -2
  41. data/spec/fixtures/landscape.jpg +0 -0
  42. data/spec/fixtures/portrait.jpg +0 -0
  43. data/spec/mount_spec.rb +0 -25
  44. data/spec/orm/datamapper_spec.rb +55 -48
  45. data/spec/orm/mongoid_spec.rb +206 -0
  46. data/spec/orm/mongomapper_spec.rb +19 -1
  47. data/spec/orm/sequel_spec.rb +3 -12
  48. data/spec/processing/image_science_spec.rb +56 -0
  49. data/spec/processing/mini_magick_spec.rb +76 -0
  50. data/spec/processing/rmagick_spec.rb +68 -0
  51. data/spec/sanitized_file_spec.rb +84 -74
  52. data/spec/spec_helper.rb +1 -3
  53. data/spec/storage/grid_fs_spec.rb +78 -0
  54. data/spec/storage/right_s3_spec.rb +75 -0
  55. data/spec/storage/s3_spec.rb +83 -0
  56. data/spec/uploader/cache_spec.rb +1 -13
  57. data/spec/uploader/configuration_spec.rb +105 -0
  58. data/spec/uploader/{default_path_spec.rb → default_url_spec.rb} +22 -5
  59. data/spec/uploader/paths_spec.rb +1 -1
  60. data/spec/uploader/processing_spec.rb +11 -0
  61. data/spec/uploader/store_spec.rb +21 -47
  62. data/spec/uploader/versions_spec.rb +0 -8
  63. metadata +105 -17
  64. data/LICENSE +0 -8
  65. data/carrierwave.gemspec +0 -57
  66. data/lib/carrierwave/uploader/default_path.rb +0 -23
  67. data/lib/carrierwave/uploader/paths.rb +0 -27
data/Generators CHANGED
@@ -1,4 +1,4 @@
1
1
  scope 'merb-gen' do
2
- dir = File.join(File.dirname(__FILE__), 'lib', 'generators/')
2
+ dir = File.join(File.dirname(__FILE__), 'merb_generators/')
3
3
  Merb.add_generators dir + 'uploader_generator'
4
4
  end
@@ -1,5 +1,42 @@
1
- === Version 0.3.2.3 2009-08-28
2
- * Added support for MongoMapper
1
+ === Version 0.4.2 2009-11-26
2
+
3
+ * [added] RightAWS as an alternative S3 implementation
4
+ * [added] An option to enable/disable processing for tests
5
+ * [added] Mongoid ORM support
6
+ * [fixed] DataMapper now works both with and without dm-validations
7
+
8
+ === Version 0.4.1 2009-10-26
9
+
10
+ * [changed] Major changes to the ImageScience module, it actually works now!
11
+ * [fixed] Bug in configuration where it complais that it can't dup Symbol
12
+
13
+ * [removed] Support for Sequel < 2.12
14
+ * [removed] `crop_resized` and `resize` aliases in RMagick, use `resize_to_fill` and `resize_to_fit` respectively
15
+
16
+ === Version 0.4.0 2009-10-12
17
+
18
+ * [changed] the `public` option has been renamed `root` and the old `root` option was removed. No more ambiguity.
19
+ * [changed] Major *breaking* changes to the configuration syntax.
20
+
21
+ * [removed] support for `default_path`
22
+ * [removed] the `cache_to_cache_dir` option
23
+ * [removed] storage no longer calls `setup!` on storage engines
24
+
25
+ * [added] Support for MongoDB's GridFS store
26
+
27
+ === Version 0.3.4 2009-09-01
28
+
29
+ * [added] `default_url` as a replacement for `default_path`
30
+ * [deprecated] `default_path` is deprecated
31
+
32
+ === Version 0.3.4 2009-08-31
33
+
34
+ * [fixed] Deleting no longer causes TypeError in MongoMapper
35
+
36
+ === Version 0.3.3 2009-08-29
37
+
38
+ * [added] Support for MongoMapper
39
+ * [added] Support for CNamed Bucket URLs for Amazon S3
3
40
 
4
41
  === Version 0.3.2 2009-07-18
5
42
 
@@ -3,7 +3,6 @@ History.txt
3
3
  Manifest.txt
4
4
  README.rdoc
5
5
  Rakefile
6
- carrierwave.gemspec
7
6
  cucumber.yml
8
7
  features/caching.feature
9
8
  features/file_storage.feature
@@ -12,6 +11,7 @@ features/file_storage_overridden_store_dir.feature
12
11
  features/file_storage_reversing_processor.feature
13
12
  features/fixtures/bork.txt
14
13
  features/fixtures/monkey.txt
14
+ features/grid_fs_storage.feature
15
15
  features/mount_activerecord.feature
16
16
  features/mount_datamapper.feature
17
17
  features/step_definitions/activerecord_steps.rb
@@ -36,29 +36,33 @@ lib/carrierwave/core_ext/module_setup.rb
36
36
  lib/carrierwave/mount.rb
37
37
  lib/carrierwave/orm/activerecord.rb
38
38
  lib/carrierwave/orm/datamapper.rb
39
+ lib/carrierwave/orm/mongoid.rb
39
40
  lib/carrierwave/orm/mongomapper.rb
40
41
  lib/carrierwave/orm/sequel.rb
41
42
  lib/carrierwave/processing/image_science.rb
43
+ lib/carrierwave/processing/mini_magick.rb
42
44
  lib/carrierwave/processing/rmagick.rb
43
45
  lib/carrierwave/sanitized_file.rb
44
46
  lib/carrierwave/storage/abstract.rb
45
47
  lib/carrierwave/storage/file.rb
48
+ lib/carrierwave/storage/grid_fs.rb
49
+ lib/carrierwave/storage/right_s3.rb
46
50
  lib/carrierwave/storage/s3.rb
47
51
  lib/carrierwave/test/matchers.rb
48
52
  lib/carrierwave/uploader.rb
49
53
  lib/carrierwave/uploader/cache.rb
50
54
  lib/carrierwave/uploader/callbacks.rb
51
- lib/carrierwave/uploader/default_path.rb
55
+ lib/carrierwave/uploader/configuration.rb
56
+ lib/carrierwave/uploader/default_url.rb
52
57
  lib/carrierwave/uploader/extension_whitelist.rb
53
58
  lib/carrierwave/uploader/mountable.rb
54
- lib/carrierwave/uploader/paths.rb
55
59
  lib/carrierwave/uploader/processing.rb
56
60
  lib/carrierwave/uploader/proxy.rb
57
61
  lib/carrierwave/uploader/remove.rb
58
62
  lib/carrierwave/uploader/store.rb
59
63
  lib/carrierwave/uploader/url.rb
60
64
  lib/carrierwave/uploader/versions.rb
61
- lib/generators/uploader_generator.rb
65
+ merb_generators/uploader_generator.rb
62
66
  rails_generators/uploader/USAGE
63
67
  rails_generators/uploader/templates/uploader.rb
64
68
  rails_generators/uploader/uploader_generator.rb
@@ -67,17 +71,27 @@ script/destroy
67
71
  script/generate
68
72
  spec/compatibility/paperclip_spec.rb
69
73
  spec/fixtures/bork.txt
74
+ spec/fixtures/landscape.jpg
75
+ spec/fixtures/portrait.jpg
70
76
  spec/fixtures/test.jpeg
71
77
  spec/fixtures/test.jpg
72
78
  spec/mount_spec.rb
73
79
  spec/orm/activerecord_spec.rb
74
80
  spec/orm/datamapper_spec.rb
81
+ spec/orm/mongoid_spec.rb
75
82
  spec/orm/mongomapper_spec.rb
76
83
  spec/orm/sequel_spec.rb
84
+ spec/processing/image_science_spec.rb
85
+ spec/processing/mini_magick_spec.rb
86
+ spec/processing/rmagick_spec.rb
77
87
  spec/sanitized_file_spec.rb
78
88
  spec/spec_helper.rb
89
+ spec/storage/grid_fs_spec.rb
90
+ spec/storage/right_s3_spec.rb
91
+ spec/storage/s3_spec.rb
79
92
  spec/uploader/cache_spec.rb
80
- spec/uploader/default_path_spec.rb
93
+ spec/uploader/configuration_spec.rb
94
+ spec/uploader/default_url_spec.rb
81
95
  spec/uploader/extension_whitelist_spec.rb
82
96
  spec/uploader/mountable_spec.rb
83
97
  spec/uploader/paths_spec.rb
@@ -9,7 +9,7 @@ upload files.
9
9
 
10
10
  == Description
11
11
 
12
- * RDoc Documentation {available at Rubyforge}[http://carrierwave.rubyforge.org/].
12
+ * RDoc Documentation {available at Rubyforge}[http://carrierwave.rubyforge.org/rdoc].
13
13
  * Source code {hosted at GitHub}[http://github.com/jnicklas/carrierwave]
14
14
  * Please {report any issues}[http://github.com/jnicklas/carrierwave/issues] on GitHub
15
15
  * Please direct any questions at the {mailing list}[http://groups.google.com/group/carrierwave]
@@ -20,12 +20,10 @@ Install the latest stable release:
20
20
 
21
21
  [sudo] gem install carrierwave
22
22
 
23
- Or the cutting edge development version:
24
-
25
- [sudo] gem install jnicklas-carrierwave --source http://gems.github.com
23
+ CarrierWave is hosted *only* on {Gemcutter}[http://gemcutter.org] as of version 0.4.0.
26
24
 
27
25
  In Merb, add it as a dependency to your config/dependencies.rb:
28
-
26
+
29
27
  dependency 'carrierwave'
30
28
 
31
29
  In Rails, add it to your environment.rb:
@@ -56,14 +54,14 @@ should look something like this:
56
54
  You can use your uploader class to store and retrieve files like this:
57
55
 
58
56
  uploader = AvatarUploader.new
59
-
57
+
60
58
  uploader.store!(my_file)
61
-
59
+
62
60
  uploader.retrieve_from_store!('my_file.png')
63
61
 
64
62
  CarrierWave gives you a +store+ for permanent storage, and a +cache+ for
65
63
  temporary storage. You can use different stores, at the moment a filesystem
66
- store and an Amazon S3 store are bundled.
64
+ store, an Amazon S3 store and a store for MongoDB's GridFS are bundled.
67
65
 
68
66
  Most of the time you are going to want to use CarrierWave together with an ORM.
69
67
  It is quite simple to mount uploaders on columns in your model, so you can
@@ -71,33 +69,22 @@ simply assign files and get going:
71
69
 
72
70
  === ActiveRecord, DataMapper, Sequel, MongoMapper
73
71
 
74
- If you are *not* using Merb or Rails you'll need to require the relevant ORM
75
- extension.
72
+ Make sure you are loading CarrierWave after loading your ORM, otherwise you'll
73
+ need to require the relevant extension manually, e.g.:
76
74
 
77
75
  require 'carrierwave/orm/activerecord'
78
- require 'carrierwave/orm/datamapper'
79
- require 'carrierwave/orm/sequel'
80
- require 'carrierwave/orm/mongomapper'
81
76
 
82
- Open your model file, for ActiveRecord do something like:
77
+ Add a string column to the model you want to mount the uploader on:
83
78
 
84
- class User < ActiveRecord::Base
85
- mount_uploader :avatar, AvatarUploader
86
- end
79
+ add_column :user, :avatar, :string
87
80
 
88
- Or for DataMapper:
81
+ Open your model file and mount the uploader:
89
82
 
90
83
  class User
91
- include DataMapper::Resource
92
-
93
84
  mount_uploader :avatar, AvatarUploader
94
85
  end
95
86
 
96
- Or for Sequel
97
-
98
- class User < Sequel::Model
99
- mount_uploader :avatar, AvatarUploader
100
- end
87
+ This works the same with all supported ORMs.
101
88
 
102
89
  Now you can cache files by assigning them to the attribute, they will
103
90
  automatically be stored when the record is saved.
@@ -122,6 +109,18 @@ method:
122
109
 
123
110
  This works for the file storage as well as Amazon S3.
124
111
 
112
+ == Securing uploads
113
+
114
+ Certain file might be dangerous if uploaded to the wrong location, such as php files or other script files. CarrierWave allows you to specify a white-list of allowed extensions.
115
+
116
+ If you're mounting the uploader, uploading a file with the wrong extension will make the record invalid instead. Otherwise, an error is raised.
117
+
118
+ class MyUploader < CarrierWave::Uploader::Base
119
+ def extension_white_list
120
+ %w(jpg jpeg gif png)
121
+ end
122
+ end
123
+
125
124
  == Adding versions
126
125
 
127
126
  Often you'll want to add different versions of the same file. The classic
@@ -130,12 +129,12 @@ example is image thumbnails. There is built in support for this:
130
129
  class MyUploader < CarrierWave::Uploader::Base
131
130
  include CarrierWave::RMagick
132
131
 
133
- process :resize => [800, 800]
132
+ process :resize_to_fit => [800, 800]
134
133
 
135
134
  version :thumb do
136
- process :crop_resized => [200,200]
135
+ process :resize_to_fill => [200,200]
137
136
  end
138
-
137
+
139
138
  end
140
139
 
141
140
  When this uploader is used, an uploaded image would be scaled to be no larger
@@ -144,7 +143,7 @@ and cropped to exactly 200 by 200 pixels. The uploader could be used like this:
144
143
 
145
144
  uploader = AvatarUploader.new
146
145
  uploader.store!(my_file) # size: 1024x768
147
-
146
+
148
147
  uploader.url # => '/url/to/my_file.png' # size: 800x600
149
148
  uploader.thumb.url # => '/url/to/thumb_my_file.png' # size: 200x200
150
149
 
@@ -178,7 +177,7 @@ like this:
178
177
  </p>
179
178
  <% end %>
180
179
 
181
- It might be a good idea to show th user that a file has been uploaded, in the
180
+ It might be a good idea to show the user that a file has been uploaded, in the
182
181
  case of images, a small thumbnail would be a good indicator:
183
182
 
184
183
  <% form_for @user do |f| %>
@@ -190,21 +189,79 @@ case of images, a small thumbnail would be a good indicator:
190
189
  </p>
191
190
  <% end %>
192
191
 
193
- NOTE: this feature currently requires write access to your filesystem. If write
194
- access is unavailable you will not be able to upload files. You can prevent
195
- CarrierWave from writing to the file system by setting
196
- `CarrierWave.config[:cache_to_cache_dir] = false`. This will however break
197
- redisplays of forms.
198
-
199
- == Providing a default path
192
+ == Providing a default URL
200
193
 
201
194
  In many cases, especially when working with images, it might be a good idea to
202
- provide a default path, a fallback in case no file has been uploaded. You can do
203
- this easily by overriding the +default_path+ method in your uploader:
195
+ provide a default url, a fallback in case no file has been uploaded. You can do
196
+ this easily by overriding the +default_url+ method in your uploader:
204
197
 
205
198
  class MyUploader < CarrierWave::Uploader::Base
206
- def default_path
207
- "images/fallback/" + [version_name, "default.png"].compact.join('_')
199
+ def default_url
200
+ "/images/fallback/" + [version_name, "default.png"].compact.join('_')
201
+ end
202
+ end
203
+
204
+ == Configuring CarrierWave
205
+
206
+ CarrierWave has a broad range of configuration options, which you can configure,
207
+ both globally and on a per-uploader basis:
208
+
209
+ CarrierWave.configure do |config|
210
+ config.permissions = 0666
211
+ config.storage = :s3
212
+ end
213
+
214
+ Or alternatively:
215
+
216
+ class AvatarUploader < CarrierWave::Uploader::Base
217
+ permissions 0777
218
+ end
219
+
220
+ == Testing CarrierWave
221
+
222
+ It's a good idea to test you uploaders in isolation. In order to speed up your
223
+ tests, it's recommended to switch off processing in your tests, and to use the
224
+ file storage. In Rails you could do that by adding an initializer with:
225
+
226
+ if Rails.env.test?
227
+ Carrierwave.configure do |config|
228
+ config.storage = :file
229
+ config.enable_processing = false
230
+ end
231
+ end
232
+
233
+ If you need to test your processing, you should test it in isolation, and enable
234
+ processing only for those tests that need it.
235
+
236
+ CarrierWave comes with some RSpec matchers which you may find useful:
237
+
238
+ require 'carrierwave/test/matchers'
239
+
240
+ describe MyUploader do
241
+ before do
242
+ MyUploader.enable_processing = true
243
+ @uploader = MyUploader.new(@user, :avatar)
244
+ @uploader.store!(File.open(path_to_file))
245
+ end
246
+
247
+ after do
248
+ MyUploader.enable_processing = false
249
+ end
250
+
251
+ context 'the thumb version' do
252
+ it "should scale down a landscape image to be exactly 64 by 64 pixels" do
253
+ @uploader.thumb.should have_dimensions(200, 200)
254
+ end
255
+ end
256
+
257
+ context 'the small version' do
258
+ it "should scale down a landscape image to fit within 200 by 200 pixels" do
259
+ @uploader.small.should be_no_larger_than(200, 200)
260
+ end
261
+ end
262
+
263
+ it "should make the image readable only to the owner and not executable" do
264
+ @uploader.should have_premissions(0600)
208
265
  end
209
266
  end
210
267
 
@@ -212,20 +269,59 @@ this easily by overriding the +default_path+ method in your uploader:
212
269
 
213
270
  You'll need to configure a bucket, access id and secret key like this:
214
271
 
215
- CarrierWave.config[:s3][:access_key_id] = 'xxxxxx'
216
- CarrierWave.config[:s3][:secret_access_key] = 'xxxxxx'
217
- CarrierWave.config[:s3][:bucket] = 'name_of_bucket'
272
+ CarrierWave.configure do |config|
273
+ config.s3_access_key_id = 'xxxxxx'
274
+ config.s3_secret_access_key = 'xxxxxx'
275
+ config.s3_bucket = 'name_of_bucket'
276
+ end
218
277
 
219
278
  Do this in an initializer in Rails, and in a +before_app_loads+ block in Merb.
220
279
 
221
280
  And then in your uploader, set the storage to :s3
222
281
 
223
- class AvatarUploader <
282
+ class AvatarUploader < CarrierWave::Uploader::Base
224
283
  storage :s3
225
284
  end
226
285
 
227
286
  That's it! You can still use the +CarrierWave::Uploader#url+ method to return
228
- the url to the file on Amazon S3
287
+ the url to the file on Amazon S3.
288
+
289
+ Alternatively, and especially if your bucket is located in Europe, you can use the
290
+ RightAWS library by setting the storage to :right_s3
291
+
292
+ class AvatarUploader < CarrierWave::Uploader::Base
293
+ storage :right_s3
294
+ end
295
+
296
+ CarrierWave uses the RightAWS S3 Interface directly, meaning that the performance issues
297
+ mentioned by Jonathan Yurek for paperclip do not apply: http://groups.google.com/group/paperclip-plugin/browse_thread/thread/d4dc166a9a5f0df4#
298
+
299
+
300
+ == Using MongoDB's GridFS store
301
+
302
+ You'll need to configure the database and host to use:
303
+
304
+ CarrierWave.configure do |config|
305
+ config.grid_fs_database = 'my_mongo_database'
306
+ config.grid_fs_host = 'mongo.example.com'
307
+ end
308
+
309
+ The defaults are 'carrierwave' and 'localhost'.
310
+
311
+ And then in your uploader, set the storage to +:grid_fs+:
312
+
313
+ class AvatarUploader < CarrierWave::Uploader::Base
314
+ storage :grid_fs
315
+ end
316
+
317
+ Since GridFS doesn't make the files available via HTTP, you'll need to stream
318
+ them yourself. In Rails for example, you could use the +send_data+ method. You
319
+ can tell CarrierWave the URL you will serve your images from, allowing it to
320
+ generate the correct URL, by setting eg:
321
+
322
+ CarrierWave.configure do |config|
323
+ config.grid_fs_access_url = "/image/show"
324
+ end
229
325
 
230
326
  == Using RMagick
231
327
 
@@ -239,16 +335,16 @@ include it in your Uploader:
239
335
  end
240
336
 
241
337
  The RMagick module gives you a few methods, like
242
- +CarrierWave::RMagick#crop_resized+ which manipulate the image file in some way.
243
- You can set a +process+ callback, which will call that method any time a file is
244
- uploaded.
338
+ +CarrierWave::RMagick#resize_to_fill+ which manipulate the image file in some
339
+ way. You can set a +process+ callback, which will call that method any time a
340
+ file is uploaded.
245
341
 
246
342
  class AvatarUploader < CarrierWave::Uploader::Base
247
343
  include CarrierWave::RMagick
248
-
249
- process :crop_resized => [200, 200]
344
+
345
+ process :resize_to_fill => [200, 200]
250
346
  process :convert => 'png'
251
-
347
+
252
348
  def filename
253
349
  super + '.png'
254
350
  end
@@ -263,8 +359,31 @@ ImageScience works the same way as RMagick.
263
359
 
264
360
  class AvatarUploader < CarrierWave::Uploader::Base
265
361
  include CarrierWave::ImageScience
266
-
267
- process :crop_resized => [200, 200]
362
+
363
+ process :resize_to_fill => [200, 200]
364
+ end
365
+
366
+ == Using MiniMagick
367
+
368
+ MiniMagick is similar to RMagick but performs all the operations using the 'mogrify'
369
+ command which is part of the standard ImageMagick kit. This allows you to have the power
370
+ of ImageMagick without having to worry about installing all the RMagick libraries.
371
+
372
+ See the MiniMagick site for more details:
373
+
374
+ http://github.com/probablycorey/mini_magick
375
+
376
+ And the ImageMagick command line options for more for whats on offer:
377
+
378
+ http://www.imagemagick.org/script/command-line-options.php
379
+
380
+ Currently, the MiniMagick carrierwave processor provides exactly the same methods as
381
+ for the RMagick processor.
382
+
383
+ class AvatarUploader < CarrierWave::Uploader::Base
384
+ include CarrierWave::MiniMagick
385
+
386
+ process :resize_to_fill => [200, 200]
268
387
  end
269
388
 
270
389
  == Migrating
@@ -303,6 +422,12 @@ These people have contributed their time and effort to CarrierWave:
303
422
  * Jonas Nicklas
304
423
  * Pavel Kunc
305
424
  * Andrew Timberlake
425
+ * Durran Jordan
426
+ * Scott Motte
427
+ * Sho Fukamachi
428
+ * Sam Lown
429
+ * Dave Ott
430
+ * Quin Hoxie
306
431
 
307
432
  == License
308
433
 
@@ -339,4 +464,4 @@ extensively specced, and there are cucumber features for some common use cases.
339
464
  Just dig in and look at the source for more in-depth explanation of what things
340
465
  are doing.
341
466
 
342
- Issues are reported on GitHub, pull requests are very welcome!
467
+ Issues are reported on GitHub, pull requests are very welcome!