samlown-carrierwave 0.4.5

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.
Files changed (111) hide show
  1. data/Generators +4 -0
  2. data/History.txt +125 -0
  3. data/Manifest.txt +110 -0
  4. data/README.rdoc +524 -0
  5. data/Rakefile +39 -0
  6. data/carrierwave.gemspec +85 -0
  7. data/cucumber.yml +2 -0
  8. data/features/caching.feature +28 -0
  9. data/features/download.feature +20 -0
  10. data/features/file_storage.feature +37 -0
  11. data/features/file_storage_overridden_filename.feature +38 -0
  12. data/features/file_storage_overridden_store_dir.feature +38 -0
  13. data/features/file_storage_reversing_processor.feature +43 -0
  14. data/features/fixtures/bork.txt +1 -0
  15. data/features/fixtures/monkey.txt +1 -0
  16. data/features/grid_fs_storage.feature +32 -0
  17. data/features/mount_activerecord.feature +46 -0
  18. data/features/mount_datamapper.feature +46 -0
  19. data/features/step_definitions/activerecord_steps.rb +22 -0
  20. data/features/step_definitions/caching_steps.rb +14 -0
  21. data/features/step_definitions/datamapper_steps.rb +29 -0
  22. data/features/step_definitions/download_steps.rb +4 -0
  23. data/features/step_definitions/file_steps.rb +53 -0
  24. data/features/step_definitions/general_steps.rb +85 -0
  25. data/features/step_definitions/mount_steps.rb +19 -0
  26. data/features/step_definitions/store_steps.rb +18 -0
  27. data/features/support/activerecord.rb +30 -0
  28. data/features/support/datamapper.rb +7 -0
  29. data/features/support/env.rb +22 -0
  30. data/features/versions_basics.feature +50 -0
  31. data/features/versions_nested_versions.feature +70 -0
  32. data/features/versions_overridden_filename.feature +51 -0
  33. data/features/versions_overriden_store_dir.feature +41 -0
  34. data/lib/carrierwave.rb +98 -0
  35. data/lib/carrierwave/compatibility/paperclip.rb +95 -0
  36. data/lib/carrierwave/core_ext/blank.rb +46 -0
  37. data/lib/carrierwave/core_ext/file.rb +11 -0
  38. data/lib/carrierwave/core_ext/inheritable_attributes.rb +108 -0
  39. data/lib/carrierwave/core_ext/module_setup.rb +51 -0
  40. data/lib/carrierwave/mount.rb +359 -0
  41. data/lib/carrierwave/orm/activerecord.rb +73 -0
  42. data/lib/carrierwave/orm/datamapper.rb +27 -0
  43. data/lib/carrierwave/orm/mongoid.rb +23 -0
  44. data/lib/carrierwave/orm/mongomapper.rb +27 -0
  45. data/lib/carrierwave/orm/sequel.rb +45 -0
  46. data/lib/carrierwave/processing/image_science.rb +101 -0
  47. data/lib/carrierwave/processing/mini_magick.rb +265 -0
  48. data/lib/carrierwave/processing/rmagick.rb +282 -0
  49. data/lib/carrierwave/sanitized_file.rb +273 -0
  50. data/lib/carrierwave/storage/abstract.rb +30 -0
  51. data/lib/carrierwave/storage/cloud_files.rb +169 -0
  52. data/lib/carrierwave/storage/file.rb +48 -0
  53. data/lib/carrierwave/storage/grid_fs.rb +97 -0
  54. data/lib/carrierwave/storage/right_s3.rb +3 -0
  55. data/lib/carrierwave/storage/s3.rb +206 -0
  56. data/lib/carrierwave/test/matchers.rb +128 -0
  57. data/lib/carrierwave/uploader.rb +44 -0
  58. data/lib/carrierwave/uploader/cache.rb +145 -0
  59. data/lib/carrierwave/uploader/callbacks.rb +42 -0
  60. data/lib/carrierwave/uploader/configuration.rb +132 -0
  61. data/lib/carrierwave/uploader/default_url.rb +19 -0
  62. data/lib/carrierwave/uploader/download.rb +59 -0
  63. data/lib/carrierwave/uploader/extension_whitelist.rb +37 -0
  64. data/lib/carrierwave/uploader/mountable.rb +39 -0
  65. data/lib/carrierwave/uploader/processing.rb +83 -0
  66. data/lib/carrierwave/uploader/proxy.rb +62 -0
  67. data/lib/carrierwave/uploader/remove.rb +22 -0
  68. data/lib/carrierwave/uploader/store.rb +89 -0
  69. data/lib/carrierwave/uploader/url.rb +33 -0
  70. data/lib/carrierwave/uploader/versions.rb +146 -0
  71. data/merb_generators/uploader_generator.rb +22 -0
  72. data/rails_generators/uploader/USAGE +2 -0
  73. data/rails_generators/uploader/templates/uploader.rb +47 -0
  74. data/rails_generators/uploader/uploader_generator.rb +21 -0
  75. data/script/console +10 -0
  76. data/script/destroy +14 -0
  77. data/script/generate +14 -0
  78. data/spec/compatibility/paperclip_spec.rb +52 -0
  79. data/spec/fixtures/bork.txt +1 -0
  80. data/spec/fixtures/landscape.jpg +0 -0
  81. data/spec/fixtures/portrait.jpg +0 -0
  82. data/spec/fixtures/test.jpeg +1 -0
  83. data/spec/fixtures/test.jpg +1 -0
  84. data/spec/mount_spec.rb +538 -0
  85. data/spec/orm/activerecord_spec.rb +271 -0
  86. data/spec/orm/datamapper_spec.rb +168 -0
  87. data/spec/orm/mongoid_spec.rb +202 -0
  88. data/spec/orm/mongomapper_spec.rb +202 -0
  89. data/spec/orm/sequel_spec.rb +183 -0
  90. data/spec/processing/image_science_spec.rb +56 -0
  91. data/spec/processing/mini_magick_spec.rb +76 -0
  92. data/spec/processing/rmagick_spec.rb +75 -0
  93. data/spec/sanitized_file_spec.rb +623 -0
  94. data/spec/spec_helper.rb +92 -0
  95. data/spec/storage/cloudfiles_spec.rb +78 -0
  96. data/spec/storage/grid_fs_spec.rb +83 -0
  97. data/spec/storage/s3_spec.rb +118 -0
  98. data/spec/uploader/cache_spec.rb +209 -0
  99. data/spec/uploader/configuration_spec.rb +105 -0
  100. data/spec/uploader/default_url_spec.rb +85 -0
  101. data/spec/uploader/download_spec.rb +75 -0
  102. data/spec/uploader/extension_whitelist_spec.rb +44 -0
  103. data/spec/uploader/mountable_spec.rb +33 -0
  104. data/spec/uploader/paths_spec.rb +22 -0
  105. data/spec/uploader/processing_spec.rb +73 -0
  106. data/spec/uploader/proxy_spec.rb +54 -0
  107. data/spec/uploader/remove_spec.rb +70 -0
  108. data/spec/uploader/store_spec.rb +264 -0
  109. data/spec/uploader/url_spec.rb +102 -0
  110. data/spec/uploader/versions_spec.rb +298 -0
  111. metadata +433 -0
@@ -0,0 +1,41 @@
1
+ Feature: uploader with file storage and versions with overridden store dir
2
+ In order to be awesome
3
+ As a developer using CarrierWave
4
+ I want to upload files to the filesystem
5
+
6
+ Background:
7
+ Given an uploader class that uses the 'file' storage
8
+ And that the uploader class has a version named 'thumb'
9
+ And that the version 'thumb' has the store_dir overridden to 'public/monkey/llama'
10
+ And an instance of that class
11
+
12
+ Scenario: store a file
13
+ When I store the file 'fixtures/bork.txt'
14
+ Then there should be a file at 'public/uploads/bork.txt'
15
+ Then there should be a file at 'public/monkey/llama/thumb_bork.txt'
16
+ And the file at 'public/uploads/bork.txt' should be identical to the file at 'fixtures/bork.txt'
17
+ And the file at 'public/monkey/llama/thumb_bork.txt' should be identical to the file at 'fixtures/bork.txt'
18
+
19
+ Scenario: cache a file and then store it
20
+ When I cache the file 'fixtures/bork.txt'
21
+ Then there should be a file called 'bork.txt' somewhere in a subdirectory of 'public/uploads/tmp'
22
+ Then there should be a file called 'thumb_bork.txt' somewhere in a subdirectory of 'public/uploads/tmp'
23
+ And the file called 'bork.txt' in a subdirectory of 'public/uploads/tmp' should be identical to the file at 'fixtures/bork.txt'
24
+ And the file called 'thumb_bork.txt' in a subdirectory of 'public/uploads/tmp' should be identical to the file at 'fixtures/bork.txt'
25
+ And there should not be a file at 'public/uploads/bork.txt'
26
+ And there should not be a file at 'public/monkey/llama/thumb_bork.txt'
27
+ When I store the file
28
+ Then there should be a file at 'public/uploads/bork.txt'
29
+ Then there should be a file at 'public/monkey/llama/thumb_bork.txt'
30
+ And the file at 'public/uploads/bork.txt' should be identical to the file at 'fixtures/bork.txt'
31
+ And the file at 'public/monkey/llama/thumb_bork.txt' should be identical to the file at 'fixtures/bork.txt'
32
+
33
+ Scenario: retrieving a file from cache then storing
34
+ Given the file 'fixtures/bork.txt' is cached file at 'public/uploads/tmp/20090212-2343-8336-0348/bork.txt'
35
+ Given the file 'fixtures/monkey.txt' is cached file at 'public/uploads/tmp/20090212-2343-8336-0348/thumb_bork.txt'
36
+ When I retrieve the cache name '20090212-2343-8336-0348/bork.txt' from the cache
37
+ And I store the file
38
+ Then there should be a file at 'public/uploads/bork.txt'
39
+ Then there should be a file at 'public/monkey/llama/thumb_bork.txt'
40
+ And the file at 'public/uploads/bork.txt' should be identical to the file at 'fixtures/bork.txt'
41
+ And the file at 'public/monkey/llama/thumb_bork.txt' should be identical to the file at 'fixtures/monkey.txt'
@@ -0,0 +1,98 @@
1
+ # encoding: utf-8
2
+
3
+ require 'fileutils'
4
+ require 'carrierwave/core_ext/blank'
5
+ require 'carrierwave/core_ext/module_setup'
6
+ require 'carrierwave/core_ext/inheritable_attributes'
7
+ require 'carrierwave/core_ext/file'
8
+
9
+ module CarrierWave
10
+
11
+ VERSION = "0.4.5"
12
+
13
+ class << self
14
+ attr_accessor :root
15
+
16
+ def configure(&block)
17
+ CarrierWave::Uploader::Base.configure(&block)
18
+ end
19
+
20
+ def clean_cached_files!
21
+ CarrierWave::Uploader::Base.clean_cached_files!
22
+ end
23
+ end
24
+
25
+ class UploadError < StandardError; end
26
+ class IntegrityError < UploadError; end
27
+ class InvalidParameter < UploadError; end
28
+ class ProcessingError < UploadError; end
29
+ class DownloadError < UploadError; end
30
+
31
+ autoload :SanitizedFile, 'carrierwave/sanitized_file'
32
+ autoload :Mount, 'carrierwave/mount'
33
+ autoload :RMagick, 'carrierwave/processing/rmagick'
34
+ autoload :ImageScience, 'carrierwave/processing/image_science'
35
+ autoload :MiniMagick, 'carrierwave/processing/mini_magick'
36
+
37
+ module Storage
38
+ autoload :Abstract, 'carrierwave/storage/abstract'
39
+ autoload :File, 'carrierwave/storage/file'
40
+ autoload :S3, 'carrierwave/storage/s3'
41
+ autoload :GridFS, 'carrierwave/storage/grid_fs'
42
+ autoload :RightS3, 'carrierwave/storage/right_s3'
43
+ autoload :CloudFiles, 'carrierwave/storage/cloud_files'
44
+ end
45
+
46
+ module Uploader
47
+ autoload :Base, 'carrierwave/uploader'
48
+ autoload :Cache, 'carrierwave/uploader/cache'
49
+ autoload :Store, 'carrierwave/uploader/store'
50
+ autoload :Download, 'carrierwave/uploader/download'
51
+ autoload :Callbacks, 'carrierwave/uploader/callbacks'
52
+ autoload :Processing, 'carrierwave/uploader/processing'
53
+ autoload :Versions, 'carrierwave/uploader/versions'
54
+ autoload :Remove, 'carrierwave/uploader/remove'
55
+ autoload :ExtensionWhitelist, 'carrierwave/uploader/extension_whitelist'
56
+ autoload :DefaultUrl, 'carrierwave/uploader/default_url'
57
+ autoload :Proxy, 'carrierwave/uploader/proxy'
58
+ autoload :Url, 'carrierwave/uploader/url'
59
+ autoload :Mountable, 'carrierwave/uploader/mountable'
60
+ autoload :Configuration, 'carrierwave/uploader/configuration'
61
+ end
62
+
63
+ module Compatibility
64
+ autoload :Paperclip, 'carrierwave/compatibility/paperclip'
65
+ end
66
+
67
+ module Test
68
+ autoload :Matchers, 'carrierwave/test/matchers'
69
+ end
70
+
71
+ end
72
+
73
+ if defined?(Merb)
74
+
75
+ CarrierWave.root = Merb.dir_for(:public)
76
+ Merb::BootLoader.before_app_loads do
77
+ # Setup path for uploaders and load all of them before classes are loaded
78
+ Merb.push_path(:uploaders, Merb.root / 'app' / 'uploaders', '*.rb')
79
+ Dir.glob(File.join(Merb.load_paths[:uploaders])).each {|f| require f }
80
+ end
81
+
82
+ elsif defined?(Rails)
83
+
84
+ CarrierWave.root = File.join(Rails.root, 'public')
85
+ ActiveSupport::Dependencies.load_paths << File.join(Rails.root, "app", "uploaders")
86
+
87
+ elsif defined?(Sinatra)
88
+
89
+ CarrierWave.root = Sinatra::Application.public
90
+
91
+ end
92
+
93
+
94
+ require File.join(File.dirname(__FILE__), "carrierwave", "orm", 'activerecord') if defined?(ActiveRecord)
95
+ require File.join(File.dirname(__FILE__), "carrierwave", "orm", 'datamapper') if defined?(DataMapper)
96
+ require File.join(File.dirname(__FILE__), "carrierwave", "orm", 'sequel') if defined?(Sequel)
97
+ require File.join(File.dirname(__FILE__), "carrierwave", "orm", "mongomapper") if defined?(MongoMapper)
98
+ require File.join(File.dirname(__FILE__), "carrierwave", "orm", "mongoid") if defined?(Mongoid)
@@ -0,0 +1,95 @@
1
+ # encoding: utf-8
2
+
3
+ module CarrierWave
4
+ module Compatibility
5
+
6
+ ##
7
+ # Mix this module into an Uploader to make it mimic Paperclip's storage paths
8
+ # This will make your Uploader use the same default storage path as paperclip
9
+ # does. If you need to override it, you can override the +paperclip_path+ method
10
+ # and provide a Paperclip style path:
11
+ #
12
+ # class MyUploader < CarrierWave::Uploader::Base
13
+ # include CarrierWave::Compatibility::Paperclip
14
+ #
15
+ # def paperclip_path
16
+ # ":rails_root/public/uploads/:id/:attachment/:style_:basename.:extension"
17
+ # end
18
+ # end
19
+ #
20
+ # ---
21
+ #
22
+ # This file contains code taken from Paperclip
23
+ #
24
+ # LICENSE
25
+ #
26
+ # The MIT License
27
+ #
28
+ # Copyright (c) 2008 Jon Yurek and thoughtbot, inc.
29
+ #
30
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
31
+ # of this software and associated documentation files (the "Software"), to deal
32
+ # in the Software without restriction, including without limitation the rights
33
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
34
+ # copies of the Software, and to permit persons to whom the Software is
35
+ # furnished to do so, subject to the following conditions:
36
+ #
37
+ # The above copyright notice and this permission notice shall be included in
38
+ # all copies or substantial portions of the Software.
39
+ #
40
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
41
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
42
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
43
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
44
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
45
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
46
+ # THE SOFTWARE.
47
+ #
48
+ module Paperclip
49
+
50
+ def store_path(for_file=filename)
51
+ path = paperclip_path
52
+ path ||= File.join(*[store_dir, paperclip_style.to_s, for_file].compact)
53
+ interpolate_paperclip_path(path, for_file)
54
+ end
55
+
56
+ def store_dir
57
+ ":rails_root/public/system/:attachment/:id"
58
+ end
59
+
60
+ def paperclip_default_style
61
+ :original
62
+ end
63
+
64
+ def paperclip_path
65
+ end
66
+
67
+ def paperclip_style
68
+ version_name || paperclip_default_style
69
+ end
70
+
71
+ private
72
+
73
+ def interpolate_paperclip_path(path, filename)
74
+ mappings.inject(path) do |agg, pair|
75
+ agg.gsub(":#{pair[0]}") { pair[1].call(self, filename).to_s }
76
+ end
77
+ end
78
+
79
+ def mappings
80
+ {
81
+ :rails_root => lambda{|u, f| Rails.root },
82
+ :rails_env => lambda{|u, f| Rails.env },
83
+ :class => lambda{|u, f| u.model.class.name.underscore.pluralize},
84
+ :id => lambda{|u, f| u.model.id },
85
+ :id_partition => lambda{|u, f| ("%09d" % u.model.id).scan(/\d{3}/).join("/")},
86
+ :attachment => lambda{|u, f| u.mounted_as.to_s.downcase.pluralize },
87
+ :style => lambda{|u, f| u.paperclip_style },
88
+ :basename => lambda{|u, f| f.gsub(/#{File.extname(f)}$/, "") },
89
+ :extension => lambda{|u, f| File.extname(f).gsub(/^\.+/, "")}
90
+ }
91
+ end
92
+
93
+ end # Paperclip
94
+ end # Compatibility
95
+ end # CarrierWave
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+
3
+ unless "".respond_to?(:blank?)
4
+ # blank? methods for several different class types
5
+ class Object
6
+ # Returns true if the object is nil or empty (if applicable)
7
+ def blank?
8
+ nil? || (respond_to?(:empty?) && empty?)
9
+ end
10
+ end # class Object
11
+
12
+ class Numeric
13
+ # Numerics can't be blank
14
+ def blank?
15
+ false
16
+ end
17
+ end # class Numeric
18
+
19
+ class NilClass
20
+ # Nils are always blank
21
+ def blank?
22
+ true
23
+ end
24
+ end # class NilClass
25
+
26
+ class TrueClass
27
+ # True is not blank.
28
+ def blank?
29
+ false
30
+ end
31
+ end # class TrueClass
32
+
33
+ class FalseClass
34
+ # False is always blank.
35
+ def blank?
36
+ true
37
+ end
38
+ end # class FalseClass
39
+
40
+ class String
41
+ # Strips out whitespace then tests if the string is empty.
42
+ def blank?
43
+ strip.empty?
44
+ end
45
+ end # class String
46
+ end
@@ -0,0 +1,11 @@
1
+ class File
2
+ def size
3
+ File.size(path)
4
+ end
5
+
6
+ def empty?
7
+ size == 0
8
+ rescue Errno::ENOENT
9
+ false
10
+ end
11
+ end
@@ -0,0 +1,108 @@
1
+ # encoding: utf-8
2
+
3
+ # Stolen from Rails 3
4
+
5
+ # Copyright (c) 2005-2009 David Heinemeier Hansson
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining
8
+ # a copy of this software and associated documentation files (the
9
+ # "Software"), to deal in the Software without restriction, including
10
+ # without limitation the rights to use, copy, modify, merge, publish,
11
+ # distribute, sublicense, and/or sell copies of the Software, and to
12
+ # permit persons to whom the Software is furnished to do so, subject to
13
+ # the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be
16
+ # included in all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+
26
+ # Retain for backward compatibility. Methods are now included in Class.
27
+ class Class
28
+ # Defines class-level inheritable attribute reader. Attributes are available to subclasses,
29
+ # each subclass has a copy of parent's attribute.
30
+ #
31
+ # @param *syms<Array[#to_s]> Array of attributes to define inheritable reader for.
32
+ # @return <Array[#to_s]> Array of attributes converted into inheritable_readers.
33
+ #
34
+ # @api public
35
+ #
36
+ # @todo Do we want to block instance_reader via :instance_reader => false
37
+ # @todo It would be preferable that we do something with a Hash passed in
38
+ # (error out or do the same as other methods above) instead of silently
39
+ # moving on). In particular, this makes the return value of this function
40
+ # less useful.
41
+ def extlib_inheritable_reader(*ivars, &block)
42
+ options = ivars.extract_options!
43
+
44
+ ivars.each do |ivar|
45
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
46
+ def self.#{ivar}
47
+ return @#{ivar} if self.object_id == #{self.object_id} || defined?(@#{ivar})
48
+ ivar = superclass.#{ivar}
49
+ return nil if ivar.nil? && !#{self}.instance_variable_defined?("@#{ivar}")
50
+ @#{ivar} = ivar.duplicable? ? ivar.dup : ivar
51
+ end
52
+ RUBY
53
+ unless options[:instance_reader] == false
54
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
55
+ def #{ivar}
56
+ self.class.#{ivar}
57
+ end
58
+ RUBY
59
+ end
60
+ instance_variable_set(:"@#{ivar}", yield) if block_given?
61
+ end
62
+ end
63
+
64
+ # Defines class-level inheritable attribute writer. Attributes are available to subclasses,
65
+ # each subclass has a copy of parent's attribute.
66
+ #
67
+ # @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to
68
+ # define inheritable writer for.
69
+ # @option syms :instance_writer<Boolean> if true, instance-level inheritable attribute writer is defined.
70
+ # @return <Array[#to_s]> An Array of the attributes that were made into inheritable writers.
71
+ #
72
+ # @api public
73
+ #
74
+ # @todo We need a style for class_eval <<-HEREDOC. I'd like to make it
75
+ # class_eval(<<-RUBY, __FILE__, __LINE__), but we should codify it somewhere.
76
+ def extlib_inheritable_writer(*ivars)
77
+ options = ivars.extract_options!
78
+
79
+ ivars.each do |ivar|
80
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
81
+ def self.#{ivar}=(obj)
82
+ @#{ivar} = obj
83
+ end
84
+ RUBY
85
+ unless options[:instance_writer] == false
86
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
87
+ def #{ivar}=(obj) self.class.#{ivar} = obj end
88
+ RUBY
89
+ end
90
+
91
+ self.send("#{ivar}=", yield) if block_given?
92
+ end
93
+ end
94
+
95
+ # Defines class-level inheritable attribute accessor. Attributes are available to subclasses,
96
+ # each subclass has a copy of parent's attribute.
97
+ #
98
+ # @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to
99
+ # define inheritable accessor for.
100
+ # @option syms :instance_writer<Boolean> if true, instance-level inheritable attribute writer is defined.
101
+ # @return <Array[#to_s]> An Array of attributes turned into inheritable accessors.
102
+ #
103
+ # @api public
104
+ def extlib_inheritable_accessor(*syms, &block)
105
+ extlib_inheritable_reader(*syms)
106
+ extlib_inheritable_writer(*syms, &block)
107
+ end
108
+ end
@@ -0,0 +1,51 @@
1
+ # encoding: utf-8
2
+
3
+ # Stolen from Rails 3
4
+
5
+ # Copyright (c) 2005-2009 David Heinemeier Hansson
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining
8
+ # a copy of this software and associated documentation files (the
9
+ # "Software"), to deal in the Software without restriction, including
10
+ # without limitation the rights to use, copy, modify, merge, publish,
11
+ # distribute, sublicense, and/or sell copies of the Software, and to
12
+ # permit persons to whom the Software is furnished to do so, subject to
13
+ # the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be
16
+ # included in all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+
26
+ class Module
27
+ attr_accessor :_setup_block
28
+ attr_accessor :_dependencies
29
+
30
+ def setup(&blk)
31
+ @_setup_block = blk
32
+ end
33
+
34
+ def use(mod)
35
+ return if self < mod
36
+
37
+ (mod._dependencies || []).each do |dep|
38
+ use dep
39
+ end
40
+ # raise "Circular dependencies" if self < mod
41
+ include mod
42
+ extend mod.const_get("ClassMethods") if mod.const_defined?("ClassMethods")
43
+ class_eval(&mod._setup_block) if mod._setup_block
44
+ end
45
+
46
+ def depends_on(mod)
47
+ return if self < mod
48
+ @_dependencies ||= []
49
+ @_dependencies << mod
50
+ end
51
+ end