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.
- data/Generators +4 -0
- data/History.txt +125 -0
- data/Manifest.txt +110 -0
- data/README.rdoc +524 -0
- data/Rakefile +39 -0
- data/carrierwave.gemspec +85 -0
- data/cucumber.yml +2 -0
- data/features/caching.feature +28 -0
- data/features/download.feature +20 -0
- data/features/file_storage.feature +37 -0
- data/features/file_storage_overridden_filename.feature +38 -0
- data/features/file_storage_overridden_store_dir.feature +38 -0
- data/features/file_storage_reversing_processor.feature +43 -0
- data/features/fixtures/bork.txt +1 -0
- data/features/fixtures/monkey.txt +1 -0
- data/features/grid_fs_storage.feature +32 -0
- data/features/mount_activerecord.feature +46 -0
- data/features/mount_datamapper.feature +46 -0
- data/features/step_definitions/activerecord_steps.rb +22 -0
- data/features/step_definitions/caching_steps.rb +14 -0
- data/features/step_definitions/datamapper_steps.rb +29 -0
- data/features/step_definitions/download_steps.rb +4 -0
- data/features/step_definitions/file_steps.rb +53 -0
- data/features/step_definitions/general_steps.rb +85 -0
- data/features/step_definitions/mount_steps.rb +19 -0
- data/features/step_definitions/store_steps.rb +18 -0
- data/features/support/activerecord.rb +30 -0
- data/features/support/datamapper.rb +7 -0
- data/features/support/env.rb +22 -0
- data/features/versions_basics.feature +50 -0
- data/features/versions_nested_versions.feature +70 -0
- data/features/versions_overridden_filename.feature +51 -0
- data/features/versions_overriden_store_dir.feature +41 -0
- data/lib/carrierwave.rb +98 -0
- data/lib/carrierwave/compatibility/paperclip.rb +95 -0
- data/lib/carrierwave/core_ext/blank.rb +46 -0
- data/lib/carrierwave/core_ext/file.rb +11 -0
- data/lib/carrierwave/core_ext/inheritable_attributes.rb +108 -0
- data/lib/carrierwave/core_ext/module_setup.rb +51 -0
- data/lib/carrierwave/mount.rb +359 -0
- data/lib/carrierwave/orm/activerecord.rb +73 -0
- data/lib/carrierwave/orm/datamapper.rb +27 -0
- data/lib/carrierwave/orm/mongoid.rb +23 -0
- data/lib/carrierwave/orm/mongomapper.rb +27 -0
- data/lib/carrierwave/orm/sequel.rb +45 -0
- data/lib/carrierwave/processing/image_science.rb +101 -0
- data/lib/carrierwave/processing/mini_magick.rb +265 -0
- data/lib/carrierwave/processing/rmagick.rb +282 -0
- data/lib/carrierwave/sanitized_file.rb +273 -0
- data/lib/carrierwave/storage/abstract.rb +30 -0
- data/lib/carrierwave/storage/cloud_files.rb +169 -0
- data/lib/carrierwave/storage/file.rb +48 -0
- data/lib/carrierwave/storage/grid_fs.rb +97 -0
- data/lib/carrierwave/storage/right_s3.rb +3 -0
- data/lib/carrierwave/storage/s3.rb +206 -0
- data/lib/carrierwave/test/matchers.rb +128 -0
- data/lib/carrierwave/uploader.rb +44 -0
- data/lib/carrierwave/uploader/cache.rb +145 -0
- data/lib/carrierwave/uploader/callbacks.rb +42 -0
- data/lib/carrierwave/uploader/configuration.rb +132 -0
- data/lib/carrierwave/uploader/default_url.rb +19 -0
- data/lib/carrierwave/uploader/download.rb +59 -0
- data/lib/carrierwave/uploader/extension_whitelist.rb +37 -0
- data/lib/carrierwave/uploader/mountable.rb +39 -0
- data/lib/carrierwave/uploader/processing.rb +83 -0
- data/lib/carrierwave/uploader/proxy.rb +62 -0
- data/lib/carrierwave/uploader/remove.rb +22 -0
- data/lib/carrierwave/uploader/store.rb +89 -0
- data/lib/carrierwave/uploader/url.rb +33 -0
- data/lib/carrierwave/uploader/versions.rb +146 -0
- data/merb_generators/uploader_generator.rb +22 -0
- data/rails_generators/uploader/USAGE +2 -0
- data/rails_generators/uploader/templates/uploader.rb +47 -0
- data/rails_generators/uploader/uploader_generator.rb +21 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/compatibility/paperclip_spec.rb +52 -0
- data/spec/fixtures/bork.txt +1 -0
- data/spec/fixtures/landscape.jpg +0 -0
- data/spec/fixtures/portrait.jpg +0 -0
- data/spec/fixtures/test.jpeg +1 -0
- data/spec/fixtures/test.jpg +1 -0
- data/spec/mount_spec.rb +538 -0
- data/spec/orm/activerecord_spec.rb +271 -0
- data/spec/orm/datamapper_spec.rb +168 -0
- data/spec/orm/mongoid_spec.rb +202 -0
- data/spec/orm/mongomapper_spec.rb +202 -0
- data/spec/orm/sequel_spec.rb +183 -0
- data/spec/processing/image_science_spec.rb +56 -0
- data/spec/processing/mini_magick_spec.rb +76 -0
- data/spec/processing/rmagick_spec.rb +75 -0
- data/spec/sanitized_file_spec.rb +623 -0
- data/spec/spec_helper.rb +92 -0
- data/spec/storage/cloudfiles_spec.rb +78 -0
- data/spec/storage/grid_fs_spec.rb +83 -0
- data/spec/storage/s3_spec.rb +118 -0
- data/spec/uploader/cache_spec.rb +209 -0
- data/spec/uploader/configuration_spec.rb +105 -0
- data/spec/uploader/default_url_spec.rb +85 -0
- data/spec/uploader/download_spec.rb +75 -0
- data/spec/uploader/extension_whitelist_spec.rb +44 -0
- data/spec/uploader/mountable_spec.rb +33 -0
- data/spec/uploader/paths_spec.rb +22 -0
- data/spec/uploader/processing_spec.rb +73 -0
- data/spec/uploader/proxy_spec.rb +54 -0
- data/spec/uploader/remove_spec.rb +70 -0
- data/spec/uploader/store_spec.rb +264 -0
- data/spec/uploader/url_spec.rb +102 -0
- data/spec/uploader/versions_spec.rb +298 -0
- 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'
|
data/lib/carrierwave.rb
ADDED
|
@@ -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,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
|