samlown-carrierwave 0.4.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|