pax_global_header 0000666 0000000 0000000 00000000064 13222647327 0014522 g ustar 00root root 0000000 0000000 52 comment=9ffd67e4c443d4ab750352ad7470301908f4fdfb
carrierwave-1.2.2/ 0000775 0000000 0000000 00000000000 13222647327 0014036 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/.gitignore 0000664 0000000 0000000 00000000360 13222647327 0016025 0 ustar 00root root 0000000 0000000 doc
.yardoc
.DS_Store
spec/public
pkg
doc
more/activerecord/spec/db
more/activerecord/spec/public
more/datamapper/spec/public
*.project
spec/fixtures/*_copy.png
spec/test.log
spec/tmp
*.swp
.rvmrc
.idea
.bundle
Gemfile.lock
gemfiles/*.lock
carrierwave-1.2.2/.rubocop.yml 0000664 0000000 0000000 00000016604 13222647327 0016317 0 ustar 00root root 0000000 0000000 Style/CollectionMethods:
Description: Preferred collection methods.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#map-find-select-reduce-size
Enabled: true
PreferredMethods:
collect: map
collect!: map!
find: detect
find_all: select
reduce: inject
Style/DotPosition:
Description: Checks the position of the dot in multi-line method calls.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#consistent-multi-line-chains
Enabled: true
EnforcedStyle: trailing
SupportedStyles:
- leading
- trailing
Style/PredicateName:
Description: Check the names of predicate methods.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#bool-methods-qmark
Enabled: true
NamePrefix:
- is_
- has_
- have_
NamePrefixBlacklist:
- is_
Exclude:
- spec/**/*
Style/SingleLineMethods:
Description: Avoid single-line methods.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-single-line-methods
Enabled: true
AllowIfMethodIsEmpty: true
Style/StringLiterals:
Description: Checks if uses of quotes match the configured preference.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#consistent-string-literals
Enabled: true
EnforcedStyle: double_quotes
SupportedStyles:
- single_quotes
- double_quotes
Style/StringLiteralsInInterpolation:
Description: Checks if uses of quotes inside expressions in interpolated strings
match the configured preference.
Enabled: true
EnforcedStyle: single_quotes
SupportedStyles:
- single_quotes
- double_quotes
Metrics/AbcSize:
Description: A calculated magnitude based on number of assignments, branches, and
conditions.
Enabled: false
Max: 15
Metrics/ClassLength:
Description: Avoid classes longer than 100 lines of code.
Enabled: false
CountComments: false
Max: 100
Metrics/ModuleLength:
CountComments: false
Max: 100
Description: Avoid modules longer than 100 lines of code.
Enabled: false
Metrics/CyclomaticComplexity:
Description: A complexity metric that is strongly correlated to the number of test
cases needed to validate a method.
Enabled: false
Max: 6
Metrics/MethodLength:
Description: Avoid methods longer than 10 lines of code.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#short-methods
Enabled: false
CountComments: false
Max: 10
Metrics/ParameterLists:
Description: Avoid parameter lists longer than three or four parameters.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#too-many-params
Enabled: false
Max: 5
CountKeywordArgs: true
Metrics/PerceivedComplexity:
Description: A complexity metric geared towards measuring complexity for a human
reader.
Enabled: false
Max: 7
Lint/AssignmentInCondition:
Description: Don't use assignment in conditions.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#safe-assignment-in-condition
Enabled: false
AllowSafeAssignment: true
Lint/EachWithObjectArgument:
Description: Check for immutable argument given to each_with_object.
Enabled: true
Lint/HandleExceptions:
Description: Don't suppress exception.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#dont-hide-exceptions
Enabled: false
Lint/LiteralInCondition:
Description: Checks of literals used in conditions.
Enabled: false
Lint/LiteralInInterpolation:
Description: Checks for literals used in interpolation.
Enabled: false
Style/InlineComment:
Description: Avoid inline comments.
Enabled: false
Style/AccessorMethodName:
Description: Check the naming of accessor methods for get_/set_.
Enabled: false
Style/Alias:
Description: Use alias_method instead of alias.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#alias-method
Enabled: false
Style/Documentation:
Description: Document classes and non-namespace modules.
Enabled: false
Style/DoubleNegation:
Description: Checks for uses of double negation (!!).
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-bang-bang
Enabled: false
Style/EachWithObject:
Description: Prefer `each_with_object` over `inject` or `reduce`.
Enabled: false
Style/EmptyLiteral:
Description: Prefer literals to Array.new/Hash.new/String.new.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#literal-array-hash
Enabled: false
Style/ModuleFunction:
Description: Checks for usage of `extend self` in modules.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#module-function
Enabled: false
Style/OneLineConditional:
Description: Favor the ternary operator(?:) over if/then/else/end constructs.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#ternary-operator
Enabled: false
Style/PerlBackrefs:
Description: Avoid Perl-style regex back references.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-perl-regexp-last-matchers
Enabled: false
Style/Send:
Description: Prefer `Object#__send__` or `Object#public_send` to `send`, as `send`
may overlap with existing methods.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#prefer-public-send
Enabled: false
Style/SpecialGlobalVars:
Description: Avoid Perl-style global variables.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-cryptic-perlisms
Enabled: false
Style/VariableInterpolation:
Description: Don't interpolate global, instance and class variables directly in
strings.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#curlies-interpolate
Enabled: false
Style/WhenThen:
Description: Use when x then ... for one-line cases.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#one-line-cases
Enabled: false
Style/RaiseArgs:
Description: Checks the arguments passed to raise/fail.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#exception-class-messages
Enabled: false
EnforcedStyle: exploded
SupportedStyles:
- compact
- exploded
Style/SignalException:
Description: Checks for proper usage of fail and raise.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#fail-method
Enabled: false
EnforcedStyle: semantic
SupportedStyles:
- only_raise
- only_fail
- semantic
Style/SingleLineBlockParams:
Description: Enforces the names of some block params.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#reduce-blocks
Enabled: false
Methods:
- reduce:
- a
- e
- inject:
- a
- e
Style/GuardClause:
Description: Check for conditionals that can be replaced with guard clauses
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals
Enabled: false
MinBodyLength: 1
Style/IfUnlessModifier:
Description: Favor modifier if/unless usage when you have a single-line body.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#if-as-a-modifier
Enabled: false
MaxLineLength: 80
Style/OptionHash:
Description: Don't use option hashes when you can use keyword arguments.
Enabled: false
Style/PercentLiteralDelimiters:
Description: Use `%`-literal delimiters consistently
StyleGuide: https://github.com/bbatsov/ruby-style-guide#percent-literal-braces
Enabled: false
PreferredDelimiters:
"%": "()"
"%i": "()"
"%q": "()"
"%Q": "()"
"%r": "{}"
"%s": "()"
"%w": "()"
"%W": "()"
"%x": "()"
Style/TrailingComma:
Description: Checks for trailing comma in parameter lists and literals.
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas
Enabled: false
EnforcedStyleForMultiline: no_comma
SupportedStyles:
- comma
- no_comma
carrierwave-1.2.2/.travis.yml 0000664 0000000 0000000 00000003254 13222647327 0016153 0 ustar 00root root 0000000 0000000 language: ruby
cache: bundler
rvm:
- 2.2.7
- 2.3.4
- 2.4.1
- jruby-9.1.5.0
gemfile:
- gemfiles/rails-4-0.gemfile
- gemfiles/rails-4-1.gemfile
- gemfiles/rails-4-2.gemfile
- gemfiles/rails-5-0.gemfile
- gemfiles/rails-5-1.gemfile
- gemfiles/rails-master.gemfile
sudo: false
before_install:
#- gem update bundler
before_script:
- psql -c 'create database carrierwave_test;' -U postgres
matrix:
include:
- rvm: 2.0
gemfile: gemfiles/rails-4-0.gemfile
- rvm: 2.0
gemfile: gemfiles/rails-4-1.gemfile
- rvm: 2.0
gemfile: gemfiles/rails-4-2.gemfile
- rvm: 2.1
gemfile: gemfiles/rails-4-0.gemfile
- rvm: 2.1
gemfile: gemfiles/rails-4-1.gemfile
- rvm: 2.1
gemfile: gemfiles/rails-4-2.gemfile
- rvm: ruby-head
gemfile: gemfiles/rails-5-1.gemfile
- rvm: ruby-head
gemfile: gemfiles/rails-master.gemfile
- rvm: jruby-head
gemfile: gemfiles/rails-5-1.gemfile
- rvm: jruby-head
gemfile: gemfiles/rails-master.gemfile
exclude:
- rvm: 2.4.1
gemfile: gemfiles/rails-4-0.gemfile
- rvm: 2.4.1
gemfile: gemfiles/rails-4-1.gemfile
- rvm: 2.4.1
gemfile: gemfiles/rails-4-2.gemfile
allow_failures:
- rvm: ruby-head
- rvm: jruby-head
- gemfile: gemfiles/rails-master.gemfile
- rvm: jruby-9.1.5.0
gemfile: gemfiles/rails-5-1.gemfile
fast_finish: true
notifications:
email: false
slack:
secure: Npzanyv/LXLIRlrNs8iTUbZNRhXlP+K2ZpjZoS2UKkr09jYyP1qdf5a//R3Lu7Yat7g2b4qTJGbaZBEMUQSVaJ6UX6quiBJjVWxjxjQ4Ugk8k/yOIAcGEGYPfS6YzRXemRwo9j4uy76cmwlv8cwEuYTSTBRK4XrdYHslX6pKSXM=
addons:
postgresql: "9.3"
apt:
packages:
- ghostscript
carrierwave-1.2.2/CHANGELOG.md 0000664 0000000 0000000 00000027240 13222647327 0015654 0 ustar 00root root 0000000 0000000 # Carrierwave History/Changelog
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
## 1.2.2 - 2018-01-02
### Fixed
* Reset Content-Type on converting file format(@kyoshidajp [#2237](https://github.com/carrierwaveuploader/carrierwave/pull/2237))
## 1.2.1 - 2017-10-04
### Fixed
* Locale check breaks when a Symbol is given to available_locales(@mshibuya [#2234](https://github.com/carrierwaveuploader/carrierwave/issues/2234))
## 1.2.0 - 2017-09-30
### Added
* Added Proc Support for Width and Height(@tomprats [#2169](https://github.com/carrierwaveuploader/carrierwave/pull/2169))
### Changed
* Decode unicode filenames from URL(@fedorkk [#2131](https://github.com/carrierwaveuploader/carrierwave/pull/2131))
* Change file size of error message to human size(@aki77 [#2199](https://github.com/carrierwaveuploader/carrierwave/pull/2199))
### Fixed
* Bundled en translation was not loaded by default, causing translation missing(@mshibuya [95ce39d3](https://github.com/carrierwaveuploader/carrierwave/commit/95ce39d3ec98bee9b2846b32fdcf093c78fa44fb))
* Remove potentially redundant HEAD request on checking fog file existence(@eritiro [#2140](https://github.com/carrierwaveuploader/carrierwave/pull/2140))
* Failing with uninitialized constant if uri is not loaded(@jasdeepsingh [#2223](https://github.com/carrierwaveuploader/carrierwave/pull/2223))
* RMagick cloud not process remotely stored files(@zog [#2185](https://github.com/carrierwaveuploader/carrierwave/pull/2185))
* Check if files are identical via FS rather than name before move(@riffraff [#2191](https://github.com/carrierwaveuploader/carrierwave/pull/2191))
* Regexp `extension_whitelist` is also case-insensitive now(@vmdhoke [#2201](https://github.com/carrierwaveuploader/carrierwave/pull/2201))
* Use `__send__` instead of `send` (@dminuoso [#2178](https://github.com/carrierwaveuploader/carrierwave/pull/2178))
## 1.1.0 - 2017-04-30
### Added
* Rails 5.1 compatibility(@paulsturgess [#2130](https://github.com/carrierwaveuploader/carrierwave/pull/2130), [#2133](https://github.com/carrierwaveuploader/carrierwave/pull/2133))
* Support for `process` callback(@cfcosta [#2045](https://github.com/carrierwaveuploader/carrierwave/pull/2045))
* S3 Transfer Acceleration support(@krekoten [#2108](https://github.com/carrierwaveuploader/carrierwave/pull/2108))
* Allow non-argument options to be passed in mini magick combine_options(@krismartin [#2097](https://github.com/carrierwaveuploader/carrierwave/pull/2097))
### Fixed
* Stop falling back to en locale when I18n is missing(@kryzhovnik [#2083](https://github.com/carrierwaveuploader/carrierwave/pull/2083))
* Allow nagative timestamp in cache id(@NickOttrando [#2092](https://github.com/carrierwaveuploader/carrierwave/pull/2092))
* Avoid calling `file.url` twice(@lukeasrodgers [#2078](https://github.com/carrierwaveuploader/carrierwave/pull/2078))
* Content Type being reset when moving cached file(@dweinand [#2117](https://github.com/carrierwaveuploader/carrierwave/pull/2117))
## 1.0.0 - 2016-12-24
_No changes._
## 1.0.0.rc - 2016-10-30
### Added
* Ability to set custom request headers on downloading remote URL(@mendab1e [#2006](https://github.com/carrierwaveuploader/carrierwave/pull/2006))
### Changed
* Re-enable `public_url` optimization for Google Cloud Storage(@nikz [#2039](https://github.com/carrierwaveuploader/carrierwave/pull/2039))
### Fixed
* Fix `clean_cache!` deleting unexpired files due to RegExp mismatch(@t-oginogin [#2036](https://github.com/carrierwaveuploader/carrierwave/pull/2036))
## 1.0.0.beta - 2016-09-08
### Added
* Rails 5 support (@mshibuya)
* Add `#width` and `#height` methods to the RMagick processor (@mehlah [#1805](https://github.com/carrierwaveuploader/carrierwave/pull/1805))
* Add a test matcher for the format (@yanivpr [#1758](https://github.com/carrierwaveuploader/carrierwave/pull/1758))
* Support of MiniMagick's Combine options (@bernabas [#1754](https://github.com/carrierwaveuploader/carrierwave/pull/1754))
* Validate with the actual content-type of files (@eavgerinos)
* Support for multiple file uploads with `mount_uploaders` method (@jnicklas and @lisarutan [#1481](https://github.com/carrierwaveuploader/carrierwave/pull/1481))
* Add a `cache_only` configuration option, useful for testing (@jeffkreeftmeijer [#1456](https://github.com/carrierwaveuploader/carrierwave/pull/1456))
* Add `#width` and `#height` methods to MiniMagick processor (@ShivaVS [#1405](https://github.com/carrierwaveuploader/carrierwave/pull/1405))
* Support for jRuby (@lephyrius [#1377](https://github.com/carrierwaveuploader/carrierwave/pull/1377))
* Make cache storage configurable (@mshibuya [#1312](https://github.com/carrierwaveuploader/carrierwave/pull/1312))
* Errors on file size (@gautampunhani [#1026](https://github.com/carrierwaveuploader/carrierwave/pull/1026))
### Changed
* Blank uploaders are now memoized on the model instance (@DarthSim [#1860](https://github.com/carrierwaveuploader/carrierwave/pull/1860))
* `#content_type_whitelist` and `extension_whitelist` now takes either a string, a regexp, or an array of values (same thing for blacklists) (@mehlah [#1825](https://github.com/carrierwaveuploader/carrierwave/pull/1825))
* [BREAKING CHANGE] Rename `extension_white_list` ~> `extension_whitelist` (@mehlah [#1819](https://github.com/carrierwaveuploader/carrierwave/pull/1819))
* [BREAKING CHANGE] Rename `extension_black_list` ~> `extension_blacklist` (@mehlah [#1819](https://github.com/carrierwaveuploader/carrierwave/pull/1819))
* [BREAKING CHANGE] Rename i18n keys `extension_black_list_error` ~> `extension_blacklist_error` and `extension_white_list_error` ~> `extension_whitelist_error` (@mehlah)
* Accept an array of strings or regexps to white/blacklist content types (@mehlah [#1816](https://github.com/carrierwaveuploader/carrierwave/pull/1816))
* Add counter to cache_id (@thomasfedb [#1797](https://github.com/carrierwaveuploader/carrierwave/pull/1797))
* [BREAKING CHANGE] Allow non-ASCII filename by default (@shuhei [#1772](https://github.com/carrierwaveuploader/carrierwave/pull/1772))
* [BREAKING CHANGE] `to_json` behavior changed when serializing an uploader (@jnicklas and @lisarutan [#1481](https://github.com/carrierwaveuploader/carrierwave/pull/1481))
* Better error when the configured storage is unknown (@st0012 [#1779](https://github.com/carrierwaveuploader/carrierwave/pull/1779))
* Allow to pass additionnal options to Rackspace `authenticated_url` (@duhast [#1722](https://github.com/carrierwaveuploader/carrierwave/pull/1722))
* Reduced memory footprint (@schneems [#1652](https://github.com/carrierwaveuploader/carrierwave/pull/1652), @simonprev [#1706](https://github.com/carrierwaveuploader/carrierwave/pull/1706))
* Improve Fog Loading (@plribeiro3000 [#1620](https://github.com/carrierwaveuploader/carrierwave/pull/1620), @eavgerinos)
* All locales from `config.i18n.available_locales` are added to load_path (@printercu [#1521](https://github.com/carrierwaveuploader/carrierwave/pull/1521))
* Do not display RMagick exception in I18n message (manuelpradal [#1361](https://github.com/carrierwaveuploader/carrierwave/pull/1361))
* [BREAKING CHANGE] `#default_url` now accepts the same args passed to `#url` (@shekibobo [#1347](https://github.com/carrierwaveuploader/carrierwave/pull/1347))
### Removed
* All locale files other than `en` are now in [carrierwave-i18n](https://github.com/carrierwaveuploader/carrierwave-i18n) (@mehlah [#1848](https://github.com/carrierwaveuploader/carrierwave/pull/1848))
* Remove `CarrierWave::MagicMimeTypes` processor module (@mehlah [#1816](https://github.com/carrierwaveuploader/carrierwave/pull/1816))
* Remove dependency on `ruby-filemagic` in white/blacklist content types (@mehlah [#1816](https://github.com/carrierwaveuploader/carrierwave/pull/1816))
* Remove `CarrierWave::MimeTypes` processor module (@mehlah [#1813](https://github.com/carrierwaveuploader/carrierwave/pull/1813))
* Remove support for Rails 3.2 and Ruby 1.8/1.9 (@bensie [2517d668](https://github.com/carrierwaveuploader/carrierwave/commit/2517d66809472fca9b1d5638eeeb515b351a8602))
### Fixed
* Don't raise an error when content_type is called on a deleted file (@jvenezia [#1915](https://github.com/carrierwaveuploader/carrierwave/pull/1915))
* #remove_previous fails to detect equality when mount_on option is set (@mshibuya [44cfb7c0](https://github.com/carrierwaveuploader/carrierwave/commit/44cfb7c01c22e0168d362001a7bb3c528c805315))
* Fix `Mounter.blank?` method (@Bonias [#1746](https://github.com/carrierwaveuploader/carrierwave/pull/1746))
* Reset `remove_#{column}` after invoking `remove_#{column}` (@eavgerinos [#1668](https://github.com/carrierwaveuploader/carrierwave/pull/1668))
* Change Google's url to the `public_url` (@m7moud [#1683](https://github.com/carrierwaveuploader/carrierwave/pull/1683))
* Do not write to `ActiveModel::Dirty` changes when assigning something blank to a mounter that was originally blank (@eavgerinos [#1635](https://github.com/carrierwaveuploader/carrierwave/pull/1635))
* Various grammar and typos fixes to error messages translations
* Don't error when size is called on a deleted file (@danielevans [#1561](https://github.com/carrierwaveuploader/carrierwave/pull/1561))
* Flush mounters on `#dup` of active record model (@danielevans [#1544](https://github.com/carrierwaveuploader/carrierwave/pull/1544))
* `Fog::File.read` returns its contents after upload instead of "closed stream" error (@stormsilver [#1517](https://github.com/carrierwaveuploader/carrierwave/pull/1517))
* Don't read file twice when calling `sanitized_file` or `cache!` (@felixbuenemann [#1476](https://github.com/carrierwaveuploader/carrierwave/pull/1476))
* Change image extension when converting formats (@nashby [#1446](https://github.com/carrierwaveuploader/carrierwave/pull/1446))
* Fix file delete being called twice on remove (@adamcrown [#1441](https://github.com/carrierwaveuploader/carrierwave/pull/1441))
* RSpec 3 support (@randoum #1421[](https://github.com/carrierwaveuploader/carrierwave/pull/1421), @akiomik [#1370](https://github.com/carrierwaveuploader/carrierwave/pull/1370))
* MiniMagick convert to a format all the pages by default and accept an optional page number parameter to convert specific pages (@harikrishnan83 [#1408](https://github.com/carrierwaveuploader/carrierwave/pull/1408))
* Fix cache workfile collision between versions (@jvdp [#1399](https://github.com/carrierwaveuploader/carrierwave/pull/1399))
* Reset mounter cache on record reload (@semenyukdmitriy [#1383](https://github.com/carrierwaveuploader/carrierwave/pull/1383))
* Retrieve only active versions of files (@filipegiusti [#1351](https://github.com/carrierwaveuploader/carrierwave/pull/1351))
* Fix default gravity in MiniMagick `resize_and_pad` (@abevoelker [#1358](https://github.com/carrierwaveuploader/carrierwave/pull/1358))
* Skip loading RMagick if already loaded (@mshibuya [#1346](https://github.com/carrierwaveuploader/carrierwave/pull/1346))
* Make the `#remove_#{column}` accessor set the mounted column as changed (@nikz [#1326](https://github.com/carrierwaveuploader/carrierwave/pull/1326))
* Tempfile and @content_type assignment (@bensie [#1487](https://github.com/carrierwaveuploader/carrierwave/issues/1487))
## 0.11.0 - 2016-03-29
### Added
### Changed
* `cache_id` is now less collision-prone thanks to a counter (@stillwaiting and @mtsmfm [#1866](https://github.com/carrierwaveuploader/carrierwave/pull/1866))
### Removed
### Fixed
* Fix require RMagick deprecation warning (@thomasfedb and @bensie [#1788](https://github.com/carrierwaveuploader/carrierwave/pull/1788))
## 0.10.0 - 2014-02-26
Please check [0.10-stable] for previous changes.
[0.10-stable]: https://github.com/carrierwaveuploader/carrierwave/blob/0.10-stable/History.txt
carrierwave-1.2.2/CONTRIBUTING.md 0000664 0000000 0000000 00000002204 13222647327 0016265 0 ustar 00root root 0000000 0000000 # Contributing to CarrierWave
CarrierWave thrives on a large number of [contributors](https://github.com/carrierwaveuploader/carrierwave/contributors),
and pull requests are very welcome. Before submitting a pull request, please make sure that your changes are well tested.
First, make sure you have `imagemagick` and `ghostscript` installed. You may need `libmagic` as well.
Then, you'll need to install bundler and the gem dependencies:
`gem install bundler && bundle install`
You should now be able to run the local tests:
`bundle exec rake`
You can also run the remote specs by creating a ~/.fog file:
```yaml
:carrierwave:
:aws_access_key_id: xxx
:aws_secret_access_key: yyy
:rackspace_username: xxx
:rackspace_api_key: yyy
:google_storage_access_key_id: xxx
:google_storage_secret_access_key: yyy
```
You should now be able to run the remote tests:
REMOTE=true bundle exec rake
Please test with the latest Ruby 2.2.x version using RVM if possible.
## Running active record tests
Make sure you have a local PostgreSQL database named `carrierwave_test` with the username
`postgres`
carrierwave-1.2.2/Gemfile 0000664 0000000 0000000 00000000112 13222647327 0015323 0 ustar 00root root 0000000 0000000 source "https://rubygems.org"
gem "activemodel-serializers-xml"
gemspec
carrierwave-1.2.2/README.md 0000664 0000000 0000000 00000074760 13222647327 0015333 0 ustar 00root root 0000000 0000000 # CarrierWave
This gem provides a simple and extremely flexible way to upload files from Ruby applications.
It works well with Rack based web applications, such as Ruby on Rails.
[](http://travis-ci.org/carrierwaveuploader/carrierwave)
[](https://codeclimate.com/github/carrierwaveuploader/carrierwave)
[](https://git.legal/projects/1363)
## Information
* RDoc documentation [available on RubyDoc.info](http://rubydoc.info/gems/carrierwave/frames)
* Source code [available on GitHub](http://github.com/carrierwaveuploader/carrierwave)
* More information, known limitations, and how-tos [available on the wiki](https://github.com/carrierwaveuploader/carrierwave/wiki)
## Getting Help
* Please ask the community on [Stack Overflow](https://stackoverflow.com/questions/tagged/carrierwave) for help if you have any questions. Please do not post usage questions on the issue tracker.
* Please report bugs on the [issue tracker](http://github.com/carrierwaveuploader/carrierwave/issues) but read the "getting help" section in the wiki first.
## Installation
Install the latest release:
```
$ gem install carrierwave -v "1.0.0"
```
In Rails, add it to your Gemfile:
```ruby
gem 'carrierwave', '~> 1.0'
```
Finally, restart the server to apply the changes.
As of version 1.0, CarrierWave requires Rails 4.0 or higher and Ruby 2.0
or higher. If you're on Rails 3, you should use v0.11.0.
## Getting Started
Start off by generating an uploader:
rails generate uploader Avatar
this should give you a file in:
app/uploaders/avatar_uploader.rb
Check out this file for some hints on how you can customize your uploader. It
should look something like this:
```ruby
class AvatarUploader < CarrierWave::Uploader::Base
storage :file
end
```
You can use your uploader class to store and retrieve files like this:
```ruby
uploader = AvatarUploader.new
uploader.store!(my_file)
uploader.retrieve_from_store!('my_file.png')
```
CarrierWave gives you a `store` for permanent storage, and a `cache` for
temporary storage. You can use different stores, including filesystem
and cloud storage.
Most of the time you are going to want to use CarrierWave together with an ORM.
It is quite simple to mount uploaders on columns in your model, so you can
simply assign files and get going:
### ActiveRecord
Make sure you are loading CarrierWave after loading your ORM, otherwise you'll
need to require the relevant extension manually, e.g.:
```ruby
require 'carrierwave/orm/activerecord'
```
Add a string column to the model you want to mount the uploader by creating
a migration:
rails g migration add_avatar_to_users avatar:string
rake db:migrate
Open your model file and mount the uploader:
```ruby
class User < ActiveRecord::Base
mount_uploader :avatar, AvatarUploader
end
```
Now you can cache files by assigning them to the attribute, they will
automatically be stored when the record is saved.
```ruby
u = User.new
u.avatar = params[:file] # Assign a file like this, or
# like this
File.open('somewhere') do |f|
u.avatar = f
end
u.save!
u.avatar.url # => '/url/to/file.png'
u.avatar.current_path # => 'path/to/file.png'
u.avatar_identifier # => 'file.png'
```
**Note**: `u.avatar` will never return nil, even if there is no photo associated to it.
To check if a photo was saved to the model, use `u.avatar.file.nil?` instead.
### DataMapper, Mongoid, Sequel
Other ORM support has been extracted into separate gems:
* [carrierwave-datamapper](https://github.com/carrierwaveuploader/carrierwave-datamapper)
* [carrierwave-mongoid](https://github.com/carrierwaveuploader/carrierwave-mongoid)
* [carrierwave-sequel](https://github.com/carrierwaveuploader/carrierwave-sequel)
There are more extensions listed in [the wiki](https://github.com/carrierwaveuploader/carrierwave/wiki)
## Multiple file uploads
CarrierWave also has convenient support for multiple file upload fields.
### ActiveRecord
Add a column which can store an array. This could be an array column or a JSON
column for example. Your choice depends on what your database supports. For
example, create a migration like this:
#### For databases with ActiveRecord json data type support (e.g. PostgreSQL, MySQL)
rails g migration add_avatars_to_users avatars:json
rake db:migrate
#### For database without ActiveRecord json data type support (e.g. SQLite)
rails g migration add_avatars_to_users avatars:string
rake db:migrate
__Note__: JSON datatype doesn't exists in SQLite adapter, that's why you can use a string datatype which will be serialized in model.
Open your model file and mount the uploader:
```ruby
class User < ActiveRecord::Base
mount_uploaders :avatars, AvatarUploader
serialize :avatars, JSON # If you use SQLite, add this line.
end
```
Make sure your file input fields are set up as multiple file fields. For
example in Rails you'll want to do something like this:
```erb
<%= form.file_field :avatars, multiple: true %>
```
Also, make sure your upload controller permits the multiple file upload attribute, *pointing to an empty array in a hash*. For example:
```ruby
params.require(:user).permit(:email, :first_name, :last_name, {avatars: []})
```
Now you can select multiple files in the upload dialog (e.g. SHIFT+SELECT), and they will
automatically be stored when the record is saved.
```ruby
u = User.new(params[:user])
u.save!
u.avatars[0].url # => '/url/to/file.png'
u.avatars[0].current_path # => 'path/to/file.png'
u.avatars[0].identifier # => 'file.png'
```
## Changing the storage directory
In order to change where uploaded files are put, just override the `store_dir`
method:
```ruby
class MyUploader < CarrierWave::Uploader::Base
def store_dir
'public/my/upload/directory'
end
end
```
This works for the file storage as well as Amazon S3 and Rackspace Cloud Files.
Define `store_dir` as `nil` if you'd like to store files at the root level.
If you store files outside the project root folder, you may want to define `cache_dir` in the same way:
```ruby
class MyUploader < CarrierWave::Uploader::Base
def cache_dir
'/tmp/projectname-cache'
end
end
```
## Securing uploads
Certain files might be dangerous if uploaded to the wrong location, such as PHP
files or other script files. CarrierWave allows you to specify a whitelist of
allowed extensions or content types.
If you're mounting the uploader, uploading a file with the wrong extension will
make the record invalid instead. Otherwise, an error is raised.
```ruby
class MyUploader < CarrierWave::Uploader::Base
def extension_whitelist
%w(jpg jpeg gif png)
end
end
```
The same thing could be done using content types.
Let's say we need an uploader that accepts only images. This can be done like this
```ruby
class MyUploader < CarrierWave::Uploader::Base
def content_type_whitelist
/image\//
end
end
```
You can use a blacklist to reject content types.
Let's say we need an uploader that reject JSON files. This can be done like this
```ruby
class NoJsonUploader < CarrierWave::Uploader::Base
def content_type_blacklist
['application/text', 'application/json']
end
end
```
### Filenames and unicode chars
Another security issue you should care for is the file names (see
[Ruby On Rails Security Guide](http://guides.rubyonrails.org/security.html#file-uploads)).
By default, CarrierWave provides only English letters, arabic numerals and some symbols as
white-listed characters in the file name. If you want to support local scripts (Cyrillic letters, letters with diacritics and so on), you
have to override `sanitize_regexp` method. It should return regular expression which would match
all *non*-allowed symbols.
```ruby
CarrierWave::SanitizedFile.sanitize_regexp = /[^[:word:]\.\-\+]/
```
Also make sure that allowing non-latin characters won't cause a compatibility issue with a third-party
plugins or client-side software.
## Setting the content type
As of v0.11.0, the `mime-types` gem is a runtime dependency and the content type is set automatically.
You no longer need to do this manually.
## Adding versions
Often you'll want to add different versions of the same file. The classic example is image thumbnails. There is built in support for this*:
*Note:* You must have Imagemagick and MiniMagick installed to do image resizing. MiniMagick is a Ruby interface for Imagemagick which is a C program. This is why MiniMagick fails on 'bundle install' without Imagemagick installed.
Some documentation refers to RMagick instead of MiniMagick but MiniMagick is recommended.
To install Imagemagick on OSX with homebrew type the following:
```
$ brew install imagemagick
```
```ruby
class MyUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
process resize_to_fit: [800, 800]
version :thumb do
process resize_to_fill: [200,200]
end
end
```
When this uploader is used, an uploaded image would be scaled to be no larger
than 800 by 800 pixels. The original aspect ratio will be kept.
A version called thumb is then created, which is scaled
to exactly 200 by 200 pixels.
If you would like to crop images to a specific height and width you
can use the alternative option of '''resize_to_fill'''. It will make sure
that the width and height specified are filled, only copping
if the aspect ratio requires it.
The uploader could be used like this:
```ruby
uploader = AvatarUploader.new
uploader.store!(my_file) # size: 1024x768
uploader.url # => '/url/to/my_file.png' # size: 800x800
uploader.thumb.url # => '/url/to/thumb_my_file.png' # size: 200x200
```
One important thing to remember is that process is called *before* versions are
created. This can cut down on processing cost.
It is possible to nest versions within versions:
```ruby
class MyUploader < CarrierWave::Uploader::Base
version :animal do
version :human
version :monkey
version :llama
end
end
```
### Conditional versions
Occasionally you want to restrict the creation of versions on certain
properties within the model or based on the picture itself.
```ruby
class MyUploader < CarrierWave::Uploader::Base
version :human, if: :is_human?
version :monkey, if: :is_monkey?
version :banner, if: :is_landscape?
private
def is_human? picture
model.can_program?(:ruby)
end
def is_monkey? picture
model.favorite_food == 'banana'
end
def is_landscape? picture
image = MiniMagick::Image.open(picture.path)
image[:width] > image[:height]
end
end
```
The `model` variable points to the instance object the uploader is attached to.
### Create versions from existing versions
For performance reasons, it is often useful to create versions from existing ones
instead of using the original file. If your uploader generates several versions
where the next is smaller than the last, it will take less time to generate from
a smaller, already processed image.
```ruby
class MyUploader < CarrierWave::Uploader::Base
version :thumb do
process resize_to_fill: [280, 280]
end
version :small_thumb, from_version: :thumb do
process resize_to_fill: [20, 20]
end
end
```
The option `:from_version` uses the file cached in the `:thumb` version instead
of the original version, potentially resulting in faster processing.
## Making uploads work across form redisplays
Often you'll notice that uploaded files disappear when a validation fails.
CarrierWave has a feature that makes it easy to remember the uploaded file even
in that case. Suppose your `user` model has an uploader mounted on `avatar`
file, just add a hidden field called `avatar_cache` (don't forget to add it to
the attr_accessible list as necessary). In Rails, this would look like this:
```erb
<%= form_for @user, html: { multipart: true } do |f| %>
<% end %>
````
It might be a good idea to show the user that a file has been uploaded, in the
case of images, a small thumbnail would be a good indicator:
```erb
<%= form_for @user, html: { multipart: true } do |f| %>
<% end %>
```
## Removing uploaded files
If you want to remove a previously uploaded file on a mounted uploader, you can
easily add a checkbox to the form which will remove the file when checked.
```erb
<%= form_for @user, html: { multipart: true } do |f| %>
<%= image_tag(@user.avatar_url) if @user.avatar? %>
<%= f.file_field :avatar %>
<% end %>
```
If you want to remove the file manually, you can call remove_avatar!, then save the object.
```erb
@user.remove_avatar!
@user.save
#=> true
```
## Uploading files from a remote location
Your users may find it convenient to upload a file from a location on the Internet
via a URL. CarrierWave makes this simple, just add the appropriate attribute to your
form and you're good to go:
```erb
<%= form_for @user, html: { multipart: true } do |f| %>
<%= image_tag(@user.avatar_url) if @user.avatar? %>
<%= f.text_field :remote_avatar_url %>
<% end %>
```
If you're using ActiveRecord, CarrierWave will indicate invalid URLs and download
failures automatically with attribute validation errors. If you aren't, or you
disable CarrierWave's `validate_download` option, you'll need to handle those
errors yourself.
## Providing a default URL
In many cases, especially when working with images, it might be a good idea to
provide a default url, a fallback in case no file has been uploaded. You can do
this easily by overriding the `default_url` method in your uploader:
```ruby
class MyUploader < CarrierWave::Uploader::Base
def default_url(*args)
"/images/fallback/" + [version_name, "default.png"].compact.join('_')
end
end
```
Or if you are using the Rails asset pipeline:
```ruby
class MyUploader < CarrierWave::Uploader::Base
def default_url(*args)
ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
end
end
```
## Recreating versions
You might come to a situation where you want to retroactively change a version
or add a new one. You can use the `recreate_versions!` method to recreate the
versions from the base file. This uses a naive approach which will re-upload and
process the specified version or all versions, if none is passed as an argument.
When you are generating random unique filenames you have to call `save!` on
the model after using `recreate_versions!`. This is necessary because
`recreate_versions!` doesn't save the new filename to the database. Calling
`save!` yourself will prevent that the database and file system are running
out of sync.
```ruby
instance = MyUploader.new
instance.recreate_versions!(:thumb, :large)
```
Or on a mounted uploader:
```ruby
User.find_each do |user|
user.avatar.recreate_versions!
end
```
Note: `recreate_versions!` will throw an exception on records without an image. To avoid this, scope the records to those with images or check if an image exists within the block. If you're using ActiveRecord, recreating versions for a user avatar might look like this:
```ruby
User.find_each do |user|
user.avatar.recreate_versions! if user.avatar?
end
```
## Configuring CarrierWave
CarrierWave has a broad range of configuration options, which you can configure,
both globally and on a per-uploader basis:
```ruby
CarrierWave.configure do |config|
config.permissions = 0666
config.directory_permissions = 0777
config.storage = :file
end
```
Or alternatively:
```ruby
class AvatarUploader < CarrierWave::Uploader::Base
permissions 0777
end
```
If you're using Rails, create an initializer for this:
config/initializers/carrierwave.rb
If you want CarrierWave to fail noisily in development, you can change these configs in your environment file:
```ruby
CarrierWave.configure do |config|
config.ignore_integrity_errors = false
config.ignore_processing_errors = false
config.ignore_download_errors = false
end
```
## Testing with CarrierWave
It's a good idea to test your uploaders in isolation. In order to speed up your
tests, it's recommended to switch off processing in your tests, and to use the
file storage. In Rails you could do that by adding an initializer with:
```ruby
if Rails.env.test? or Rails.env.cucumber?
CarrierWave.configure do |config|
config.storage = :file
config.enable_processing = false
end
end
```
Remember, if you have already set `storage :something` in your uploader, the `storage`
setting from this initializer will be ignored.
If you need to test your processing, you should test it in isolation, and enable
processing only for those tests that need it.
CarrierWave comes with some RSpec matchers which you may find useful:
```ruby
require 'carrierwave/test/matchers'
describe MyUploader do
include CarrierWave::Test::Matchers
let(:user) { double('user') }
let(:uploader) { MyUploader.new(user, :avatar) }
before do
MyUploader.enable_processing = true
File.open(path_to_file) { |f| uploader.store!(f) }
end
after do
MyUploader.enable_processing = false
uploader.remove!
end
context 'the thumb version' do
it "scales down a landscape image to be exactly 64 by 64 pixels" do
expect(uploader.thumb).to have_dimensions(64, 64)
end
end
context 'the small version' do
it "scales down a landscape image to fit within 200 by 200 pixels" do
expect(uploader.small).to be_no_larger_than(200, 200)
end
end
it "makes the image readable only to the owner and not executable" do
expect(uploader).to have_permissions(0600)
end
it "has the correct format" do
expect(uploader).to be_format('png')
end
end
```
Setting the enable_processing flag on an uploader will prevent any of the versions from processing as well.
Processing can be enabled for a single version by setting the processing flag on the version like so:
```ruby
@uploader.thumb.enable_processing = true
```
## Fog
If you want to use fog you must add in your CarrierWave initializer the
following lines
```ruby
config.fog_provider = 'fog' # 'fog/aws' etc. Defaults to 'fog'
config.fog_credentials = { ... } # Provider specific credentials
```
## Using Amazon S3
[Fog AWS](http://github.com/fog/fog-aws) is used to support Amazon S3. Ensure you have it in your Gemfile:
```ruby
gem "fog-aws"
```
You'll need to provide your fog_credentials and a fog_directory (also known as a bucket) in an initializer.
For the sake of performance it is assumed that the directory already exists, so please create it if it needs to be.
You can also pass in additional options, as documented fully in lib/carrierwave/storage/fog.rb. Here's a full example:
```ruby
CarrierWave.configure do |config|
config.fog_provider = 'fog/aws' # required
config.fog_credentials = {
provider: 'AWS', # required
aws_access_key_id: 'xxx', # required
aws_secret_access_key: 'yyy', # required
region: 'eu-west-1', # optional, defaults to 'us-east-1'
host: 's3.example.com', # optional, defaults to nil
endpoint: 'https://s3.example.com:8080' # optional, defaults to nil
}
config.fog_directory = 'name_of_directory' # required
config.fog_public = false # optional, defaults to true
config.fog_attributes = { cache_control: "public, max-age=#{365.days.to_i}" } # optional, defaults to {}
end
```
In your uploader, set the storage to :fog
```ruby
class AvatarUploader < CarrierWave::Uploader::Base
storage :fog
end
```
That's it! You can still use the `CarrierWave::Uploader#url` method to return the url to the file on Amazon S3.
## Using Rackspace Cloud Files
[Fog](http://github.com/fog/fog) is used to support Rackspace Cloud Files. Ensure you have it in your Gemfile:
```ruby
gem "fog"
```
You'll need to configure a directory (also known as a container), username and API key in the initializer.
For the sake of performance it is assumed that the directory already exists, so please create it if need be.
Using a US-based account:
```ruby
CarrierWave.configure do |config|
config.fog_provider = "fog/rackspace/storage" # optional, defaults to "fog"
config.fog_credentials = {
provider: 'Rackspace',
rackspace_username: 'xxxxxx',
rackspace_api_key: 'yyyyyy',
rackspace_region: :ord # optional, defaults to :dfw
}
config.fog_directory = 'name_of_directory'
end
```
Using a UK-based account:
```ruby
CarrierWave.configure do |config|
config.fog_provider = "fog/rackspace/storage" # optional, defaults to "fog"
config.fog_credentials = {
provider: 'Rackspace',
rackspace_username: 'xxxxxx',
rackspace_api_key: 'yyyyyy',
rackspace_auth_url: Fog::Rackspace::UK_AUTH_ENDPOINT,
rackspace_region: :lon
}
config.fog_directory = 'name_of_directory'
end
```
You can optionally include your CDN host name in the configuration.
This is *highly* recommended, as without it every request requires a lookup
of this information.
```ruby
config.asset_host = "http://c000000.cdn.rackspacecloud.com"
```
In your uploader, set the storage to :fog
```ruby
class AvatarUploader < CarrierWave::Uploader::Base
storage :fog
end
```
That's it! You can still use the `CarrierWave::Uploader#url` method to return
the url to the file on Rackspace Cloud Files.
## Using Google Storage for Developers
[Fog](http://github.com/fog/fog-google) is used to support Google Storage for Developers. Ensure you have it in your Gemfile:
```ruby
gem "fog-google"
gem "google-api-client", "> 0.8.5", "< 0.9"
gem "mime-types"
```
You'll need to configure a directory (also known as a bucket), access key id and secret access key in the initializer.
For the sake of performance it is assumed that the directory already exists, so please create it if need be.
Please read the [fog-google README](https://github.com/fog/fog-google/blob/master/README.md) on how to get credentials.
```ruby
CarrierWave.configure do |config|
config.fog_provider = 'fog/google' # required
config.fog_credentials = {
provider: 'Google',
google_storage_access_key_id: 'xxxxxx',
google_storage_secret_access_key: 'yyyyyy'
}
config.fog_directory = 'name_of_directory'
end
```
In your uploader, set the storage to :fog
```ruby
class AvatarUploader < CarrierWave::Uploader::Base
storage :fog
end
```
That's it! You can still use the `CarrierWave::Uploader#url` method to return
the url to the file on Google.
## Optimized Loading of Fog
Since Carrierwave doesn't know which parts of Fog you intend to use, it will just load the entire library (unless you use e.g. [`fog-aws`, `fog-google`] instead of fog proper). If you prefer to load fewer classes into your application, you need to load those parts of Fog yourself *before* loading CarrierWave in your Gemfile. Ex:
```ruby
gem "fog", "~> 1.27", require: "fog/rackspace/storage"
gem "carrierwave"
```
A couple of notes about versions:
* This functionality was introduced in Fog v1.20.
* This functionality is slated for CarrierWave v1.0.0.
If you're not relying on Gemfile entries alone and are requiring "carrierwave" anywhere, ensure you require "fog/rackspace/storage" before it. Ex:
```ruby
require "fog/rackspace/storage"
require "carrierwave"
```
Beware that this specific require is only needed when working with a fog provider that was not extracted to its own gem yet.
A list of the extracted providers can be found in the page of the `fog` organizations [here](https://github.com/fog).
When in doubt, inspect `Fog.constants` to see what has been loaded.
## Dynamic Asset Host
The `asset_host` config property can be assigned a proc (or anything that responds to `call`) for generating the host dynamically. The proc-compliant object gets an instance of the current `CarrierWave::Storage::Fog::File` or `CarrierWave::SanitizedFile` as its only argument.
```ruby
CarrierWave.configure do |config|
config.asset_host = proc do |file|
identifier = # some logic
"http://#{identifier}.cdn.rackspacecloud.com"
end
end
```
## Using RMagick
If you're uploading images, you'll probably want to manipulate them in some way,
you might want to create thumbnail images for example. CarrierWave comes with a
small library to make manipulating images with RMagick easier, you'll need to
include it in your Uploader:
```ruby
class AvatarUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
end
```
The RMagick module gives you a few methods, like
`CarrierWave::RMagick#resize_to_fill` which manipulate the image file in some
way. You can set a `process` callback, which will call that method any time a
file is uploaded.
There is a demonstration of convert here.
Convert will only work if the file has the same file extension, thus the use of the filename method.
```ruby
class AvatarUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
process resize_to_fill: [200, 200]
process convert: 'png'
def filename
super.chomp(File.extname(super)) + '.png' if original_filename.present?
end
end
```
Check out the manipulate! method, which makes it easy for you to write your own
manipulation methods.
## Using MiniMagick
MiniMagick is similar to RMagick but performs all the operations using the 'mogrify'
command which is part of the standard ImageMagick kit. This allows you to have the power
of ImageMagick without having to worry about installing all the RMagick libraries.
See the MiniMagick site for more details:
https://github.com/minimagick/minimagick
And the ImageMagick command line options for more for whats on offer:
http://www.imagemagick.org/script/command-line-options.php
Currently, the MiniMagick carrierwave processor provides exactly the same methods as
for the RMagick processor.
```ruby
class AvatarUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
process resize_to_fill: [200, 200]
end
```
## Migrating from Paperclip
If you are using Paperclip, you can use the provided compatibility module:
```ruby
class AvatarUploader < CarrierWave::Uploader::Base
include CarrierWave::Compatibility::Paperclip
end
```
See the documentation for `CarrierWave::Compatibility::Paperclip` for more
details.
Be sure to use mount_on to specify the correct column:
```ruby
mount_uploader :avatar, AvatarUploader, mount_on: :avatar_file_name
```
## I18n
The Active Record validations use the Rails `i18n` framework. Add these keys to
your translations file:
```yaml
errors:
messages:
carrierwave_processing_error: failed to be processed
carrierwave_integrity_error: is not of an allowed file type
carrierwave_download_error: could not be downloaded
extension_whitelist_error: "You are not allowed to upload %{extension} files, allowed types: %{allowed_types}"
extension_blacklist_error: "You are not allowed to upload %{extension} files, prohibited types: %{prohibited_types}"
content_type_whitelist_error: "You are not allowed to upload %{content_type} files"
content_type_blacklist_error: "You are not allowed to upload %{content_type} files"
rmagick_processing_error: "Failed to manipulate with rmagick, maybe it is not an image?"
mini_magick_processing_error: "Failed to manipulate with MiniMagick, maybe it is not an image? Original Error: %{e}"
min_size_error: "File size should be greater than %{min_size}"
max_size_error: "File size should be less than %{max_size}"
```
The [`carrierwave-i18n`](https://github.com/carrierwaveuploader/carrierwave-i18n)
library adds support for additional locales.
## Large files
By default, CarrierWave copies an uploaded file twice, first copying the file into the cache, then
copying the file into the store. For large files, this can be prohibitively time consuming.
You may change this behavior by overriding either or both of the `move_to_cache` and
`move_to_store` methods:
```ruby
class MyUploader < CarrierWave::Uploader::Base
def move_to_cache
true
end
def move_to_store
true
end
end
```
When the `move_to_cache` and/or `move_to_store` methods return true, files will be moved (instead of copied) to the cache and store respectively.
This has only been tested with the local filesystem store.
## Skipping ActiveRecord callbacks
By default, mounting an uploader into an ActiveRecord model will add a few
callbacks. For example, this code:
```ruby
class User
mount_uploader :avatar, AvatarUploader
end
```
Will add these callbacks:
```ruby
after_save :store_avatar!
before_save :write_avatar_identifier
after_commit :remove_avatar!, on: :destroy
after_commit :mark_remove_avatar_false, on: :update
after_save :store_previous_changes_for_avatar
after_commit :remove_previously_stored_avatar, on: :update
```
If you want to skip any of these callbacks (eg. you want to keep the existing
avatar, even after uploading a new one), you can use ActiveRecord’s
`skip_callback` method.
```ruby
class User
mount_uploader :avatar, AvatarUploader
skip_callback :commit, :after, :remove_previously_stored_avatar
end
```
## Contributing to CarrierWave
See [CONTRIBUTING.md](https://github.com/carrierwaveuploader/carrierwave/blob/master/CONTRIBUTING.md)
## License
Copyright (c) 2008-2015 Jonas Nicklas
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
carrierwave-1.2.2/Rakefile 0000664 0000000 0000000 00000001111 13222647327 0015475 0 ustar 00root root 0000000 0000000 require 'rubygems'
begin
require 'bundler/setup'
rescue LoadError
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
end
require 'bundler'
Bundler::GemHelper.install_tasks
require 'rake'
require 'rspec/core/rake_task'
require 'cucumber'
require 'cucumber/rake/task'
desc "Run all examples"
RSpec::Core::RakeTask.new(:spec) do |t|
t.rspec_opts = %w[--color]
end
desc "Run cucumber features"
Cucumber::Rake::Task.new(:features) do |t|
t.cucumber_opts = "features --format progress"
end
task :default => [:spec, :features]
carrierwave-1.2.2/carrierwave.gemspec 0000664 0000000 0000000 00000003014 13222647327 0017713 0 ustar 00root root 0000000 0000000 # -*- encoding: utf-8 -*-
lib = File.expand_path('../lib/', __FILE__)
$:.unshift lib unless $:.include?(lib)
require 'carrierwave/version'
Gem::Specification.new do |s|
s.name = "carrierwave"
s.version = CarrierWave::VERSION
s.authors = ["Jonas Nicklas"]
s.description = "Upload files in your Ruby applications, map them to a range of ORMs, store them on different backends."
s.summary = "Ruby file upload library"
s.email = ["jonas.nicklas@gmail.com"]
s.extra_rdoc_files = ["README.md"]
s.files = Dir["{bin,lib}/**/*", "README.md"]
s.homepage = %q{https://github.com/carrierwaveuploader/carrierwave}
s.rdoc_options = ["--main"]
s.require_paths = ["lib"]
s.licenses = ["MIT"]
s.required_ruby_version = ">= 2.0.0"
s.add_dependency "activesupport", ">= 4.0.0"
s.add_dependency "activemodel", ">= 4.0.0"
s.add_dependency "mime-types", ">= 1.16"
if RUBY_ENGINE == 'jruby'
s.add_development_dependency 'activerecord-jdbcpostgresql-adapter'
else
s.add_development_dependency "pg"
end
s.add_development_dependency "rails", ">= 4.0.0"
s.add_development_dependency "cucumber", "~> 2.3"
s.add_development_dependency "rspec", "~> 3.4"
s.add_development_dependency "webmock"
s.add_development_dependency "fog", ">= 1.28.0"
s.add_development_dependency "mini_magick", ">= 3.6.0"
if RUBY_ENGINE != 'jruby'
s.add_development_dependency "rmagick"
end
s.add_development_dependency "timecop"
s.add_development_dependency "generator_spec", ">= 0.9.1"
s.add_development_dependency "pry"
end
carrierwave-1.2.2/cucumber.yml 0000664 0000000 0000000 00000000114 13222647327 0016362 0 ustar 00root root 0000000 0000000 default: --format pretty --no-source
html: --format html --out features.html carrierwave-1.2.2/features/ 0000775 0000000 0000000 00000000000 13222647327 0015654 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/features/caching.feature 0000664 0000000 0000000 00000003231 13222647327 0020624 0 ustar 00root root 0000000 0000000 Feature: uploader with file storage
In order to be able to temporarily store files to disk
As a developer using CarrierWave
I want to cache files
Scenario: cache a file
Given an uploader class that uses the 'file' storage
And an instance of that class
When I cache the file 'fixtures/bork.txt'
Then there should be a file called 'bork.txt' somewhere in a subdirectory of 'public/uploads/tmp'
And the file called 'bork.txt' in a subdirectory of 'public/uploads/tmp' should be identical to the file at 'fixtures/bork.txt'
Scenario: cache two files in succession
Given an uploader class that uses the 'file' storage
And an instance of that class
When I cache the file 'fixtures/bork.txt'
Then there should be a file called 'bork.txt' somewhere in a subdirectory of 'public/uploads/tmp'
And the file called 'bork.txt' in a subdirectory of 'public/uploads/tmp' should be identical to the file at 'fixtures/bork.txt'
When I cache the file 'fixtures/monkey.txt'
Then there should be a file called 'monkey.txt' somewhere in a subdirectory of 'public/uploads/tmp'
And the file called 'monkey.txt' in a subdirectory of 'public/uploads/tmp' should be identical to the file at 'fixtures/monkey.txt'
Scenario: retrieving a file from cache
Given an uploader class that uses the 'file' storage
And an instance of that class
And the file 'fixtures/bork.txt' is cached file at 'public/uploads/tmp/1369894322-345-1234-2255/bork.txt'
When I retrieve the cache name '1369894322-345-1234-2255/bork.txt' from the cache
Then the uploader should have 'public/uploads/tmp/1369894322-345-1234-2255/bork.txt' as its current path
carrierwave-1.2.2/features/download.feature 0000664 0000000 0000000 00000001567 13222647327 0021051 0 ustar 00root root 0000000 0000000 Feature: downloading files
In order to allow users to upload remote files
As a developer using CarrierWave
I want to download files to the filesystem via HTTP
Background:
Given an uploader class that uses the 'file' storage
And an instance of that class
Scenario: download a file
When I download the file 'http://s3.amazonaws.com/Monkey/testfile.txt'
Then there should be a file called 'testfile.txt' somewhere in a subdirectory of 'public/uploads/tmp'
And the file called 'testfile.txt' in a subdirectory of 'public/uploads/tmp' should contain 'S3 Remote File'
Scenario: downloading a file then storing
When I download the file 'http://s3.amazonaws.com/Monkey/testfile.txt'
And I store the file
Then there should be a file at 'public/uploads/testfile.txt'
And the file at 'public/uploads/testfile.txt' should contain 'S3 Remote File'
carrierwave-1.2.2/features/file_storage.feature 0000664 0000000 0000000 00000003652 13222647327 0021702 0 ustar 00root root 0000000 0000000 Feature: uploader with file storage
In order to be awesome
As a developer using CarrierWave
I want to upload files to the filesystem
Background:
Given an uploader class that uses the 'file' storage
And an instance of that class
Scenario: store a file
When I store the file 'fixtures/bork.txt'
Then there should be a file at 'public/uploads/bork.txt'
And the file at 'public/uploads/bork.txt' should be identical to the file at 'fixtures/bork.txt'
Scenario: store two files in succession
When I store the file 'fixtures/bork.txt'
Then there should be a file at 'public/uploads/bork.txt'
And the file at 'public/uploads/bork.txt' should be identical to the file at 'fixtures/bork.txt'
When I store the file 'fixtures/monkey.txt'
Then there should be a file at 'public/uploads/monkey.txt'
And the file at 'public/uploads/monkey.txt' should be identical to the file at 'fixtures/monkey.txt'
Scenario: cache a file and then store it
When I cache the file 'fixtures/bork.txt'
Then there should be a file called 'bork.txt' somewhere in a subdirectory of 'public/uploads/tmp'
And the file called 'bork.txt' in a subdirectory of 'public/uploads/tmp' should be identical to the file at 'fixtures/bork.txt'
And there should not be a file at 'public/uploads/bork.txt'
When I store the file
Then there should be a file at 'public/uploads/bork.txt'
And the file at 'public/uploads/bork.txt' should be identical to the file at 'fixtures/bork.txt'
Scenario: retrieving a file from cache then storing
Given the file 'fixtures/bork.txt' is cached file at 'public/uploads/tmp/1369894322-345-1234-2255/bork.txt'
When I retrieve the cache name '1369894322-345-1234-2255/bork.txt' from the cache
And I store the file
Then there should be a file at 'public/uploads/bork.txt'
And the file at 'public/uploads/bork.txt' should be identical to the file at 'fixtures/bork.txt'
carrierwave-1.2.2/features/file_storage_overridden_filename.feature 0000664 0000000 0000000 00000004014 13222647327 0025754 0 ustar 00root root 0000000 0000000 Feature: uploader with file storage and overriden filename
In order to be awesome
As a developer using CarrierWave
I want to upload files to the filesystem with an overriden filename
Background:
Given an uploader class that uses the 'file' storage
And that the uploader reverses the filename
And an instance of that class
Scenario: store a file
When I store the file 'fixtures/bork.txt'
Then there should be a file at 'public/uploads/txt.krob'
And the file at 'public/uploads/txt.krob' should be identical to the file at 'fixtures/bork.txt'
Scenario: store two files in succession
When I store the file 'fixtures/bork.txt'
Then there should be a file at 'public/uploads/txt.krob'
And the file at 'public/uploads/txt.krob' should be identical to the file at 'fixtures/bork.txt'
When I store the file 'fixtures/monkey.txt'
Then there should be a file at 'public/uploads/txt.yeknom'
And the file at 'public/uploads/txt.yeknom' should be identical to the file at 'fixtures/monkey.txt'
Scenario: cache a file and then store it
When I cache the file 'fixtures/bork.txt'
Then there should be a file called 'bork.txt' somewhere in a subdirectory of 'public/uploads/tmp'
And the file called 'bork.txt' in a subdirectory of 'public/uploads/tmp' should be identical to the file at 'fixtures/bork.txt'
And there should not be a file at 'public/uploads/txt.krob'
When I store the file
Then there should be a file at 'public/uploads/txt.krob'
And the file at 'public/uploads/txt.krob' should be identical to the file at 'fixtures/bork.txt'
Scenario: retrieving a file from cache then storing
Given the file 'fixtures/bork.txt' is cached file at 'public/uploads/tmp/1369894322-345-1234-2255/bork.txt'
When I retrieve the cache name '1369894322-345-1234-2255/bork.txt' from the cache
And I store the file
Then there should be a file at 'public/uploads/txt.krob'
And the file at 'public/uploads/txt.krob' should be identical to the file at 'fixtures/bork.txt'
carrierwave-1.2.2/features/file_storage_overridden_store_dir.feature 0000664 0000000 0000000 00000004112 13222647327 0026165 0 ustar 00root root 0000000 0000000 Feature: uploader with file storage and overridden store dir
In order to be awesome
As a developer using CarrierWave
I want to upload files to the filesystem
Background:
Given an uploader class that uses the 'file' storage
And that the uploader has the store_dir overridden to 'public/monkey/llama'
And an instance of that class
Scenario: store a file
When I store the file 'fixtures/bork.txt'
Then there should be a file at 'public/monkey/llama/bork.txt'
And the file at 'public/monkey/llama/bork.txt' should be identical to the file at 'fixtures/bork.txt'
Scenario: store two files in succession
When I store the file 'fixtures/bork.txt'
Then there should be a file at 'public/monkey/llama/bork.txt'
And the file at 'public/monkey/llama/bork.txt' should be identical to the file at 'fixtures/bork.txt'
When I store the file 'fixtures/monkey.txt'
Then there should be a file at 'public/monkey/llama/monkey.txt'
And the file at 'public/monkey/llama/monkey.txt' should be identical to the file at 'fixtures/monkey.txt'
Scenario: cache a file and then store it
When I cache the file 'fixtures/bork.txt'
Then there should be a file called 'bork.txt' somewhere in a subdirectory of 'public/uploads/tmp'
And the file called 'bork.txt' in a subdirectory of 'public/uploads/tmp' should be identical to the file at 'fixtures/bork.txt'
And there should not be a file at 'public/monkey/llama/bork.txt'
When I store the file
Then there should be a file at 'public/monkey/llama/bork.txt'
And the file at 'public/monkey/llama/bork.txt' should be identical to the file at 'fixtures/bork.txt'
Scenario: retrieving a file from cache then storing
Given the file 'fixtures/bork.txt' is cached file at 'public/uploads/tmp/1369894322-345-1234-2255/bork.txt'
When I retrieve the cache name '1369894322-345-1234-2255/bork.txt' from the cache
And I store the file
Then there should be a file at 'public/monkey/llama/bork.txt'
And the file at 'public/monkey/llama/bork.txt' should be identical to the file at 'fixtures/bork.txt'
carrierwave-1.2.2/features/file_storage_reversing_processor.feature 0000664 0000000 0000000 00000005003 13222647327 0026055 0 ustar 00root root 0000000 0000000 Feature: uploader with file storage and a processor that reverses the file
In order to be awesome
As a developer using CarrierWave
I want to upload files to the filesystem
Background:
Given an uploader class that uses the 'file' storage
And an instance of that class
And the class has a method called 'reverse' that reverses the contents of a file
And the class will process 'reverse'
Scenario: store a file
When I store the file 'fixtures/bork.txt'
Then there should be a file at 'public/uploads/bork.txt'
And the file at 'public/uploads/bork.txt' should not be identical to the file at 'fixtures/bork.txt'
And the file at 'public/uploads/bork.txt' should be the reverse of the file at 'fixtures/bork.txt'
Scenario: store two files in succession
When I store the file 'fixtures/bork.txt'
Then there should be a file at 'public/uploads/bork.txt'
And the file at 'public/uploads/bork.txt' should not be identical to the file at 'fixtures/bork.txt'
And the file at 'public/uploads/bork.txt' should be the reverse of the file at 'fixtures/bork.txt'
When I store the file 'fixtures/monkey.txt'
Then there should be a file at 'public/uploads/monkey.txt'
And the file at 'public/uploads/monkey.txt' should not be identical to the file at 'fixtures/monkey.txt'
And the file at 'public/uploads/monkey.txt' should be the reverse of the file at 'fixtures/monkey.txt'
Scenario: cache a file and then store it
When I cache the file 'fixtures/bork.txt'
Then there should be a file called 'bork.txt' somewhere in a subdirectory of 'public/uploads/tmp'
And the file called 'bork.txt' in a subdirectory of 'public/uploads/tmp' should not be identical to the file at 'fixtures/bork.txt'
And there should not be a file at 'public/uploads/bork.txt'
When I store the file
Then there should be a file at 'public/uploads/bork.txt'
And the file at 'public/uploads/bork.txt' should not be identical to the file at 'fixtures/bork.txt'
And the file at 'public/uploads/bork.txt' should be the reverse of the file at 'fixtures/bork.txt'
Scenario: retrieving a file from cache then storing
Given the file 'fixtures/bork.txt' is cached file at 'public/uploads/tmp/1369894322-345-1234-2255/bork.txt'
When I retrieve the cache name '1369894322-345-1234-2255/bork.txt' from the cache
And I store the file
Then there should be a file at 'public/uploads/bork.txt'
And the file at 'public/uploads/bork.txt' should be identical to the file at 'fixtures/bork.txt'
carrierwave-1.2.2/features/fixtures/ 0000775 0000000 0000000 00000000000 13222647327 0017525 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/features/fixtures/bork.txt 0000664 0000000 0000000 00000000016 13222647327 0021220 0 ustar 00root root 0000000 0000000 this is a file carrierwave-1.2.2/features/fixtures/monkey.txt 0000664 0000000 0000000 00000000024 13222647327 0021564 0 ustar 00root root 0000000 0000000 this is another file carrierwave-1.2.2/features/fixtures/upcased_bork.txt 0000664 0000000 0000000 00000000016 13222647327 0022724 0 ustar 00root root 0000000 0000000 THIS IS A FILE carrierwave-1.2.2/features/mount_activerecord.feature 0000664 0000000 0000000 00000004530 13222647327 0023127 0 ustar 00root root 0000000 0000000 Feature: Mount an Uploader on ActiveRecord class
In order to easily attach files to a form
As a web developer using CarrierWave
I want to mount an uploader on an ActiveRecord class
Background:
Given an uploader class that uses the 'file' storage
And an activerecord class that uses the 'users' table
And the uploader class is mounted on the 'avatar' column
And an instance of the activerecord class
Scenario: assign a file
When I assign the file 'fixtures/bork.txt' to the 'avatar' column
Then there should be a file called 'bork.txt' somewhere in a subdirectory of 'public/uploads/tmp'
And the file called 'bork.txt' in a subdirectory of 'public/uploads/tmp' should be identical to the file at 'fixtures/bork.txt'
Scenario: assign a file and save the record
When I assign the file 'fixtures/bork.txt' to the 'avatar' column
And I save the active record
Then there should be a file at 'public/uploads/bork.txt'
And the file at 'public/uploads/bork.txt' should be identical to the file at 'fixtures/bork.txt'
And the url for the column 'avatar' should be '/uploads/bork.txt'
Scenario: assign a file and retrieve it from cache
When I assign the file 'fixtures/bork.txt' to the 'avatar' column
And I retrieve the file later from the cache name for the column 'avatar'
And I save the active record
Then there should be a file at 'public/uploads/bork.txt'
And the file at 'public/uploads/bork.txt' should be identical to the file at 'fixtures/bork.txt'
And the url for the column 'avatar' should be '/uploads/bork.txt'
Scenario: store a file and retrieve it later
When I assign the file 'fixtures/bork.txt' to the 'avatar' column
And I retrieve the file later from the cache name for the column 'avatar'
And I save the active record
Then there should be a file at 'public/uploads/bork.txt'
When I reload the active record
Then the url for the column 'avatar' should be '/uploads/bork.txt'
Scenario: store a file and delete the record
When I assign the file 'fixtures/bork.txt' to the 'avatar' column
And I retrieve the file later from the cache name for the column 'avatar'
And I save the active record
Then there should be a file at 'public/uploads/bork.txt'
When I delete the active record
Then there should not be a file at 'public/uploads/bork.txt'
carrierwave-1.2.2/features/step_definitions/ 0000775 0000000 0000000 00000000000 13222647327 0021222 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/features/step_definitions/activerecord_steps.rb 0000664 0000000 0000000 00000000723 13222647327 0025441 0 ustar 00root root 0000000 0000000 Given /^an activerecord class that uses the '([^\']*)' table$/ do |name|
@mountee_klass = Class.new(ActiveRecord::Base)
@mountee_klass.table_name = name
end
Given /^an instance of the activerecord class$/ do
@instance = @mountee_klass.new
end
When /^I save the active record$/ do
@instance.save!
end
When /^I reload the active record$/ do
@instance = @instance.class.find(@instance.id)
end
When /^I delete the active record$/ do
@instance.destroy
end
carrierwave-1.2.2/features/step_definitions/caching_steps.rb 0000664 0000000 0000000 00000000603 13222647327 0024360 0 ustar 00root root 0000000 0000000 Given /^the file '(.*?)' is cached file at '(.*?)'$/ do |file, cached|
FileUtils.mkdir_p(File.dirname(file_path(cached)))
FileUtils.cp(file_path(file), file_path(cached))
end
When /^I cache the file '(.*?)'$/ do |file|
@uploader.cache!(File.open(file_path(file)))
end
When /^I retrieve the cache name '(.*?)' from the cache$/ do |name|
@uploader.retrieve_from_cache!(name)
end
carrierwave-1.2.2/features/step_definitions/datamapper_steps.rb 0000664 0000000 0000000 00000001153 13222647327 0025103 0 ustar 00root root 0000000 0000000 Given /^a datamapper class that has a '([^\']*)' column$/ do |column|
@mountee_klass = Class.new do
include DataMapper::Resource
storage_names[:default] = 'users'
property :id, DataMapper::Types::Serial
property column.to_sym, String
end
@mountee_klass.auto_migrate!
end
Given /^an instance of the datamapper class$/ do
@instance = @mountee_klass.new
end
When /^I save the datamapper record$/ do
@instance.save
end
When /^I reload the datamapper record$/ do
@instance = @instance.class.first(:id => @instance.key)
end
When /^I delete the datamapper record$/ do
@instance.destroy
end
carrierwave-1.2.2/features/step_definitions/download_steps.rb 0000664 0000000 0000000 00000000413 13222647327 0024572 0 ustar 00root root 0000000 0000000 When /^I download the file '([^']+)'/ do |url|
unless ENV['REMOTE'] == 'true'
stub_request(:get, "s3.amazonaws.com/Monkey/testfile.txt").
to_return(body: "S3 Remote File", headers: { "Content-Type" => "text/plain" })
end
@uploader.download!(url)
end
carrierwave-1.2.2/features/step_definitions/file_steps.rb 0000664 0000000 0000000 00000003430 13222647327 0023704 0 ustar 00root root 0000000 0000000 ###
# EXISTENCE
Then /^there should be a file at '(.*?)'$/ do |file|
File.exist?(file_path(file)).should be_truthy
end
Then /^there should not be a file at '(.*?)'$/ do |file|
File.exist?(file_path(file)).should be_falsey
end
Then /^there should be a file called '(.*?)' somewhere in a subdirectory of '(.*?)'$/ do |file, directory|
Dir.glob(File.join(file_path(directory), '**', file)).any?.should be_truthy
end
###
# IDENTICAL
Then /^the file at '(.*?)' should be identical to the file at '(.*?)'$/ do |one, two|
File.read(file_path(one)).should == File.read(file_path(two))
end
Then /^the file at '(.*?)' should not be identical to the file at '(.*?)'$/ do |one, two|
File.read(file_path(one)).should_not == File.read(file_path(two))
end
Then /^the file called '(.*?)' in a subdirectory of '(.*?)' should be identical to the file at '(.*?)'$/ do |file, directory, other|
File.read(Dir.glob(File.join(file_path(directory), '**', file)).first).should == File.read(file_path(other))
end
Then /^the file called '(.*?)' in a subdirectory of '(.*?)' should not be identical to the file at '(.*?)'$/ do |file, directory, other|
File.read(Dir.glob(File.join(file_path(directory), '**', file)).first).should_not == File.read(file_path(other))
end
###
# CONTENT
Then /^the file called '([^']+)' in a subdirectory of '([^']+)' should contain '([^']+)'$/ do |file, directory, content|
File.read(Dir.glob(File.join(file_path(directory), '**', file)).first).should include(content)
end
Then /^the file at '([^']+)' should contain '([^']+)'$/ do |path, content|
File.read(file_path(path)).should include(content)
end
###
# REVERSING
Then /^the file at '(.*?)' should be the reverse of the file at '(.*?)'$/ do |one, two|
File.read(file_path(one)).should == File.read(file_path(two)).reverse
end
carrierwave-1.2.2/features/step_definitions/general_steps.rb 0000664 0000000 0000000 00000005432 13222647327 0024406 0 ustar 00root root 0000000 0000000 Given /^an uploader class that uses the '(.*?)' storage$/ do |kind|
@klass = Class.new(CarrierWave::Uploader::Base)
@klass.storage = kind.to_sym
end
Given /^an instance of that class$/ do
@uploader = @klass.new
end
Given /^a processor method named :upcase$/ do
@klass.class_eval do
define_method(:upcase) do
content = File.read(current_path)
File.open(current_path, 'w') { |f| f.write content.upcase }
end
end
end
Then /^the contents of the file should be '(.*?)'$/ do |contents|
@uploader.read.chomp.should == contents
end
Given /^that the uploader reverses the filename$/ do
@klass.class_eval do
def filename
super.reverse unless super.blank?
end
end
end
Given /^that the uploader has the filename overridden to '(.*?)'$/ do |filename|
@klass.class_eval do
define_method(:filename) do
filename
end
end
end
Given /^that the uploader has the store_dir overridden to '(.*?)'$/ do |store_dir|
@klass.class_eval do
define_method(:store_dir) do
file_path(store_dir)
end
end
end
Given /^that the version '(.*?)' has the store_dir overridden to '(.*?)'$/ do |version, store_dir|
@klass.versions[version.to_sym].class_eval do
define_method(:store_dir) do
file_path(store_dir)
end
end
end
Given /^that the uploader class has a version named '([^\']+)'$/ do |name|
@klass.version(name)
end
Given /^that the uploader class has a version named '([^\']+)' which process '([a-zA-Z0-9\_\?!]*)'$/ do |name, processor_name|
@klass.version(name) do
process processor_name.to_sym
end
end
Given /^that the uploader class has a version named '([^\']+)' which is based on version '(.*?)'$/ do |name, based_version_name|
@klass.version(name, {:from_version => based_version_name.to_sym})
end
Given /^yo dawg, I put a version called '(.*?)' in your version called '(.*?)'$/ do |v2, v1|
@klass.version(v1) do
version(v2)
end
end
Given /^the class has a method called 'reverse' that reverses the contents of a file$/ do
@klass.class_eval do
def reverse
text = File.read(current_path)
File.open(current_path, 'w') { |f| f.write(text.reverse) }
end
end
end
Given /^the class will process '([a-zA-Z0-9\_\?!]*)'$/ do |name|
@klass.process name.to_sym
end
Then /^the uploader should have '(.*?)' as its current path$/ do |path|
@uploader.current_path.should == file_path(path)
end
Then /^the uploader should have the url '(.*?)'$/ do |url|
@uploader.url.should == url
end
Then /^the uploader's version '(.*?)' should have the url '(.*?)'$/ do |version, url|
@uploader.versions[version.to_sym].url.should == url
end
Then /^the uploader's nested version '(.*?)' nested in '(.*?)' should have the url '(.*?)'$/ do |v2, v1, url|
@uploader.versions[v1.to_sym].versions[v2.to_sym].url.should == url
end
carrierwave-1.2.2/features/step_definitions/mount_steps.rb 0000664 0000000 0000000 00000001213 13222647327 0024124 0 ustar 00root root 0000000 0000000 When /^I assign the file '([^\']*)' to the '([^\']*)' column$/ do |path, column|
@instance.send("#{column}=", File.open(file_path(path)))
end
Given /^the uploader class is mounted on the '([^\']*)' column$/ do |column|
@mountee_klass.mount_uploader column.to_sym, @klass
end
When /^I retrieve the file later from the cache name for the column '([^\']*)'$/ do |column|
new_instance = @instance.class.new
new_instance.send("#{column}_cache=", @instance.send("#{column}_cache"))
@instance = new_instance
end
Then /^the url for the column '([^\']*)' should be '([^\']*)'$/ do |column, url|
@instance.send("#{column}_url").should == url
end
carrierwave-1.2.2/features/step_definitions/store_steps.rb 0000664 0000000 0000000 00000000671 13222647327 0024125 0 ustar 00root root 0000000 0000000 Given /^the file '(.*?)' is stored at '(.*?)'$/ do |file, stored|
FileUtils.mkdir_p(File.dirname(file_path(stored)))
FileUtils.cp(file_path(file), file_path(stored))
end
When /^I store the file$/ do
@uploader.store!
end
When /^I store the file '(.*?)'$/ do |file|
@uploader.store!(File.open(file_path(file)))
end
When /^I retrieve the file '(.*?)' from the store$/ do |identifier|
@uploader.retrieve_from_store!(identifier)
end
carrierwave-1.2.2/features/support/ 0000775 0000000 0000000 00000000000 13222647327 0017370 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/features/support/activerecord.rb 0000664 0000000 0000000 00000000646 13222647327 0022375 0 ustar 00root root 0000000 0000000 require 'carrierwave/mount'
require File.join(File.dirname(__FILE__), '..', '..', 'spec', 'support', 'activerecord')
class TestMigration < ActiveRecord.version.to_s >= '5.0' ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
def self.up
create_table :users, :force => true do |t|
t.column :avatar, :string
end
end
def self.down
drop_table :users
end
end
Before do
TestMigration.up
end
carrierwave-1.2.2/features/support/env.rb 0000664 0000000 0000000 00000000645 13222647327 0020512 0 ustar 00root root 0000000 0000000 $:.unshift File.expand_path(File.join('..', '..', 'lib'), File.dirname(__FILE__))
require File.join(File.dirname(__FILE__), 'activerecord')
require 'rspec'
require 'carrierwave'
require "webmock/cucumber"
alias :running :lambda
def file_path( *paths )
File.expand_path(File.join('..', *paths), File.dirname(__FILE__))
end
CarrierWave.root = file_path('public')
After do
FileUtils.rm_rf(file_path("public"))
end
carrierwave-1.2.2/features/versions_basics.feature 0000664 0000000 0000000 00000006021 13222647327 0022424 0 ustar 00root root 0000000 0000000 Feature: uploader with file storage and versions
In order to be awesome
As a developer using CarrierWave
I want to upload files to the filesystem
Background:
Given an uploader class that uses the 'file' storage
And that the uploader class has a version named 'thumb'
And an instance of that class
Scenario: store a file
When I store the file 'fixtures/bork.txt'
Then there should be a file at 'public/uploads/bork.txt'
Then there should be a file at 'public/uploads/thumb_bork.txt'
And the file at 'public/uploads/bork.txt' should be identical to the file at 'fixtures/bork.txt'
And the file at 'public/uploads/thumb_bork.txt' should be identical to the file at 'fixtures/bork.txt'
And the uploader should have the url '/uploads/bork.txt'
And the uploader's version 'thumb' should have the url '/uploads/thumb_bork.txt'
Scenario: cache a file and then store it
When I cache the file 'fixtures/bork.txt'
Then there should be a file called 'bork.txt' somewhere in a subdirectory of 'public/uploads/tmp'
Then there should be a file called 'thumb_bork.txt' somewhere in a subdirectory of 'public/uploads/tmp'
And the file called 'bork.txt' in a subdirectory of 'public/uploads/tmp' should be identical to the file at 'fixtures/bork.txt'
And there should not be a file at 'public/uploads/bork.txt'
And there should not be a file at 'public/uploads/thumb_bork.txt'
When I store the file
Then there should be a file at 'public/uploads/bork.txt'
And there should be a file at 'public/uploads/thumb_bork.txt'
And the file at 'public/uploads/bork.txt' should be identical to the file at 'fixtures/bork.txt'
And the file at 'public/uploads/thumb_bork.txt' should be identical to the file at 'fixtures/bork.txt'
And the uploader should have the url '/uploads/bork.txt'
And the uploader's version 'thumb' should have the url '/uploads/thumb_bork.txt'
Scenario: retrieving a file from cache then storing
Given the file 'fixtures/bork.txt' is cached file at 'public/uploads/tmp/1369894322-345-1234-2255/bork.txt'
Given the file 'fixtures/monkey.txt' is cached file at 'public/uploads/tmp/1369894322-345-1234-2255/thumb_bork.txt'
When I retrieve the cache name '1369894322-345-1234-2255/bork.txt' from the cache
And I store the file
Then there should be a file at 'public/uploads/bork.txt'
Then there should be a file at 'public/uploads/thumb_bork.txt'
And the file at 'public/uploads/bork.txt' should be identical to the file at 'fixtures/bork.txt'
And the file at 'public/uploads/thumb_bork.txt' should be identical to the file at 'fixtures/monkey.txt'
Scenario: retrieving a file from store
Given the file 'fixtures/bork.txt' is stored at 'public/uploads/bork.txt'
Given the file 'fixtures/monkey.txt' is stored at 'public/uploads/thumb_bork.txt'
When I retrieve the file 'bork.txt' from the store
Then the uploader should have the url '/uploads/bork.txt'
And the uploader's version 'thumb' should have the url '/uploads/thumb_bork.txt'
carrierwave-1.2.2/features/versions_caching_from_versions.feature 0000664 0000000 0000000 00000004435 13222647327 0025536 0 ustar 00root root 0000000 0000000 Feature: uploader with file storage and versions with overridden store dir
In order to be awesome
As a developer using CarrierWave
I want to upload files to the filesystem
Background:
Given an uploader class that uses the 'file' storage
Given a processor method named :upcase
And that the uploader class has a version named 'thumb' which process 'upcase'
And that the version 'thumb' has the store_dir overridden to 'public/monkey/llama'
And that the uploader class has a version named 'small_thumb' which is based on version 'thumb'
And that the version 'small_thumb' has the store_dir overridden to 'public/monkey/toro'
And an instance of that class
Scenario: cache a file and then store it
When I cache the file 'fixtures/bork.txt'
Then there should be a file called 'bork.txt' somewhere in a subdirectory of 'public/uploads/tmp'
Then there should be a file called 'thumb_bork.txt' somewhere in a subdirectory of 'public/uploads/tmp'
Then there should be a file called 'small_thumb_bork.txt' somewhere in a subdirectory of 'public/uploads/tmp'
And the file called 'bork.txt' in a subdirectory of 'public/uploads/tmp' should be identical to the file at 'fixtures/bork.txt'
And the file called 'thumb_bork.txt' in a subdirectory of 'public/uploads/tmp' should be identical to the file at 'fixtures/upcased_bork.txt'
And the file called 'small_thumb_bork.txt' in a subdirectory of 'public/uploads/tmp' should be identical to the file at 'fixtures/upcased_bork.txt'
And there should not be a file at 'public/uploads/bork.txt'
And there should not be a file at 'public/monkey/llama/thumb_bork.txt'
And there should not be a file at 'public/monkey/toro/small_thumb_bork.txt'
When I store the file
Then there should be a file at 'public/uploads/bork.txt'
Then there should be a file at 'public/monkey/llama/thumb_bork.txt'
Then there should be a file at 'public/monkey/toro/small_thumb_bork.txt'
And the file at 'public/uploads/bork.txt' should be identical to the file at 'fixtures/bork.txt'
And the file at 'public/monkey/llama/thumb_bork.txt' should be identical to the file at 'fixtures/upcased_bork.txt'
And the file at 'public/monkey/toro/small_thumb_bork.txt' should be identical to the file at 'fixtures/upcased_bork.txt' carrierwave-1.2.2/features/versions_nested_versions.feature 0000664 0000000 0000000 00000011772 13222647327 0024403 0 ustar 00root root 0000000 0000000 Feature: uploader with nested versions
In order to optimize performance for processing
As a developer using CarrierWave
I want to set nested versions
Background:
Given an uploader class that uses the 'file' storage
And that the uploader class has a version named 'thumb'
And yo dawg, I put a version called 'mini' in your version called 'thumb'
And yo dawg, I put a version called 'micro' in your version called 'thumb'
And an instance of that class
Scenario: store a file
When I store the file 'fixtures/bork.txt'
Then there should be a file at 'public/uploads/bork.txt'
Then there should be a file at 'public/uploads/thumb_bork.txt'
Then there should be a file at 'public/uploads/thumb_mini_bork.txt'
Then there should be a file at 'public/uploads/thumb_micro_bork.txt'
And the file at 'public/uploads/bork.txt' should be identical to the file at 'fixtures/bork.txt'
And the file at 'public/uploads/thumb_bork.txt' should be identical to the file at 'fixtures/bork.txt'
And the file at 'public/uploads/thumb_mini_bork.txt' should be identical to the file at 'fixtures/bork.txt'
And the file at 'public/uploads/thumb_micro_bork.txt' should be identical to the file at 'fixtures/bork.txt'
And the uploader should have the url '/uploads/bork.txt'
And the uploader's version 'thumb' should have the url '/uploads/thumb_bork.txt'
And the uploader's nested version 'mini' nested in 'thumb' should have the url '/uploads/thumb_mini_bork.txt'
And the uploader's nested version 'micro' nested in 'thumb' should have the url '/uploads/thumb_micro_bork.txt'
Scenario: cache a file and then store it
When I cache the file 'fixtures/bork.txt'
Then there should be a file called 'bork.txt' somewhere in a subdirectory of 'public/uploads/tmp'
Then there should be a file called 'thumb_bork.txt' somewhere in a subdirectory of 'public/uploads/tmp'
And the file called 'bork.txt' in a subdirectory of 'public/uploads/tmp' should be identical to the file at 'fixtures/bork.txt'
And there should not be a file at 'public/uploads/bork.txt'
And there should not be a file at 'public/uploads/thumb_bork.txt'
When I store the file
Then there should be a file at 'public/uploads/bork.txt'
And there should be a file at 'public/uploads/thumb_bork.txt'
And the file at 'public/uploads/bork.txt' should be identical to the file at 'fixtures/bork.txt'
And the file at 'public/uploads/thumb_bork.txt' should be identical to the file at 'fixtures/bork.txt'
And the uploader should have the url '/uploads/bork.txt'
And the uploader's version 'thumb' should have the url '/uploads/thumb_bork.txt'
And the uploader's nested version 'mini' nested in 'thumb' should have the url '/uploads/thumb_mini_bork.txt'
And the uploader's nested version 'micro' nested in 'thumb' should have the url '/uploads/thumb_micro_bork.txt'
Scenario: retrieving a file from cache then storing
Given the file 'fixtures/bork.txt' is cached file at 'public/uploads/tmp/1369894322-345-1234-2255/bork.txt'
Given the file 'fixtures/monkey.txt' is cached file at 'public/uploads/tmp/1369894322-345-1234-2255/thumb_bork.txt'
Given the file 'fixtures/bork.txt' is cached file at 'public/uploads/tmp/1369894322-345-1234-2255/thumb_mini_bork.txt'
Given the file 'fixtures/monkey.txt' is cached file at 'public/uploads/tmp/1369894322-345-1234-2255/thumb_micro_bork.txt'
When I retrieve the cache name '1369894322-345-1234-2255/bork.txt' from the cache
And I store the file
Then there should be a file at 'public/uploads/bork.txt'
Then there should be a file at 'public/uploads/thumb_bork.txt'
Then there should be a file at 'public/uploads/thumb_mini_bork.txt'
Then there should be a file at 'public/uploads/thumb_micro_bork.txt'
And the file at 'public/uploads/bork.txt' should be identical to the file at 'fixtures/bork.txt'
And the file at 'public/uploads/thumb_bork.txt' should be identical to the file at 'fixtures/monkey.txt'
And the file at 'public/uploads/thumb_mini_bork.txt' should be identical to the file at 'fixtures/bork.txt'
And the file at 'public/uploads/thumb_micro_bork.txt' should be identical to the file at 'fixtures/monkey.txt'
Scenario: retrieving a file from store
Given the file 'fixtures/bork.txt' is stored at 'public/uploads/bork.txt'
Given the file 'fixtures/monkey.txt' is stored at 'public/uploads/thumb_bork.txt'
Given the file 'fixtures/monkey.txt' is stored at 'public/uploads/thumb_mini_bork.txt'
Given the file 'fixtures/monkey.txt' is stored at 'public/uploads/thumb_micro_bork.txt'
When I retrieve the file 'bork.txt' from the store
Then the uploader should have the url '/uploads/bork.txt'
And the uploader's version 'thumb' should have the url '/uploads/thumb_bork.txt'
And the uploader's nested version 'mini' nested in 'thumb' should have the url '/uploads/thumb_mini_bork.txt'
And the uploader's nested version 'micro' nested in 'thumb' should have the url '/uploads/thumb_micro_bork.txt'
carrierwave-1.2.2/features/versions_overridden_filename.feature 0000664 0000000 0000000 00000006413 13222647327 0025166 0 ustar 00root root 0000000 0000000 Feature: uploader with file storage and overriden filename
In order to customize the filaname of uploaded files
As a developer using CarrierWave
I want to upload files to the filesystem with an overriden filename and different verions
Background:
Given an uploader class that uses the 'file' storage
And that the uploader class has a version named 'thumb'
And that the uploader has the filename overridden to 'grark.png'
And an instance of that class
Scenario: store a file
When I store the file 'fixtures/bork.txt'
Then there should be a file at 'public/uploads/grark.png'
Then there should be a file at 'public/uploads/thumb_grark.png'
And the file at 'public/uploads/grark.png' should be identical to the file at 'fixtures/bork.txt'
And the file at 'public/uploads/thumb_grark.png' should be identical to the file at 'fixtures/bork.txt'
And the uploader should have the url '/uploads/grark.png'
And the uploader's version 'thumb' should have the url '/uploads/thumb_grark.png'
Scenario: cache a file and then store it
When I cache the file 'fixtures/bork.txt'
Then there should be a file called 'bork.txt' somewhere in a subdirectory of 'public/uploads/tmp'
Then there should be a file called 'thumb_bork.txt' somewhere in a subdirectory of 'public/uploads/tmp'
And the file called 'bork.txt' in a subdirectory of 'public/uploads/tmp' should be identical to the file at 'fixtures/bork.txt'
And there should not be a file at 'public/uploads/grark.png'
And there should not be a file at 'public/uploads/thumb_grark.png'
When I store the file
Then there should be a file at 'public/uploads/grark.png'
And there should be a file at 'public/uploads/thumb_grark.png'
And the file at 'public/uploads/grark.png' should be identical to the file at 'fixtures/bork.txt'
And the file at 'public/uploads/thumb_grark.png' should be identical to the file at 'fixtures/bork.txt'
And the uploader should have the url '/uploads/grark.png'
And the uploader's version 'thumb' should have the url '/uploads/thumb_grark.png'
Scenario: retrieving a file from cache then storing
Given the file 'fixtures/bork.txt' is cached file at 'public/uploads/tmp/1369894322-345-1234-2255/bork.txt'
Given the file 'fixtures/monkey.txt' is cached file at 'public/uploads/tmp/1369894322-345-1234-2255/thumb_bork.txt'
When I retrieve the cache name '1369894322-345-1234-2255/bork.txt' from the cache
And I store the file
Then there should be a file at 'public/uploads/grark.png'
Then there should be a file at 'public/uploads/thumb_grark.png'
And the file at 'public/uploads/grark.png' should be identical to the file at 'fixtures/bork.txt'
And the file at 'public/uploads/thumb_grark.png' should be identical to the file at 'fixtures/monkey.txt'
Scenario: retrieving a file from store
Given the file 'fixtures/bork.txt' is stored at 'public/uploads/bork.txt'
Given the file 'fixtures/monkey.txt' is stored at 'public/uploads/thumb_bork.txt'
When I retrieve the file 'bork.txt' from the store
Then the uploader should have the url '/uploads/bork.txt'
And the uploader's version 'thumb' should have the url '/uploads/thumb_bork.txt'
carrierwave-1.2.2/features/versions_overriden_store_dir.feature 0000664 0000000 0000000 00000005164 13222647327 0025236 0 ustar 00root root 0000000 0000000 Feature: uploader with file storage and versions with overridden store dir
In order to be awesome
As a developer using CarrierWave
I want to upload files to the filesystem
Background:
Given an uploader class that uses the 'file' storage
And that the uploader class has a version named 'thumb'
And that the version 'thumb' has the store_dir overridden to 'public/monkey/llama'
And an instance of that class
Scenario: store a file
When I store the file 'fixtures/bork.txt'
Then there should be a file at 'public/uploads/bork.txt'
Then there should be a file at 'public/monkey/llama/thumb_bork.txt'
And the file at 'public/uploads/bork.txt' should be identical to the file at 'fixtures/bork.txt'
And the file at 'public/monkey/llama/thumb_bork.txt' should be identical to the file at 'fixtures/bork.txt'
Scenario: cache a file and then store it
When I cache the file 'fixtures/bork.txt'
Then there should be a file called 'bork.txt' somewhere in a subdirectory of 'public/uploads/tmp'
Then there should be a file called 'thumb_bork.txt' somewhere in a subdirectory of 'public/uploads/tmp'
And the file called 'bork.txt' in a subdirectory of 'public/uploads/tmp' should be identical to the file at 'fixtures/bork.txt'
And the file called 'thumb_bork.txt' in a subdirectory of 'public/uploads/tmp' should be identical to the file at 'fixtures/bork.txt'
And there should not be a file at 'public/uploads/bork.txt'
And there should not be a file at 'public/monkey/llama/thumb_bork.txt'
When I store the file
Then there should be a file at 'public/uploads/bork.txt'
Then there should be a file at 'public/monkey/llama/thumb_bork.txt'
And the file at 'public/uploads/bork.txt' should be identical to the file at 'fixtures/bork.txt'
And the file at 'public/monkey/llama/thumb_bork.txt' should be identical to the file at 'fixtures/bork.txt'
Scenario: retrieving a file from cache then storing
Given the file 'fixtures/bork.txt' is cached file at 'public/uploads/tmp/1369894322-345-1234-2255/bork.txt'
Given the file 'fixtures/monkey.txt' is cached file at 'public/uploads/tmp/1369894322-345-1234-2255/thumb_bork.txt'
When I retrieve the cache name '1369894322-345-1234-2255/bork.txt' from the cache
And I store the file
Then there should be a file at 'public/uploads/bork.txt'
Then there should be a file at 'public/monkey/llama/thumb_bork.txt'
And the file at 'public/uploads/bork.txt' should be identical to the file at 'fixtures/bork.txt'
And the file at 'public/monkey/llama/thumb_bork.txt' should be identical to the file at 'fixtures/monkey.txt'
carrierwave-1.2.2/gemfiles/ 0000775 0000000 0000000 00000000000 13222647327 0015631 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/gemfiles/rails-4-0.gemfile 0000664 0000000 0000000 00000000261 13222647327 0020572 0 ustar 00root root 0000000 0000000 source "https://rubygems.org"
gem "rails", "~> 4.0.0"
gem "railties", "~> 4.0.0"
gem "activerecord-jdbcpostgresql-adapter", "~> 1.3", platforms: :jruby
gemspec :path => "../"
carrierwave-1.2.2/gemfiles/rails-4-1.gemfile 0000664 0000000 0000000 00000000226 13222647327 0020574 0 ustar 00root root 0000000 0000000 source "https://rubygems.org"
gem "rails", "~> 4.1.0"
gem "activerecord-jdbcpostgresql-adapter", "~> 1.3", platforms: :jruby
gemspec :path => "../"
carrierwave-1.2.2/gemfiles/rails-4-2.gemfile 0000664 0000000 0000000 00000000226 13222647327 0020575 0 ustar 00root root 0000000 0000000 source "https://rubygems.org"
gem "rails", "~> 4.2.0"
gem "activerecord-jdbcpostgresql-adapter", "~> 1.3", platforms: :jruby
gemspec :path => "../"
carrierwave-1.2.2/gemfiles/rails-5-0.gemfile 0000664 0000000 0000000 00000000271 13222647327 0020574 0 ustar 00root root 0000000 0000000 source "https://rubygems.org"
gem "rails", "~> 5.0.0"
gem "activemodel-serializers-xml"
gem "activerecord-jdbcpostgresql-adapter", "~> 50.0", platforms: :jruby
gemspec :path => "../"
carrierwave-1.2.2/gemfiles/rails-5-1.gemfile 0000664 0000000 0000000 00000000271 13222647327 0020575 0 ustar 00root root 0000000 0000000 source "https://rubygems.org"
gem "rails", "~> 5.1.0"
gem "activemodel-serializers-xml"
gem "activerecord-jdbcpostgresql-adapter", "~> 51.0", platforms: :jruby
gemspec :path => "../"
carrierwave-1.2.2/gemfiles/rails-master.gemfile 0000664 0000000 0000000 00000001041 13222647327 0021562 0 ustar 00root root 0000000 0000000 source "https://rubygems.org"
gem "rails", github: "rails/rails", branch: "master"
gem "rack", github: "rack/rack", branch: "master"
gem "arel", github: "rails/arel", branch: "master"
gem "sprockets", github: "rails/sprockets", branch: "master"
gem "sprockets-rails", github: "rails/sprockets-rails", branch: "master"
gem "sass-rails", github: "rails/sass-rails"
gem "activemodel-serializers-xml"
gem "activerecord-jdbcpostgresql-adapter", github: "jruby/activerecord-jdbc-adapter", branch: "rails-5", platforms: :jruby
gemspec :path => "../"
carrierwave-1.2.2/lib/ 0000775 0000000 0000000 00000000000 13222647327 0014604 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/lib/carrierwave.rb 0000664 0000000 0000000 00000004510 13222647327 0017443 0 ustar 00root root 0000000 0000000 require 'fileutils'
require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/object/try'
require 'active_support/core_ext/class/attribute'
require 'active_support/concern'
module CarrierWave
class << self
attr_accessor :root, :base_path
attr_writer :tmp_path
def configure(&block)
CarrierWave::Uploader::Base.configure(&block)
end
def clean_cached_files!(seconds=60*60*24)
CarrierWave::Uploader::Base.clean_cached_files!(seconds)
end
def tmp_path
@tmp_path ||= File.expand_path(File.join('..', 'tmp'), root)
end
end
end
if defined?(Merb)
CarrierWave.root = Merb.dir_for(:public)
Merb::BootLoader.before_app_loads do
# Setup path for uploaders and load all of them before classes are loaded
Merb.push_path(:uploaders, Merb.root / 'app' / 'uploaders', '*.rb')
Dir.glob(File.join(Merb.load_paths[:uploaders])).each {|f| require f }
end
elsif defined?(Rails)
module CarrierWave
class Railtie < Rails::Railtie
initializer "carrierwave.setup_paths" do |app|
CarrierWave.root = Rails.root.join(Rails.public_path).to_s
CarrierWave.base_path = ENV['RAILS_RELATIVE_URL_ROOT']
available_locales = Array(app.config.i18n.available_locales || [])
if available_locales.blank? || available_locales.include?(:en)
I18n.load_path.prepend(File.join(File.dirname(__FILE__), 'carrierwave', 'locale', "en.yml"))
end
end
initializer "carrierwave.active_record" do
ActiveSupport.on_load :active_record do
require 'carrierwave/orm/activerecord'
end
end
end
end
elsif defined?(Sinatra)
if defined?(Padrino) && defined?(PADRINO_ROOT)
CarrierWave.root = File.join(PADRINO_ROOT, "public")
else
CarrierWave.root = if Sinatra::Application.respond_to?(:public_folder)
# Sinatra >= 1.3
Sinatra::Application.public_folder
else
# Sinatra < 1.3
Sinatra::Application.public
end
end
end
require "carrierwave/utilities"
require "carrierwave/error"
require "carrierwave/sanitized_file"
require "carrierwave/mounter"
require "carrierwave/mount"
require "carrierwave/processing"
require "carrierwave/version"
require "carrierwave/storage"
require "carrierwave/uploader"
require "carrierwave/compatibility/paperclip"
require "carrierwave/test/matchers"
carrierwave-1.2.2/lib/carrierwave/ 0000775 0000000 0000000 00000000000 13222647327 0017116 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/lib/carrierwave/compatibility/ 0000775 0000000 0000000 00000000000 13222647327 0021767 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/lib/carrierwave/compatibility/paperclip.rb 0000664 0000000 0000000 00000007203 13222647327 0024275 0 ustar 00root root 0000000 0000000 module CarrierWave
module Compatibility
##
# Mix this module into an Uploader to make it mimic Paperclip's storage paths
# This will make your Uploader use the same default storage path as paperclip
# does. If you need to override it, you can override the +paperclip_path+ method
# and provide a Paperclip style path:
#
# class MyUploader < CarrierWave::Uploader::Base
# include CarrierWave::Compatibility::Paperclip
#
# def paperclip_path
# ":rails_root/public/uploads/:id/:attachment/:style_:basename.:extension"
# end
# end
#
# ---
#
# This file contains code taken from Paperclip
#
# LICENSE
#
# The MIT License
#
# Copyright (c) 2008 Jon Yurek and thoughtbot, inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
module Paperclip
extend ActiveSupport::Concern
DEFAULT_MAPPINGS = {
:rails_root => lambda{|u, f| Rails.root.to_s },
:rails_env => lambda{|u, f| Rails.env },
:id_partition => lambda{|u, f| ("%09d" % u.model.id).scan(/\d{3}/).join("/")},
:id => lambda{|u, f| u.model.id },
:attachment => lambda{|u, f| u.mounted_as.to_s.downcase.pluralize },
:style => lambda{|u, f| u.paperclip_style },
:basename => lambda{|u, f| u.filename.gsub(/#{File.extname(u.filename)}$/, "") },
:extension => lambda{|u, d| File.extname(u.filename).gsub(/^\.+/, "")},
:class => lambda{|u, f| u.model.class.name.underscore.pluralize}
}
included do
attr_accessor :filename
class_attribute :mappings
self.mappings ||= DEFAULT_MAPPINGS.dup
end
def store_path(for_file=filename)
path = paperclip_path
self.filename = for_file
path ||= File.join(*[store_dir, paperclip_style.to_s, for_file].compact)
interpolate_paperclip_path(path)
end
def store_dir
":rails_root/public/system/:attachment/:id"
end
def paperclip_default_style
:original
end
def paperclip_path
end
def paperclip_style
version_name || paperclip_default_style
end
module ClassMethods
def interpolate(sym, &block)
mappings[sym] = block
end
end
private
def interpolate_paperclip_path(path)
mappings.each_pair.inject(path) do |agg, pair|
agg.gsub(":#{pair[0]}") { pair[1].call(self, self.paperclip_style).to_s }
end
end
end # Paperclip
end # Compatibility
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/error.rb 0000664 0000000 0000000 00000000433 13222647327 0020574 0 ustar 00root root 0000000 0000000 module CarrierWave
class UploadError < StandardError; end
class IntegrityError < UploadError; end
class InvalidParameter < UploadError; end
class ProcessingError < UploadError; end
class DownloadError < UploadError; end
class UnknownStorageError < StandardError; end
end
carrierwave-1.2.2/lib/carrierwave/locale/ 0000775 0000000 0000000 00000000000 13222647327 0020355 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/lib/carrierwave/locale/en.yml 0000664 0000000 0000000 00000001730 13222647327 0021503 0 ustar 00root root 0000000 0000000 en:
errors:
messages:
carrierwave_processing_error: failed to be processed
carrierwave_integrity_error: is not of an allowed file type
carrierwave_download_error: could not be downloaded
extension_whitelist_error: "You are not allowed to upload %{extension} files, allowed types: %{allowed_types}"
extension_blacklist_error: "You are not allowed to upload %{extension} files, prohibited types: %{prohibited_types}"
content_type_whitelist_error: "You are not allowed to upload %{content_type} files"
content_type_blacklist_error: "You are not allowed to upload %{content_type} files"
rmagick_processing_error: "Failed to manipulate with rmagick, maybe it is not an image?"
mini_magick_processing_error: "Failed to manipulate with MiniMagick, maybe it is not an image? Original Error: %{e}"
min_size_error: "File size should be greater than %{min_size}"
max_size_error: "File size should be less than %{max_size}"
carrierwave-1.2.2/lib/carrierwave/mount.rb 0000664 0000000 0000000 00000036502 13222647327 0020613 0 ustar 00root root 0000000 0000000 module CarrierWave
##
# If a Class is extended with this module, it gains the mount_uploader
# method, which is used for mapping attributes to uploaders and allowing
# easy assignment.
#
# You can use mount_uploader with pretty much any class, however it is
# intended to be used with some kind of persistent storage, like an ORM.
# If you want to persist the uploaded files in a particular Class, it
# needs to implement a `read_uploader` and a `write_uploader` method.
#
module Mount
##
# === Returns
#
# [Hash{Symbol => CarrierWave}] what uploaders are mounted on which columns
#
def uploaders
@uploaders ||= superclass.respond_to?(:uploaders) ? superclass.uploaders.dup : {}
end
def uploader_options
@uploader_options ||= superclass.respond_to?(:uploader_options) ? superclass.uploader_options.dup : {}
end
##
# Return a particular option for a particular uploader
#
# === Parameters
#
# [column (Symbol)] The column the uploader is mounted at
# [option (Symbol)] The option, e.g. validate_integrity
#
# === Returns
#
# [Object] The option value
#
def uploader_option(column, option)
if uploader_options[column].has_key?(option)
uploader_options[column][option]
else
uploaders[column].send(option)
end
end
##
# Mounts the given uploader on the given column. This means that assigning
# and reading from the column will upload and retrieve files. Supposing
# that a User class has an uploader mounted on image, you can assign and
# retrieve files like this:
#
# @user.image # =>
# @user.image.store!(some_file_object)
#
# @user.image.url # => '/some_url.png'
#
# It is also possible (but not recommended) to omit the uploader, which
# will create an anonymous uploader class.
#
# Passing a block makes it possible to customize the uploader. This can be
# convenient for brevity, but if there is any significant logic in the
# uploader, you should do the right thing and have it in its own file.
#
# === Added instance methods
#
# Supposing a class has used +mount_uploader+ to mount an uploader on a column
# named +image+, in that case the following methods will be added to the class:
#
# [image] Returns an instance of the uploader only if anything has been uploaded
# [image=] Caches the given file
#
# [image_url] Returns the url to the uploaded file
#
# [image_cache] Returns a string that identifies the cache location of the file
# [image_cache=] Retrieves the file from the cache based on the given cache name
#
# [remote_image_url] Returns previously cached remote url
# [remote_image_url=] Retrieve the file from the remote url
#
# [remove_image] An attribute reader that can be used with a checkbox to mark a file for removal
# [remove_image=] An attribute writer that can be used with a checkbox to mark a file for removal
# [remove_image?] Whether the file should be removed when store_image! is called.
#
# [store_image!] Stores a file that has been assigned with +image=+
# [remove_image!] Removes the uploaded file from the filesystem.
#
# [image_integrity_error] Returns an error object if the last file to be assigned caused an integrity error
# [image_processing_error] Returns an error object if the last file to be assigned caused a processing error
# [image_download_error] Returns an error object if the last file to be remotely assigned caused a download error
#
# [image_identifier] Reads out the identifier of the file
#
# === Parameters
#
# [column (Symbol)] the attribute to mount this uploader on
# [uploader (CarrierWave::Uploader)] the uploader class to mount
# [options (Hash{Symbol => Object})] a set of options
# [&block (Proc)] customize anonymous uploaders
#
# === Options
#
# [:mount_on => Symbol] if the name of the column to be serialized to differs you can override it using this option
# [:ignore_integrity_errors => Boolean] if set to true, integrity errors will result in caching failing silently
# [:ignore_processing_errors => Boolean] if set to true, processing errors will result in caching failing silently
#
# === Examples
#
# Mounting uploaders on different columns.
#
# class Song
# mount_uploader :lyrics, LyricsUploader
# mount_uploader :alternative_lyrics, LyricsUploader
# mount_uploader :file, SongUploader
# end
#
# This will add an anonymous uploader with only the default settings:
#
# class Data
# mount_uploader :csv
# end
#
# this will add an anonymous uploader overriding the store_dir:
#
# class Product
# mount_uploader :blueprint do
# def store_dir
# 'blueprints'
# end
# end
# end
#
def mount_uploader(column, uploader=nil, options={}, &block)
mount_base(column, uploader, options, &block)
mod = Module.new
include mod
mod.class_eval <<-RUBY, __FILE__, __LINE__+1
def #{column}
_mounter(:#{column}).uploaders[0] ||= _mounter(:#{column}).blank_uploader
end
def #{column}=(new_file)
_mounter(:#{column}).cache([new_file])
end
def #{column}_url(*args)
#{column}.url(*args)
end
def #{column}_cache
_mounter(:#{column}).cache_names[0]
end
def #{column}_cache=(cache_name)
_mounter(:#{column}).cache_names = [cache_name]
end
def remote_#{column}_url
[_mounter(:#{column}).remote_urls].flatten[0]
end
def remote_#{column}_url=(url)
_mounter(:#{column}).remote_urls = [url]
end
def remote_#{column}_request_header=(header)
_mounter(:#{column}).remote_request_headers = [header]
end
def write_#{column}_identifier
return if frozen?
mounter = _mounter(:#{column})
if mounter.remove?
write_uploader(mounter.serialization_column, nil)
elsif mounter.identifiers.first
write_uploader(mounter.serialization_column, mounter.identifiers.first)
end
end
def #{column}_identifier
_mounter(:#{column}).read_identifiers[0]
end
def store_previous_changes_for_#{column}
attribute_changes = ::ActiveRecord.version.to_s.to_f >= 5.1 ? saved_changes : changes
@_previous_changes_for_#{column} = attribute_changes[_mounter(:#{column}).serialization_column]
end
def remove_previously_stored_#{column}
before, after = @_previous_changes_for_#{column}
_mounter(:#{column}).remove_previous([before], [after])
end
RUBY
end
##
# Mounts the given uploader on the given array column. This means that
# assigning and reading from the array column will upload and retrieve
# multiple files. Supposing that a User class has an uploader mounted on
# images, and that images can store an array, for example it could be a
# PostgreSQL JSON column. You can assign and retrieve files like this:
#
# @user.images # => []
# @user.images = [some_file_object]
# @user.images # => []
#
# @user.images[0].url # => '/some_url.png'
#
# It is also possible (but not recommended) to omit the uploader, which
# will create an anonymous uploader class.
#
# Passing a block makes it possible to customize the uploader. This can be
# convenient for brevity, but if there is any significant logic in the
# uploader, you should do the right thing and have it in its own file.
#
# === Added instance methods
#
# Supposing a class has used +mount_uploaders+ to mount an uploader on a column
# named +images+, in that case the following methods will be added to the class:
#
# [images] Returns an array of uploaders for each uploaded file
# [images=] Caches the given files
#
# [images_urls] Returns the urls to the uploaded files
#
# [images_cache] Returns a string that identifies the cache location of the files
# [images_cache=] Retrieves the files from the cache based on the given cache name
#
# [remote_image_urls] Returns previously cached remote urls
# [remote_image_urls=] Retrieve files from the given remote urls
#
# [remove_images] An attribute reader that can be used with a checkbox to mark the files for removal
# [remove_images=] An attribute writer that can be used with a checkbox to mark the files for removal
# [remove_images?] Whether the files should be removed when store_image! is called.
#
# [store_images!] Stores all files that have been assigned with +images=+
# [remove_images!] Removes the uploaded file from the filesystem.
#
# [images_integrity_error] Returns an error object if the last files to be assigned caused an integrity error
# [images_processing_error] Returns an error object if the last files to be assigned caused a processing error
# [images_download_error] Returns an error object if the last files to be remotely assigned caused a download error
#
# [image_identifiers] Reads out the identifiers of the files
#
# === Parameters
#
# [column (Symbol)] the attribute to mount this uploader on
# [uploader (CarrierWave::Uploader)] the uploader class to mount
# [options (Hash{Symbol => Object})] a set of options
# [&block (Proc)] customize anonymous uploaders
#
# === Options
#
# [:mount_on => Symbol] if the name of the column to be serialized to differs you can override it using this option
# [:ignore_integrity_errors => Boolean] if set to true, integrity errors will result in caching failing silently
# [:ignore_processing_errors => Boolean] if set to true, processing errors will result in caching failing silently
#
# === Examples
#
# Mounting uploaders on different columns.
#
# class Song
# mount_uploaders :lyrics, LyricsUploader
# mount_uploaders :alternative_lyrics, LyricsUploader
# mount_uploaders :files, SongUploader
# end
#
# This will add an anonymous uploader with only the default settings:
#
# class Data
# mount_uploaders :csv_files
# end
#
# this will add an anonymous uploader overriding the store_dir:
#
# class Product
# mount_uploaders :blueprints do
# def store_dir
# 'blueprints'
# end
# end
# end
#
def mount_uploaders(column, uploader=nil, options={}, &block)
mount_base(column, uploader, options, &block)
mod = Module.new
include mod
mod.class_eval <<-RUBY, __FILE__, __LINE__+1
def #{column}
_mounter(:#{column}).uploaders
end
def #{column}=(new_files)
_mounter(:#{column}).cache(new_files)
end
def #{column}_urls(*args)
_mounter(:#{column}).urls(*args)
end
def #{column}_cache
names = _mounter(:#{column}).cache_names
names.to_json if names.present?
end
def #{column}_cache=(cache_name)
_mounter(:#{column}).cache_names = JSON.parse(cache_name) if cache_name.present?
end
def remote_#{column}_urls
_mounter(:#{column}).remote_urls
end
def remote_#{column}_urls=(urls)
_mounter(:#{column}).remote_urls = urls
end
def remote_#{column}_request_headers=(headers)
_mounter(:#{column}).remote_request_headers = headers
end
def write_#{column}_identifier
return if frozen?
mounter = _mounter(:#{column})
if mounter.remove?
write_uploader(mounter.serialization_column, nil)
elsif mounter.identifiers.any?
write_uploader(mounter.serialization_column, mounter.identifiers)
end
end
def #{column}_identifiers
_mounter(:#{column}).read_identifiers
end
def store_previous_changes_for_#{column}
attribute_changes = ::ActiveRecord.version.to_s.to_f >= 5.1 ? saved_changes : changes
@_previous_changes_for_#{column} = attribute_changes[_mounter(:#{column}).serialization_column]
end
def remove_previously_stored_#{column}
_mounter(:#{column}).remove_previous(*@_previous_changes_for_#{column})
end
RUBY
end
private
def mount_base(column, uploader=nil, options={}, &block)
include CarrierWave::Mount::Extension
uploader = build_uploader(uploader, &block)
uploaders[column.to_sym] = uploader
uploader_options[column.to_sym] = options
# Make sure to write over accessors directly defined on the class.
# Simply super to the included module below.
class_eval <<-RUBY, __FILE__, __LINE__+1
def #{column}; super; end
def #{column}=(new_file); super; end
RUBY
mod = Module.new
include mod
mod.class_eval <<-RUBY, __FILE__, __LINE__+1
def #{column}?
_mounter(:#{column}).present?
end
def remove_#{column}
_mounter(:#{column}).remove
end
def remove_#{column}!
_mounter(:#{column}).remove!
end
def remove_#{column}=(value)
_mounter(:#{column}).remove = value
end
def remove_#{column}?
_mounter(:#{column}).remove?
end
def store_#{column}!
_mounter(:#{column}).store!
end
def #{column}_integrity_error
_mounter(:#{column}).integrity_error
end
def #{column}_processing_error
_mounter(:#{column}).processing_error
end
def #{column}_download_error
_mounter(:#{column}).download_error
end
def mark_remove_#{column}_false
_mounter(:#{column}).remove = false
end
RUBY
end
def build_uploader(uploader, &block)
return uploader if uploader && !block_given?
uploader = Class.new(uploader || CarrierWave::Uploader::Base)
const_set("Uploader#{uploader.object_id}".tr('-', '_'), uploader)
if block_given?
uploader.class_eval(&block)
uploader.recursively_apply_block_to_versions(&block)
end
uploader
end
module Extension
##
# overwrite this to read from a serialized attribute
#
def read_uploader(column); end
##
# overwrite this to write to a serialized attribute
#
def write_uploader(column, identifier); end
private
def _mounter(column)
# We cannot memoize in frozen objects :(
return Mounter.new(self, column) if frozen?
@_mounters ||= {}
@_mounters[column] ||= Mounter.new(self, column)
end
end # Extension
end # Mount
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/mounter.rb 0000664 0000000 0000000 00000010267 13222647327 0021142 0 ustar 00root root 0000000 0000000 module CarrierWave
# this is an internal class, used by CarrierWave::Mount so that
# we don't pollute the model with a lot of methods.
class Mounter #:nodoc:
attr_reader :column, :record, :remote_urls, :integrity_error,
:processing_error, :download_error
attr_accessor :remove, :remote_request_headers
def initialize(record, column, options={})
@record = record
@column = column
@options = record.class.uploader_options[column]
end
def uploader_class
record.class.uploaders[column]
end
def blank_uploader
uploader_class.new(record, column)
end
def identifiers
uploaders.map(&:identifier)
end
def read_identifiers
[record.read_uploader(serialization_column)].flatten.reject(&:blank?)
end
def uploaders
@uploaders ||= read_identifiers.map do |identifier|
uploader = blank_uploader
uploader.retrieve_from_store!(identifier) if identifier.present?
uploader
end
end
def cache(new_files)
return if not new_files or new_files == ""
@uploaders = new_files.map do |new_file|
uploader = blank_uploader
uploader.cache!(new_file)
uploader
end
@integrity_error = nil
@processing_error = nil
rescue CarrierWave::IntegrityError => e
@integrity_error = e
raise e unless option(:ignore_integrity_errors)
rescue CarrierWave::ProcessingError => e
@processing_error = e
raise e unless option(:ignore_processing_errors)
end
def cache_names
uploaders.map(&:cache_name).compact
end
def cache_names=(cache_names)
return if not cache_names or cache_names == "" or uploaders.any?(&:cached?)
@uploaders = cache_names.map do |cache_name|
uploader = blank_uploader
uploader.retrieve_from_cache!(cache_name)
uploader
end
rescue CarrierWave::InvalidParameter
end
def remote_urls=(urls)
return if not urls or urls == "" or urls.all?(&:blank?)
@remote_urls = urls
@download_error = nil
@integrity_error = nil
@uploaders = urls.zip(remote_request_headers || []).map do |url, header|
uploader = blank_uploader
uploader.download!(url, header || {})
uploader
end
rescue CarrierWave::DownloadError => e
@download_error = e
raise e unless option(:ignore_download_errors)
rescue CarrierWave::ProcessingError => e
@processing_error = e
raise e unless option(:ignore_processing_errors)
rescue CarrierWave::IntegrityError => e
@integrity_error = e
raise e unless option(:ignore_integrity_errors)
end
def store!
if remove?
remove!
else
uploaders.reject(&:blank?).each(&:store!)
end
end
def urls(*args)
uploaders.map { |u| u.url(*args) }
end
def blank?
uploaders.none?(&:present?)
end
def remove?
remove.present? && remove !~ /\A0|false$\z/
end
def remove!
uploaders.reject(&:blank?).each(&:remove!)
@uploaders = []
end
def serialization_column
option(:mount_on) || column
end
def remove_previous(before=nil, after=nil)
after ||= []
return unless before
# both 'before' and 'after' can be string when 'mount_on' option is set
before = before.reject(&:blank?).map do |value|
if value.is_a?(String)
uploader = blank_uploader
uploader.retrieve_from_store!(value)
uploader
else
value
end
end
after_paths = after.reject(&:blank?).map do |value|
if value.is_a?(String)
uploader = blank_uploader
uploader.retrieve_from_store!(value)
uploader
else
value
end.path
end
before.each do |uploader|
if uploader.remove_previously_stored_files_after_update and not after_paths.include?(uploader.path)
uploader.remove!
end
end
end
attr_accessor :uploader_options
private
def option(name)
self.uploader_options ||= {}
self.uploader_options[name] ||= record.class.uploader_option(column, name)
end
end # Mounter
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/orm/ 0000775 0000000 0000000 00000000000 13222647327 0017713 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/lib/carrierwave/orm/activerecord.rb 0000664 0000000 0000000 00000005473 13222647327 0022723 0 ustar 00root root 0000000 0000000 require 'active_record'
require 'carrierwave/validations/active_model'
module CarrierWave
module ActiveRecord
include CarrierWave::Mount
##
# See +CarrierWave::Mount#mount_uploader+ for documentation
#
def mount_uploader(column, uploader=nil, options={}, &block)
super
class_eval <<-RUBY, __FILE__, __LINE__+1
def remote_#{column}_url=(url)
column = _mounter(:#{column}).serialization_column
__send__(:"\#{column}_will_change!")
super
end
RUBY
end
##
# See +CarrierWave::Mount#mount_uploaders+ for documentation
#
def mount_uploaders(column, uploader=nil, options={}, &block)
super
class_eval <<-RUBY, __FILE__, __LINE__+1
def remote_#{column}_urls=(url)
column = _mounter(:#{column}).serialization_column
__send__(:"\#{column}_will_change!")
super
end
RUBY
end
private
def mount_base(column, uploader=nil, options={}, &block)
super
alias_method :read_uploader, :read_attribute
alias_method :write_uploader, :write_attribute
public :read_uploader
public :write_uploader
include CarrierWave::Validations::ActiveModel
validates_integrity_of column if uploader_option(column.to_sym, :validate_integrity)
validates_processing_of column if uploader_option(column.to_sym, :validate_processing)
validates_download_of column if uploader_option(column.to_sym, :validate_download)
after_save :"store_#{column}!"
before_save :"write_#{column}_identifier"
after_commit :"remove_#{column}!", :on => :destroy
after_commit :"mark_remove_#{column}_false", :on => :update
after_save :"store_previous_changes_for_#{column}"
after_commit :"remove_previously_stored_#{column}", :on => :update
class_eval <<-RUBY, __FILE__, __LINE__+1
def #{column}=(new_file)
column = _mounter(:#{column}).serialization_column
if !(new_file.blank? && __send__(:#{column}).blank?)
__send__(:"\#{column}_will_change!")
end
super
end
def remove_#{column}=(value)
column = _mounter(:#{column}).serialization_column
__send__(:"\#{column}_will_change!")
super
end
def remove_#{column}!
self.remove_#{column} = true
write_#{column}_identifier
self.remove_#{column} = false
super
end
# Reset cached mounter on record reload
def reload(*)
@_mounters = nil
super
end
# Reset cached mounter on record dup
def initialize_dup(other)
@_mounters = nil
super
end
RUBY
end
end # ActiveRecord
end # CarrierWave
ActiveRecord::Base.extend CarrierWave::ActiveRecord
carrierwave-1.2.2/lib/carrierwave/processing.rb 0000664 0000000 0000000 00000000126 13222647327 0021616 0 ustar 00root root 0000000 0000000 require "carrierwave/processing/rmagick"
require "carrierwave/processing/mini_magick"
carrierwave-1.2.2/lib/carrierwave/processing/ 0000775 0000000 0000000 00000000000 13222647327 0021272 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/lib/carrierwave/processing/mini_magick.rb 0000664 0000000 0000000 00000023756 13222647327 0024103 0 ustar 00root root 0000000 0000000 module CarrierWave
##
# This module simplifies manipulation with MiniMagick by providing a set
# of convenient helper methods. If you want to use them, you'll need to
# require this file:
#
# require 'carrierwave/processing/mini_magick'
#
# And then include it in your uploader:
#
# class MyUploader < CarrierWave::Uploader::Base
# include CarrierWave::MiniMagick
# end
#
# You can now use the provided helpers:
#
# class MyUploader < CarrierWave::Uploader::Base
# include CarrierWave::MiniMagick
#
# process :resize_to_fit => [200, 200]
# end
#
# Or create your own helpers with the powerful manipulate! method. Check
# out the ImageMagick docs at http://www.imagemagick.org/script/command-line-options.php for more
# info
#
# class MyUploader < CarrierWave::Uploader::Base
# include CarrierWave::MiniMagick
#
# process :radial_blur => 10
#
# def radial_blur(amount)
# manipulate! do |img|
# img.radial_blur(amount)
# img = yield(img) if block_given?
# img
# end
# end
# end
#
# === Note
#
# MiniMagick is a mini replacement for RMagick that uses the command line
# tool "mogrify" for image manipulation.
#
# You can find more information here:
#
# http://mini_magick.rubyforge.org/
# and
# https://github.com/minimagick/minimagick/
#
#
module MiniMagick
extend ActiveSupport::Concern
included do
begin
require "mini_magick"
rescue LoadError => e
e.message << " (You may need to install the mini_magick gem)"
raise e
end
end
module ClassMethods
def convert(format)
process :convert => format
end
def resize_to_limit(width, height)
process :resize_to_limit => [width, height]
end
def resize_to_fit(width, height)
process :resize_to_fit => [width, height]
end
def resize_to_fill(width, height, gravity='Center')
process :resize_to_fill => [width, height, gravity]
end
def resize_and_pad(width, height, background=:transparent, gravity='Center')
process :resize_and_pad => [width, height, background, gravity]
end
end
##
# Changes the image encoding format to the given format
#
# See http://www.imagemagick.org/script/command-line-options.php#format
#
# === Parameters
#
# [format (#to_s)] an abreviation of the format
#
# === Yields
#
# [MiniMagick::Image] additional manipulations to perform
#
# === Examples
#
# image.convert(:png)
#
def convert(format, page=nil)
@format = format
@page = page
manipulate! do |img|
img = yield(img) if block_given?
img
end
end
##
# Resize the image to fit within the specified dimensions while retaining
# the original aspect ratio. Will only resize the image if it is larger than the
# specified dimensions. The resulting image may be shorter or narrower than specified
# in the smaller dimension but will not be larger than the specified values.
#
# === Parameters
#
# [width (Integer)] the width to scale the image to
# [height (Integer)] the height to scale the image to
#
# === Yields
#
# [MiniMagick::Image] additional manipulations to perform
#
def resize_to_limit(width, height, combine_options: {})
width = dimension_from width
height = dimension_from height
manipulate! do |img|
img.combine_options do |cmd|
cmd.resize "#{width}x#{height}>"
append_combine_options cmd, combine_options
end
img = yield(img) if block_given?
img
end
end
##
# Resize the image to fit within the specified dimensions while retaining
# the original aspect ratio. The image may be shorter or narrower than
# specified in the smaller dimension but will not be larger than the specified values.
#
# === Parameters
#
# [width (Integer)] the width to scale the image to
# [height (Integer)] the height to scale the image to
#
# === Yields
#
# [MiniMagick::Image] additional manipulations to perform
#
def resize_to_fit(width, height, combine_options: {})
width = dimension_from width
height = dimension_from height
manipulate! do |img|
img.combine_options do |cmd|
cmd.resize "#{width}x#{height}"
append_combine_options cmd, combine_options
end
img = yield(img) if block_given?
img
end
end
##
# Resize the image to fit within the specified dimensions while retaining
# the aspect ratio of the original image. If necessary, crop the image in the
# larger dimension.
#
# === Parameters
#
# [width (Integer)] the width to scale the image to
# [height (Integer)] the height to scale the image to
# [gravity (String)] the current gravity suggestion (default: 'Center'; options: 'NorthWest', 'North', 'NorthEast', 'West', 'Center', 'East', 'SouthWest', 'South', 'SouthEast')
#
# === Yields
#
# [MiniMagick::Image] additional manipulations to perform
#
def resize_to_fill(width, height, gravity = 'Center', combine_options: {})
width = dimension_from width
height = dimension_from height
manipulate! do |img|
cols, rows = img[:dimensions]
img.combine_options do |cmd|
if width != cols || height != rows
scale_x = width/cols.to_f
scale_y = height/rows.to_f
if scale_x >= scale_y
cols = (scale_x * (cols + 0.5)).round
rows = (scale_x * (rows + 0.5)).round
cmd.resize "#{cols}"
else
cols = (scale_y * (cols + 0.5)).round
rows = (scale_y * (rows + 0.5)).round
cmd.resize "x#{rows}"
end
end
cmd.gravity gravity
cmd.background "rgba(255,255,255,0.0)"
cmd.extent "#{width}x#{height}" if cols != width || rows != height
append_combine_options cmd, combine_options
end
img = yield(img) if block_given?
img
end
end
##
# Resize the image to fit within the specified dimensions while retaining
# the original aspect ratio. If necessary, will pad the remaining area
# with the given color, which defaults to transparent (for gif and png,
# white for jpeg).
#
# See http://www.imagemagick.org/script/command-line-options.php#gravity
# for gravity options.
#
# === Parameters
#
# [width (Integer)] the width to scale the image to
# [height (Integer)] the height to scale the image to
# [background (String, :transparent)] the color of the background as a hexcode, like "#ff45de"
# [gravity (String)] how to position the image
#
# === Yields
#
# [MiniMagick::Image] additional manipulations to perform
#
def resize_and_pad(width, height, background=:transparent, gravity='Center', combine_options: {})
width = dimension_from width
height = dimension_from height
manipulate! do |img|
img.combine_options do |cmd|
cmd.thumbnail "#{width}x#{height}>"
if background == :transparent
cmd.background "rgba(255, 255, 255, 0.0)"
else
cmd.background background
end
cmd.gravity gravity
cmd.extent "#{width}x#{height}"
append_combine_options cmd, combine_options
end
img = yield(img) if block_given?
img
end
end
##
# Returns the width of the image in pixels.
#
# === Returns
#
# [Integer] the image's width in pixels
#
def width
mini_magick_image[:width]
end
##
# Returns the height of the image in pixels.
#
# === Returns
#
# [Integer] the image's height in pixels
#
def height
mini_magick_image[:height]
end
##
# Manipulate the image with MiniMagick. This method will load up an image
# and then pass each of its frames to the supplied block. It will then
# save the image to disk.
#
# === Gotcha
#
# This method assumes that the object responds to +current_path+.
# Any class that this module is mixed into must have a +current_path+ method.
# CarrierWave::Uploader does, so you won't need to worry about this in
# most cases.
#
# === Yields
#
# [MiniMagick::Image] manipulations to perform
#
# === Raises
#
# [CarrierWave::ProcessingError] if manipulation failed.
#
def manipulate!
cache_stored_file! if !cached?
image = ::MiniMagick::Image.open(current_path)
begin
image.format(@format.to_s.downcase, @page) if @format
image = yield(image)
image.write(current_path)
if @format
move_to = current_path.chomp(File.extname(current_path)) + ".#{@format}"
file.content_type = ::MIME::Types.type_for(move_to).first.to_s
file.move_to(move_to, permissions, directory_permissions)
end
image.run_command("identify", current_path)
ensure
image.destroy!
end
rescue ::MiniMagick::Error, ::MiniMagick::Invalid => e
message = I18n.translate(:"errors.messages.mini_magick_processing_error", :e => e)
raise CarrierWave::ProcessingError, message
end
private
def append_combine_options(cmd, combine_options)
combine_options.each do |method, options|
if options.nil?
cmd.send(method)
else
cmd.send(method, options)
end
end
end
def dimension_from(value)
return value unless value.instance_of?(Proc)
value.arity >= 1 ? value.call(self) : value.call
end
def mini_magick_image
if url
::MiniMagick::Image.open(url)
else
::MiniMagick::Image.open(current_path)
end
end
end # MiniMagick
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/processing/rmagick.rb 0000664 0000000 0000000 00000026753 13222647327 0023251 0 ustar 00root root 0000000 0000000 module CarrierWave
##
# This module simplifies manipulation with RMagick by providing a set
# of convenient helper methods. If you want to use them, you'll need to
# require this file:
#
# require 'carrierwave/processing/rmagick'
#
# And then include it in your uploader:
#
# class MyUploader < CarrierWave::Uploader::Base
# include CarrierWave::RMagick
# end
#
# You can now use the provided helpers:
#
# class MyUploader < CarrierWave::Uploader::Base
# include CarrierWave::RMagick
#
# process :resize_to_fit => [200, 200]
# end
#
# Or create your own helpers with the powerful manipulate! method. Check
# out the RMagick docs at http://www.imagemagick.org/RMagick/doc/ for more
# info
#
# class MyUploader < CarrierWave::Uploader::Base
# include CarrierWave::RMagick
#
# process :do_stuff => 10.0
#
# def do_stuff(blur_factor)
# manipulate! do |img|
# img = img.sepiatone
# img = img.auto_orient
# img = img.radial_blur(blur_factor)
# end
# end
# end
#
# === Note
#
# You should be aware how RMagick handles memory. manipulate! takes care
# of freeing up memory for you, but for optimum memory usage you should
# use destructive operations as much as possible:
#
# DON'T DO THIS:
# img = img.resize_to_fit
#
# DO THIS INSTEAD:
# img.resize_to_fit!
#
# Read this for more information why:
#
# http://rubyforge.org/forum/forum.php?thread_id=1374&forum_id=1618
#
module RMagick
extend ActiveSupport::Concern
included do
begin
require "rmagick"
rescue LoadError
require "RMagick"
rescue LoadError => e
e.message << " (You may need to install the rmagick gem)"
raise e
end
end
module ClassMethods
def convert(format)
process :convert => format
end
def resize_to_limit(width, height)
process :resize_to_limit => [width, height]
end
def resize_to_fit(width, height)
process :resize_to_fit => [width, height]
end
def resize_to_fill(width, height, gravity=::Magick::CenterGravity)
process :resize_to_fill => [width, height, gravity]
end
def resize_and_pad(width, height, background=:transparent, gravity=::Magick::CenterGravity)
process :resize_and_pad => [width, height, background, gravity]
end
def resize_to_geometry_string(geometry_string)
process :resize_to_geometry_string => [geometry_string]
end
end
##
# Changes the image encoding format to the given format
#
# See even http://www.imagemagick.org/RMagick/doc/magick.html#formats
#
# === Parameters
#
# [format (#to_s)] an abreviation of the format
#
# === Yields
#
# [Magick::Image] additional manipulations to perform
#
# === Examples
#
# image.convert(:png)
#
def convert(format)
manipulate!(:format => format)
@format = format
end
##
# Resize the image to fit within the specified dimensions while retaining
# the original aspect ratio. Will only resize the image if it is larger than the
# specified dimensions. The resulting image may be shorter or narrower than specified
# in the smaller dimension but will not be larger than the specified values.
#
# === Parameters
#
# [width (Integer)] the width to scale the image to
# [height (Integer)] the height to scale the image to
#
# === Yields
#
# [Magick::Image] additional manipulations to perform
#
def resize_to_limit(width, height)
width = dimension_from width
height = dimension_from height
manipulate! do |img|
geometry = Magick::Geometry.new(width, height, 0, 0, Magick::GreaterGeometry)
new_img = img.change_geometry(geometry) do |new_width, new_height|
img.resize(new_width, new_height)
end
destroy_image(img)
new_img = yield(new_img) if block_given?
new_img
end
end
##
# From the RMagick documentation: "Resize the image to fit within the
# specified dimensions while retaining the original aspect ratio. The
# image may be shorter or narrower than specified in the smaller dimension
# but will not be larger than the specified values."
#
# See even http://www.imagemagick.org/RMagick/doc/image3.html#resize_to_fit
#
# === Parameters
#
# [width (Integer)] the width to scale the image to
# [height (Integer)] the height to scale the image to
#
# === Yields
#
# [Magick::Image] additional manipulations to perform
#
def resize_to_fit(width, height)
width = dimension_from width
height = dimension_from height
manipulate! do |img|
img.resize_to_fit!(width, height)
img = yield(img) if block_given?
img
end
end
##
# From the RMagick documentation: "Resize the image to fit within the
# specified dimensions while retaining the aspect ratio of the original
# image. If necessary, crop the image in the larger dimension."
#
# See even http://www.imagemagick.org/RMagick/doc/image3.html#resize_to_fill
#
# === Parameters
#
# [width (Integer)] the width to scale the image to
# [height (Integer)] the height to scale the image to
#
# === Yields
#
# [Magick::Image] additional manipulations to perform
#
def resize_to_fill(width, height, gravity=::Magick::CenterGravity)
width = dimension_from width
height = dimension_from height
manipulate! do |img|
img.crop_resized!(width, height, gravity)
img = yield(img) if block_given?
img
end
end
##
# Resize the image to fit within the specified dimensions while retaining
# the original aspect ratio. If necessary, will pad the remaining area
# with the given color, which defaults to transparent (for gif and png,
# white for jpeg).
#
# === Parameters
#
# [width (Integer)] the width to scale the image to
# [height (Integer)] the height to scale the image to
# [background (String, :transparent)] the color of the background as a hexcode, like "#ff45de"
# [gravity (Magick::GravityType)] how to position the image
#
# === Yields
#
# [Magick::Image] additional manipulations to perform
#
def resize_and_pad(width, height, background=:transparent, gravity=::Magick::CenterGravity)
width = dimension_from width
height = dimension_from height
manipulate! do |img|
img.resize_to_fit!(width, height)
new_img = ::Magick::Image.new(width, height) { self.background_color = background == :transparent ? 'rgba(255,255,255,0)' : background.to_s }
if background == :transparent
filled = new_img.matte_floodfill(1, 1)
else
filled = new_img.color_floodfill(1, 1, ::Magick::Pixel.from_color(background))
end
destroy_image(new_img)
filled.composite!(img, gravity, ::Magick::OverCompositeOp)
destroy_image(img)
filled = yield(filled) if block_given?
filled
end
end
##
# Resize the image per the provided geometry string.
#
# === Parameters
#
# [geometry_string (String)] the proportions in which to scale image
#
# === Yields
#
# [Magick::Image] additional manipulations to perform
#
def resize_to_geometry_string(geometry_string)
manipulate! do |img|
new_img = img.change_geometry(geometry_string) do |new_width, new_height|
img.resize(new_width, new_height)
end
destroy_image(img)
new_img = yield(new_img) if block_given?
new_img
end
end
##
# Returns the width of the image.
#
# === Returns
#
# [Integer] the image's width in pixels
#
def width
rmagick_image.columns
end
##
# Returns the height of the image.
#
# === Returns
#
# [Integer] the image's height in pixels
#
def height
rmagick_image.rows
end
##
# Manipulate the image with RMagick. This method will load up an image
# and then pass each of its frames to the supplied block. It will then
# save the image to disk.
#
# === Gotcha
#
# This method assumes that the object responds to +current_path+.
# Any class that this module is mixed into must have a +current_path+ method.
# CarrierWave::Uploader does, so you won't need to worry about this in
# most cases.
#
# === Yields
#
# [Magick::Image] manipulations to perform
# [Integer] Frame index if the image contains multiple frames
# [Hash] options, see below
#
# === Options
#
# The options argument to this method is also yielded as the third
# block argument.
#
# Currently, the following options are defined:
#
# ==== :write
# A hash of assignments to be evaluated in the block given to the RMagick write call.
#
# An example:
#
# manipulate! do |img, index, options|
# options[:write] = {
# :quality => 50,
# :depth => 8
# }
# img
# end
#
# This will translate to the following RMagick::Image#write call:
#
# image.write do |img|
# self.quality = 50
# self.depth = 8
# end
#
# ==== :read
# A hash of assignments to be given to the RMagick read call.
#
# The options available are identical to those for write, but are passed in directly, like this:
#
# manipulate! :read => { :density => 300 }
#
# ==== :format
# Specify the output format. If unset, the filename extension is used to determine the format.
#
# === Raises
#
# [CarrierWave::ProcessingError] if manipulation failed.
#
def manipulate!(options={}, &block)
cache_stored_file! if !cached?
read_block = create_info_block(options[:read])
image = ::Magick::Image.read(current_path, &read_block)
frames = ::Magick::ImageList.new
image.each_with_index do |frame, index|
frame = yield *[frame, index, options].take(block.arity) if block_given?
frames << frame if frame
end
frames.append(true) if block_given?
write_block = create_info_block(options[:write])
if options[:format] || @format
frames.write("#{options[:format] || @format}:#{current_path}", &write_block)
move_to = current_path.chomp(File.extname(current_path)) + ".#{options[:format] || @format}"
file.content_type = ::MIME::Types.type_for(move_to).first.to_s
file.move_to(move_to, permissions, directory_permissions)
else
frames.write(current_path, &write_block)
end
destroy_image(frames)
rescue ::Magick::ImageMagickError => e
raise CarrierWave::ProcessingError, I18n.translate(:"errors.messages.rmagick_processing_error", :e => e)
end
private
def create_info_block(options)
return nil unless options
assignments = options.map { |k, v| "self.#{k} = #{v}" }
code = "lambda { |img| " + assignments.join(";") + "}"
eval code
end
def destroy_image(image)
image.try(:destroy!)
end
def dimension_from(value)
return value unless value.instance_of?(Proc)
value.arity >= 1 ? value.call(self) : value.call
end
def rmagick_image
::Magick::Image.from_blob(self.read).first
end
end # RMagick
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/sanitized_file.rb 0000664 0000000 0000000 00000020673 13222647327 0022444 0 ustar 00root root 0000000 0000000 require 'pathname'
require 'active_support/core_ext/string/multibyte'
begin
# Use mime/types/columnar if available, for reduced memory usage
require 'mime/types/columnar'
rescue LoadError
require 'mime/types'
end
module CarrierWave
##
# SanitizedFile is a base class which provides a common API around all
# the different quirky Ruby File libraries. It has support for Tempfile,
# File, StringIO, Merb-style upload Hashes, as well as paths given as
# Strings and Pathnames.
#
# It's probably needlessly comprehensive and complex. Help is appreciated.
#
class SanitizedFile
attr_accessor :file
class << self
attr_writer :sanitize_regexp
def sanitize_regexp
@sanitize_regexp ||= /[^[:word:]\.\-\+]/
end
end
def initialize(file)
self.file = file
end
##
# Returns the filename as is, without sanitizing it.
#
# === Returns
#
# [String] the unsanitized filename
#
def original_filename
return @original_filename if @original_filename
if @file and @file.respond_to?(:original_filename)
@file.original_filename
elsif path
File.basename(path)
end
end
##
# Returns the filename, sanitized to strip out any evil characters.
#
# === Returns
#
# [String] the sanitized filename
#
def filename
sanitize(original_filename) if original_filename
end
alias_method :identifier, :filename
##
# Returns the part of the filename before the extension. So if a file is called 'test.jpeg'
# this would return 'test'
#
# === Returns
#
# [String] the first part of the filename
#
def basename
split_extension(filename)[0] if filename
end
##
# Returns the file extension
#
# === Returns
#
# [String] the extension
#
def extension
split_extension(filename)[1] if filename
end
##
# Returns the file's size.
#
# === Returns
#
# [Integer] the file's size in bytes.
#
def size
if is_path?
exists? ? File.size(path) : 0
elsif @file.respond_to?(:size)
@file.size
elsif path
exists? ? File.size(path) : 0
else
0
end
end
##
# Returns the full path to the file. If the file has no path, it will return nil.
#
# === Returns
#
# [String, nil] the path where the file is located.
#
def path
unless @file.blank?
if is_path?
File.expand_path(@file)
elsif @file.respond_to?(:path) and not @file.path.blank?
File.expand_path(@file.path)
end
end
end
##
# === Returns
#
# [Boolean] whether the file is supplied as a pathname or string.
#
def is_path?
!!((@file.is_a?(String) || @file.is_a?(Pathname)) && !@file.blank?)
end
##
# === Returns
#
# [Boolean] whether the file is valid and has a non-zero size
#
def empty?
@file.nil? || self.size.nil? || (self.size.zero? && ! self.exists?)
end
##
# === Returns
#
# [Boolean] Whether the file exists
#
def exists?
self.path.present? && File.exist?(self.path)
end
##
# Returns the contents of the file.
#
# === Returns
#
# [String] contents of the file
#
def read
if @content
@content
elsif is_path?
File.open(@file, "rb") {|file| file.read}
else
@file.try(:rewind)
@content = @file.read
@file.try(:close) unless @file.try(:closed?)
@content
end
end
##
# Moves the file to the given path
#
# === Parameters
#
# [new_path (String)] The path where the file should be moved.
# [permissions (Integer)] permissions to set on the file in its new location.
# [directory_permissions (Integer)] permissions to set on created directories.
#
def move_to(new_path, permissions=nil, directory_permissions=nil, keep_filename=false)
return if self.empty?
new_path = File.expand_path(new_path)
mkdir!(new_path, directory_permissions)
move!(new_path)
chmod!(new_path, permissions)
if keep_filename
self.file = {:tempfile => new_path, :filename => original_filename, :content_type => content_type}
else
self.file = {:tempfile => new_path, :content_type => content_type}
end
self
end
##
# Helper to move file to new path.
#
def move!(new_path)
if exists?
FileUtils.mv(path, new_path) unless File.identical?(new_path, path)
else
File.open(new_path, "wb") { |f| f.write(read) }
end
end
##
# Creates a copy of this file and moves it to the given path. Returns the copy.
#
# === Parameters
#
# [new_path (String)] The path where the file should be copied to.
# [permissions (Integer)] permissions to set on the copy
# [directory_permissions (Integer)] permissions to set on created directories.
#
# === Returns
#
# @return [CarrierWave::SanitizedFile] the location where the file will be stored.
#
def copy_to(new_path, permissions=nil, directory_permissions=nil)
return if self.empty?
new_path = File.expand_path(new_path)
mkdir!(new_path, directory_permissions)
copy!(new_path)
chmod!(new_path, permissions)
self.class.new({:tempfile => new_path, :content_type => content_type})
end
##
# Helper to create copy of file in new path.
#
def copy!(new_path)
if exists?
FileUtils.cp(path, new_path) unless new_path == path
else
File.open(new_path, "wb") { |f| f.write(read) }
end
end
##
# Removes the file from the filesystem.
#
def delete
FileUtils.rm(self.path) if exists?
end
##
# Returns a File object, or nil if it does not exist.
#
# === Returns
#
# [File] a File object representing the SanitizedFile
#
def to_file
return @file if @file.is_a?(File)
File.open(path, "rb") if exists?
end
##
# Returns the content type of the file.
#
# === Returns
#
# [String] the content type of the file
#
def content_type
return @content_type if @content_type
if @file.respond_to?(:content_type) and @file.content_type
@content_type = @file.content_type.to_s.chomp
elsif path
@content_type = ::MIME::Types.type_for(path).first.to_s
end
end
##
# Sets the content type of the file.
#
# === Returns
#
# [String] the content type of the file
#
def content_type=(type)
@content_type = type
end
##
# Used to sanitize the file name. Public to allow overriding for non-latin characters.
#
# === Returns
#
# [Regexp] the regexp for sanitizing the file name
#
def sanitize_regexp
CarrierWave::SanitizedFile.sanitize_regexp
end
private
def file=(file)
if file.is_a?(Hash)
@file = file["tempfile"] || file[:tempfile]
@original_filename = file["filename"] || file[:filename]
@content_type = file["content_type"] || file[:content_type] || file["type"] || file[:type]
else
@file = file
@original_filename = nil
@content_type = nil
end
end
# create the directory if it doesn't exist
def mkdir!(path, directory_permissions)
options = {}
options[:mode] = directory_permissions if directory_permissions
FileUtils.mkdir_p(File.dirname(path), options) unless File.exist?(File.dirname(path))
end
def chmod!(path, permissions)
File.chmod(permissions, path) if permissions
end
# Sanitize the filename, to prevent hacking
def sanitize(name)
name = name.tr("\\", "/") # work-around for IE
name = File.basename(name)
name = name.gsub(sanitize_regexp,"_")
name = "_#{name}" if name =~ /\A\.+\z/
name = "unnamed" if name.size == 0
return name.mb_chars.to_s
end
def split_extension(filename)
# regular expressions to try for identifying extensions
extension_matchers = [
/\A(.+)\.(tar\.([glx]?z|bz2))\z/, # matches "something.tar.gz"
/\A(.+)\.([^\.]+)\z/ # matches "something.jpg"
]
extension_matchers.each do |regexp|
if filename =~ regexp
return $1, $2
end
end
return filename, "" # In case we weren't able to split the extension
end
end # SanitizedFile
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/storage.rb 0000664 0000000 0000000 00000000112 13222647327 0021101 0 ustar 00root root 0000000 0000000 require "carrierwave/storage/abstract"
require "carrierwave/storage/file"
carrierwave-1.2.2/lib/carrierwave/storage/ 0000775 0000000 0000000 00000000000 13222647327 0020562 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/lib/carrierwave/storage/abstract.rb 0000664 0000000 0000000 00000002273 13222647327 0022716 0 ustar 00root root 0000000 0000000 module CarrierWave
module Storage
##
# This file serves mostly as a specification for Storage engines. There is no requirement
# that storage engines must be a subclass of this class.
#
class Abstract
attr_reader :uploader
def initialize(uploader)
@uploader = uploader
end
def identifier
uploader.filename
end
def store!(file)
end
def retrieve!(identifier)
end
def cache!(new_file)
raise NotImplementedError.new("Need to implement #cache! if you want to use #{self.class.name} as a cache storage.")
end
def retrieve_from_cache!(identifier)
raise NotImplementedError.new("Need to implement #retrieve_from_cache! if you want to use #{self.class.name} as a cache storage.")
end
def delete_dir!(path)
raise NotImplementedError.new("Need to implement #delete_dir! if you want to use #{self.class.name} as a cache storage.")
end
def clean_cache!(seconds)
raise NotImplementedError.new("Need to implement #clean_cache! if you want to use #{self.class.name} as a cache storage.")
end
end # Abstract
end # Storage
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/storage/file.rb 0000664 0000000 0000000 00000007077 13222647327 0022041 0 ustar 00root root 0000000 0000000 module CarrierWave
module Storage
##
# File storage stores file to the Filesystem (surprising, no?). There's really not much
# to it, it uses the store_dir defined on the uploader as the storage location. That's
# pretty much it.
#
class File < Abstract
##
# Move the file to the uploader's store path.
#
# By default, store!() uses copy_to(), which operates by copying the file
# from the cache to the store, then deleting the file from the cache.
# If move_to_store() is overriden to return true, then store!() uses move_to(),
# which simply moves the file from cache to store. Useful for large files.
#
# === Parameters
#
# [file (CarrierWave::SanitizedFile)] the file to store
#
# === Returns
#
# [CarrierWave::SanitizedFile] a sanitized file
#
def store!(file)
path = ::File.expand_path(uploader.store_path, uploader.root)
if uploader.move_to_store
file.move_to(path, uploader.permissions, uploader.directory_permissions)
else
file.copy_to(path, uploader.permissions, uploader.directory_permissions)
end
end
##
# Retrieve the file from its store path
#
# === Parameters
#
# [identifier (String)] the filename of the file
#
# === Returns
#
# [CarrierWave::SanitizedFile] a sanitized file
#
def retrieve!(identifier)
path = ::File.expand_path(uploader.store_path(identifier), uploader.root)
CarrierWave::SanitizedFile.new(path)
end
##
# Stores given file to cache directory.
#
# === Parameters
#
# [new_file (File, IOString, Tempfile)] any kind of file object
#
# === Returns
#
# [CarrierWave::SanitizedFile] a sanitized file
#
def cache!(new_file)
new_file.move_to(::File.expand_path(uploader.cache_path, uploader.root), uploader.permissions, uploader.directory_permissions, true)
rescue Errno::EMLINK => e
raise(e) if @cache_called
@cache_called = true
# NOTE: Remove cached files older than 10 minutes
clean_cache!(600)
cache!(new_file)
end
##
# Retrieves the file with the given cache_name from the cache.
#
# === Parameters
#
# [cache_name (String)] uniquely identifies a cache file
#
# === Raises
#
# [CarrierWave::InvalidParameter] if the cache_name is incorrectly formatted.
#
def retrieve_from_cache!(identifier)
CarrierWave::SanitizedFile.new(::File.expand_path(uploader.cache_path(identifier), uploader.root))
end
##
# Deletes a cache dir
#
def delete_dir!(path)
if path
begin
Dir.rmdir(::File.expand_path(path, uploader.root))
rescue Errno::ENOENT
# Ignore: path does not exist
rescue Errno::ENOTDIR
# Ignore: path is not a dir
rescue Errno::ENOTEMPTY, Errno::EEXIST
# Ignore: dir is not empty
end
end
end
def clean_cache!(seconds)
Dir.glob(::File.expand_path(::File.join(uploader.cache_dir, '*'), CarrierWave.root)).each do |dir|
# generate_cache_id returns key formated TIMEINT-PID-COUNTER-RND
time = dir.scan(/(\d+)-\d+-\d+-\d+/).first.map(&:to_i)
time = Time.at(*time)
if time < (Time.now.utc - seconds)
FileUtils.rm_rf(dir)
end
end
end
end # File
end # Storage
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/storage/fog.rb 0000664 0000000 0000000 00000032672 13222647327 0021674 0 ustar 00root root 0000000 0000000 module CarrierWave
module Storage
##
# Stores things using the "fog" gem.
#
# fog supports storing files with AWS, Google, Local and Rackspace
#
# You need to setup some options to configure your usage:
#
# [:fog_credentials] host info and credentials for service
# [:fog_directory] specifies name of directory to store data in, assumed to already exist
#
# [:fog_attributes] (optional) additional attributes to set on files
# [:fog_public] (optional) public readability, defaults to true
# [:fog_authenticated_url_expiration] (optional) time (in seconds) that authenticated urls
# will be valid, when fog_public is false and provider is AWS or Google, defaults to 600
# [:fog_use_ssl_for_aws] (optional) #public_url will use https for the AWS generated URL]
# [:fog_aws_accelerate] (optional) #public_url will use s3-accelerate subdomain
# instead of s3, defaults to false
#
#
# AWS credentials contain the following keys:
#
# [:aws_access_key_id]
# [:aws_secret_access_key]
# [:region] (optional) defaults to 'us-east-1'
# :region should be one of ['eu-west-1', 'us-east-1', 'ap-southeast-1', 'us-west-1', 'ap-northeast-1', 'eu-central-1']
#
#
# Google credentials contain the following keys:
# [:google_storage_access_key_id]
# [:google_storage_secrete_access_key]
#
#
# Local credentials contain the following keys:
#
# [:local_root] local path to files
#
#
# Rackspace credentials contain the following keys:
#
# [:rackspace_username]
# [:rackspace_api_key]
#
#
# A full example with AWS credentials:
# CarrierWave.configure do |config|
# config.fog_credentials = {
# :aws_access_key_id => 'xxxxxx',
# :aws_secret_access_key => 'yyyyyy',
# :provider => 'AWS'
# }
# config.fog_directory = 'directoryname'
# config.fog_public = true
# end
#
class Fog < Abstract
class << self
def connection_cache
@connection_cache ||= {}
end
end
##
# Store a file
#
# === Parameters
#
# [file (CarrierWave::SanitizedFile)] the file to store
#
# === Returns
#
# [CarrierWave::Storage::Fog::File] the stored file
#
def store!(file)
f = CarrierWave::Storage::Fog::File.new(uploader, self, uploader.store_path)
f.store(file)
f
end
##
# Retrieve a file
#
# === Parameters
#
# [identifier (String)] unique identifier for file
#
# === Returns
#
# [CarrierWave::Storage::Fog::File] the stored file
#
def retrieve!(identifier)
CarrierWave::Storage::Fog::File.new(uploader, self, uploader.store_path(identifier))
end
##
# Stores given file to cache directory.
#
# === Parameters
#
# [new_file (File, IOString, Tempfile)] any kind of file object
#
# === Returns
#
# [CarrierWave::SanitizedFile] a sanitized file
#
def cache!(new_file)
f = CarrierWave::Storage::Fog::File.new(uploader, self, uploader.cache_path)
f.store(new_file)
f
end
##
# Retrieves the file with the given cache_name from the cache.
#
# === Parameters
#
# [cache_name (String)] uniquely identifies a cache file
#
# === Raises
#
# [CarrierWave::InvalidParameter] if the cache_name is incorrectly formatted.
#
def retrieve_from_cache!(identifier)
CarrierWave::Storage::Fog::File.new(uploader, self, uploader.cache_path(identifier))
end
##
# Deletes a cache dir
#
def delete_dir!(path)
# do nothing, because there's no such things as 'empty directory'
end
def clean_cache!(seconds)
connection.directories.new(
:key => uploader.fog_directory,
:public => uploader.fog_public
).files.all(:prefix => uploader.cache_dir).each do |file|
# generate_cache_id returns key formated TIMEINT-PID-COUNTER-RND
time = file.key.scan(/(\d+)-\d+-\d+-\d+/).first.map { |t| t.to_i }
time = Time.at(*time)
file.destroy if time < (Time.now.utc - seconds)
end
end
def connection
@connection ||= begin
options = credentials = uploader.fog_credentials
self.class.connection_cache[credentials] ||= ::Fog::Storage.new(options)
end
end
class File
include CarrierWave::Utilities::Uri
##
# Current local path to file
#
# === Returns
#
# [String] a path to file
#
attr_reader :path
##
# Return all attributes from file
#
# === Returns
#
# [Hash] attributes from file
#
def attributes
file.attributes
end
##
# Return a temporary authenticated url to a private file, if available
# Only supported for AWS, Rackspace and Google providers
#
# === Returns
#
# [String] temporary authenticated url
# or
# [NilClass] no authenticated url available
#
def authenticated_url(options = {})
if ['AWS', 'Google', 'Rackspace', 'OpenStack'].include?(@uploader.fog_credentials[:provider])
# avoid a get by using local references
local_directory = connection.directories.new(:key => @uploader.fog_directory)
local_file = local_directory.files.new(:key => path)
expire_at = ::Fog::Time.now + @uploader.fog_authenticated_url_expiration
case @uploader.fog_credentials[:provider]
when 'AWS'
local_file.url(expire_at, options)
when 'Rackspace'
connection.get_object_https_url(@uploader.fog_directory, path, expire_at, options)
when 'OpenStack'
connection.get_object_https_url(@uploader.fog_directory, path, expire_at)
else
local_file.url(expire_at)
end
end
end
##
# Lookup value for file content-type header
#
# === Returns
#
# [String] value of content-type
#
def content_type
@content_type || !file.nil? && file.content_type
end
##
# Set non-default content-type header (default is file.content_type)
#
# === Returns
#
# [String] returns new content type value
#
def content_type=(new_content_type)
@content_type = new_content_type
end
##
# Remove the file from service
#
# === Returns
#
# [Boolean] true for success or raises error
#
def delete
# avoid a get by just using local reference
directory.files.new(:key => path).destroy
end
##
# Return extension of file
#
# === Returns
#
# [String] extension of file or nil if the file has no extension
#
def extension
path_elements = path.split('.')
path_elements.last if path_elements.size > 1
end
##
# deprecated: All attributes from file (includes headers)
#
# === Returns
#
# [Hash] attributes from file
#
def headers
location = caller.first
warning = "[yellow][WARN] headers is deprecated, use attributes instead[/]"
warning << " [light_black](#{location})[/]"
Formatador.display_line(warning)
attributes
end
def initialize(uploader, base, path)
@uploader, @base, @path = uploader, base, path
end
##
# Read content of file from service
#
# === Returns
#
# [String] contents of file
def read
file.body
end
##
# Return size of file body
#
# === Returns
#
# [Integer] size of file body
#
def size
file.nil? ? 0 : file.content_length
end
##
# Check if the file exists on the remote service
#
# === Returns
#
# [Boolean] true if file exists or false
def exists?
!!file
end
##
# Write file to service
#
# === Returns
#
# [Boolean] true on success or raises error
def store(new_file)
if new_file.is_a?(self.class)
new_file.copy_to(path)
else
fog_file = new_file.to_file
@content_type ||= new_file.content_type
@file = directory.files.create({
:body => (fog_file ? fog_file : new_file).read,
:content_type => @content_type,
:key => path,
:public => @uploader.fog_public
}.merge(@uploader.fog_attributes))
fog_file.close if fog_file && !fog_file.closed?
end
true
end
##
# Return a url to a public file, if available
#
# === Returns
#
# [String] public url
# or
# [NilClass] no public url available
#
def public_url
encoded_path = encode_path(path)
if host = @uploader.asset_host
if host.respond_to? :call
"#{host.call(self)}/#{encoded_path}"
else
"#{host}/#{encoded_path}"
end
else
# AWS/Google optimized for speed over correctness
case @uploader.fog_credentials[:provider].to_s
when 'AWS'
# check if some endpoint is set in fog_credentials
if @uploader.fog_credentials.has_key?(:endpoint)
"#{@uploader.fog_credentials[:endpoint]}/#{@uploader.fog_directory}/#{encoded_path}"
else
protocol = @uploader.fog_use_ssl_for_aws ? "https" : "http"
# if directory is a valid subdomain, use that style for access
if @uploader.fog_directory.to_s =~ /^(?:[a-z]|\d(?!\d{0,2}(?:\d{1,3}){3}$))(?:[a-z0-9\.]|(?![\-])|\-(?![\.])){1,61}[a-z0-9]$/
s3_subdomain = @uploader.fog_aws_accelerate ? "s3-accelerate" : "s3"
"#{protocol}://#{@uploader.fog_directory}.#{s3_subdomain}.amazonaws.com/#{encoded_path}"
else
# directory is not a valid subdomain, so use path style for access
"#{protocol}://s3.amazonaws.com/#{@uploader.fog_directory}/#{encoded_path}"
end
end
when 'Google'
# https://cloud.google.com/storage/docs/access-public-data
"https://storage.googleapis.com/#{@uploader.fog_directory}/#{encoded_path}"
else
# avoid a get by just using local reference
directory.files.new(:key => path).public_url
end
end
end
##
# Return url to file, if avaliable
#
# === Returns
#
# [String] url
# or
# [NilClass] no url available
#
def url(options = {})
if !@uploader.fog_public
authenticated_url(options)
else
public_url
end
end
##
# Return file name, if available
#
# === Returns
#
# [String] file name
# or
# [NilClass] no file name available
#
def filename(options = {})
return unless file_url = url(options)
CGI.unescape(file_url.split('?').first).gsub(/.*\/(.*?$)/, '\1')
end
##
# Creates a copy of this file and returns it.
#
# === Parameters
#
# [new_path (String)] The path where the file should be copied to.
#
# === Returns
#
# @return [CarrierWave::Storage::Fog::File] the location where the file will be stored.
#
def copy_to(new_path)
connection.copy_object(@uploader.fog_directory, file.key, @uploader.fog_directory, new_path, acl_header)
CarrierWave::Storage::Fog::File.new(@uploader, @base, new_path)
end
private
##
# connection to service
#
# === Returns
#
# [Fog::#{provider}::Storage] connection to service
#
def connection
@base.connection
end
##
# local reference to directory containing file
#
# === Returns
#
# [Fog::#{provider}::Directory] containing directory
#
def directory
@directory ||= begin
connection.directories.new(
:key => @uploader.fog_directory,
:public => @uploader.fog_public
)
end
end
##
# lookup file
#
# === Returns
#
# [Fog::#{provider}::File] file data from remote service
#
def file
@file ||= directory.files.head(path)
end
def acl_header
{'x-amz-acl' => @uploader.fog_public ? 'public-read' : 'private'}
end
end
end # Fog
end # Storage
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/test/ 0000775 0000000 0000000 00000000000 13222647327 0020075 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/lib/carrierwave/test/matchers.rb 0000664 0000000 0000000 00000026521 13222647327 0022236 0 ustar 00root root 0000000 0000000 module CarrierWave
module Test
##
# These are some matchers that can be used in RSpec specs, to simplify the testing
# of uploaders.
#
module Matchers
class BeIdenticalTo # :nodoc:
def initialize(expected)
@expected = expected
end
def matches?(actual)
@actual = actual
FileUtils.identical?(@actual, @expected)
end
def failure_message
"expected #{@actual.inspect} to be identical to #{@expected.inspect}"
end
def failure_message_when_negated
"expected #{@actual.inspect} to not be identical to #{@expected.inspect}"
end
def description
"be identical to #{@expected.inspect}"
end
# RSpec 2 compatibility:
alias_method :negative_failure_message, :failure_message_when_negated
end
def be_identical_to(expected)
BeIdenticalTo.new(expected)
end
class HavePermissions # :nodoc:
def initialize(expected)
@expected = expected
end
def matches?(actual)
@actual = actual
# Satisfy expectation here. Return false or raise an error if it's not met.
(File.stat(@actual.path).mode & 0777) == @expected
end
def failure_message
"expected #{@actual.current_path.inspect} to have permissions #{@expected.to_s(8)}, but they were #{(File.stat(@actual.path).mode & 0777).to_s(8)}"
end
def failure_message_when_negated
"expected #{@actual.current_path.inspect} not to have permissions #{@expected.to_s(8)}, but it did"
end
def description
"have permissions #{@expected.to_s(8)}"
end
# RSpec 2 compatibility:
alias_method :negative_failure_message, :failure_message_when_negated
end
def have_permissions(expected)
HavePermissions.new(expected)
end
class HaveDirectoryPermissions # :nodoc:
def initialize(expected)
@expected = expected
end
def matches?(actual)
@actual = actual
# Satisfy expectation here. Return false or raise an error if it's not met.
(File.stat(File.dirname @actual.path).mode & 0777) == @expected
end
def failure_message
"expected #{File.dirname @actual.current_path.inspect} to have permissions #{@expected.to_s(8)}, but they were #{(File.stat(@actual.path).mode & 0777).to_s(8)}"
end
def failure_message_when_negated
"expected #{File.dirname @actual.current_path.inspect} not to have permissions #{@expected.to_s(8)}, but it did"
end
def description
"have permissions #{@expected.to_s(8)}"
end
# RSpec 2 compatibility:
alias_method :negative_failure_message, :failure_message_when_negated
end
def have_directory_permissions(expected)
HaveDirectoryPermissions.new(expected)
end
class BeNoLargerThan # :nodoc:
def initialize(width, height)
@width, @height = width, height
end
def matches?(actual)
@actual = actual
# Satisfy expectation here. Return false or raise an error if it's not met.
image = ImageLoader.load_image(@actual.current_path)
@actual_width = image.width
@actual_height = image.height
@actual_width <= @width && @actual_height <= @height
end
def failure_message
"expected #{@actual.current_path.inspect} to be no larger than #{@width} by #{@height}, but it was #{@actual_width} by #{@actual_height}."
end
def failure_message_when_negated
"expected #{@actual.current_path.inspect} to be larger than #{@width} by #{@height}, but it wasn't."
end
def description
"be no larger than #{@width} by #{@height}"
end
# RSpec 2 compatibility:
alias_method :negative_failure_message, :failure_message_when_negated
end
def be_no_larger_than(width, height)
BeNoLargerThan.new(width, height)
end
class HaveDimensions # :nodoc:
def initialize(width, height)
@width, @height = width, height
end
def matches?(actual)
@actual = actual
# Satisfy expectation here. Return false or raise an error if it's not met.
image = ImageLoader.load_image(@actual.current_path)
@actual_width = image.width
@actual_height = image.height
@actual_width == @width && @actual_height == @height
end
def failure_message
"expected #{@actual.current_path.inspect} to have an exact size of #{@width} by #{@height}, but it was #{@actual_width} by #{@actual_height}."
end
def failure_message_when_negated
"expected #{@actual.current_path.inspect} not to have an exact size of #{@width} by #{@height}, but it did."
end
def description
"have an exact size of #{@width} by #{@height}"
end
# RSpec 2 compatibility:
alias_method :negative_failure_message, :failure_message_when_negated
end
def have_dimensions(width, height)
HaveDimensions.new(width, height)
end
class HaveHeight # :nodoc:
def initialize(height)
@height = height
end
def matches?(actual)
@actual = actual
# Satisfy expectation here. Return false or raise an error if it's not met.
image = ImageLoader.load_image(@actual.current_path)
@actual_height = image.height
@actual_height == @height
end
def failure_message
"expected #{@actual.current_path.inspect} to have an exact size of #{@height}, but it was #{@actual_height}."
end
def failure_message_when_negated
"expected #{@actual.current_path.inspect} not to have an exact size of #{@height}, but it did."
end
def description
"have an exact height of #{@height}"
end
# RSpec 2 compatibility:
alias_method :negative_failure_message, :failure_message_when_negated
end
def have_height(height)
HaveHeight.new(height)
end
class HaveWidth # :nodoc:
def initialize(width)
@width = width
end
def matches?(actual)
@actual = actual
# Satisfy expectation here. Return false or raise an error if it's not met.
image = ImageLoader.load_image(@actual.current_path)
@actual_width = image.width
@actual_width == @width
end
def failure_message
"expected #{@actual.current_path.inspect} to have an exact size of #{@width}, but it was #{@actual_width}."
end
def failure_message_when_negated
"expected #{@actual.current_path.inspect} not to have an exact size of #{@width}, but it did."
end
def description
"have an exact width of #{@width}"
end
# RSpec 2 compatibility:
alias_method :negative_failure_message, :failure_message_when_negated
end
def have_width(width)
HaveWidth.new(width)
end
class BeNoWiderThan # :nodoc:
def initialize(width)
@width = width
end
def matches?(actual)
@actual = actual
# Satisfy expectation here. Return false or raise an error if it's not met.
image = ImageLoader.load_image(@actual.current_path)
@actual_width = image.width
@actual_width <= @width
end
def failure_message
"expected #{@actual.current_path.inspect} to be no wider than #{@width}, but it was #{@actual_width}."
end
def failure_message_when_negated
"expected #{@actual.current_path.inspect} not to be wider than #{@width}, but it is."
end
def description
"have a width less than or equal to #{@width}"
end
# RSpec 2 compatibility:
alias_method :negative_failure_message, :failure_message_when_negated
end
def be_no_wider_than(width)
BeNoWiderThan.new(width)
end
class BeNoTallerThan # :nodoc:
def initialize(height)
@height = height
end
def matches?(actual)
@actual = actual
# Satisfy expectation here. Return false or raise an error if it's not met.
image = ImageLoader.load_image(@actual.current_path)
@actual_height = image.height
@actual_height <= @height
end
def failure_message
"expected #{@actual.current_path.inspect} to be no taller than #{@height}, but it was #{@actual_height}."
end
def failure_message_when_negated
"expected #{@actual.current_path.inspect} not to be taller than #{@height}, but it is."
end
def description
"have a height less than or equal to #{@height}"
end
# RSpec 2 compatibility:
alias_method :negative_failure_message, :failure_message_when_negated
end
def be_no_taller_than(height)
BeNoTallerThan.new(height)
end
class BeFormat # :nodoc:
def initialize(expected)
@expected = expected
end
def matches?(actual)
@actual = actual
# Satisfy expectation here. Return false or raise an error if it's not met.
image = ImageLoader.load_image(@actual.current_path)
@actual_expected = image.format
!@expected.nil? && @actual_expected.casecmp(@expected).zero?
end
def failure_message
"expected #{@actual.current_path.inspect} to have #{@expected} format, but it was #{@actual_expected}."
end
def failure_message_when_negated
"expected #{@actual.current_path.inspect} not to have #{@expected} format, but it did."
end
def description
"have #{@expected} format"
end
# RSpec 2 compatibility:
alias_method :negative_failure_message, :failure_message_when_negated
end
def be_format(expected)
BeFormat.new(expected)
end
class ImageLoader # :nodoc:
def self.load_image(filename)
if defined? ::MiniMagick
MiniMagickWrapper.new(filename)
else
unless defined? ::Magick
begin
require 'rmagick'
rescue LoadError
require 'RMagick'
rescue LoadError
puts "WARNING: Failed to require rmagick, image processing may fail!"
end
end
MagickWrapper.new(filename)
end
end
end
class MagickWrapper # :nodoc:
attr_reader :image
def width
image.columns
end
def height
image.rows
end
def format
image.format
end
def initialize(filename)
@image = ::Magick::Image.read(filename).first
end
end
class MiniMagickWrapper # :nodoc:
attr_reader :image
def width
image[:width]
end
def height
image[:height]
end
def format
image[:format]
end
def initialize(filename)
@image = ::MiniMagick::Image.open(filename)
end
end
end # Matchers
end # Test
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/uploader.rb 0000664 0000000 0000000 00000004726 13222647327 0021267 0 ustar 00root root 0000000 0000000 require "carrierwave/uploader/configuration"
require "carrierwave/uploader/callbacks"
require "carrierwave/uploader/proxy"
require "carrierwave/uploader/url"
require "carrierwave/uploader/mountable"
require "carrierwave/uploader/cache"
require "carrierwave/uploader/store"
require "carrierwave/uploader/download"
require "carrierwave/uploader/remove"
require "carrierwave/uploader/extension_whitelist"
require "carrierwave/uploader/extension_blacklist"
require "carrierwave/uploader/content_type_whitelist"
require "carrierwave/uploader/content_type_blacklist"
require "carrierwave/uploader/file_size"
require "carrierwave/uploader/processing"
require "carrierwave/uploader/versions"
require "carrierwave/uploader/default_url"
require "carrierwave/uploader/serialization"
module CarrierWave
##
# See CarrierWave::Uploader::Base
#
module Uploader
##
# An uploader is a class that allows you to easily handle the caching and storage of
# uploaded files. Please refer to the README for configuration options.
#
# Once you have an uploader you can use it in isolation:
#
# my_uploader = MyUploader.new
# my_uploader.cache!(File.open(path_to_file))
# my_uploader.retrieve_from_store!('monkey.png')
#
# Alternatively, you can mount it on an ORM or other persistence layer, with
# +CarrierWave::Mount#mount_uploader+. There are extensions for activerecord and datamapper
# these are *very* simple (they are only a dozen lines of code), so adding your own should
# be trivial.
#
class Base
attr_reader :file
include CarrierWave::Uploader::Configuration
include CarrierWave::Uploader::Callbacks
include CarrierWave::Uploader::Proxy
include CarrierWave::Uploader::Url
include CarrierWave::Uploader::Mountable
include CarrierWave::Uploader::Cache
include CarrierWave::Uploader::Store
include CarrierWave::Uploader::Download
include CarrierWave::Uploader::Remove
include CarrierWave::Uploader::ExtensionWhitelist
include CarrierWave::Uploader::ExtensionBlacklist
include CarrierWave::Uploader::ContentTypeWhitelist
include CarrierWave::Uploader::ContentTypeBlacklist
include CarrierWave::Uploader::FileSize
include CarrierWave::Uploader::Processing
include CarrierWave::Uploader::Versions
include CarrierWave::Uploader::DefaultUrl
include CarrierWave::Uploader::Serialization
end # Base
end # Uploader
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/uploader/ 0000775 0000000 0000000 00000000000 13222647327 0020731 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/lib/carrierwave/uploader/cache.rb 0000664 0000000 0000000 00000014470 13222647327 0022327 0 ustar 00root root 0000000 0000000 module CarrierWave
class FormNotMultipart < UploadError
def message
"You tried to assign a String or a Pathname to an uploader, for security reasons, this is not allowed.\n\n If this is a file upload, please check that your upload form is multipart encoded."
end
end
class CacheCounter
@@counter = 0
def self.increment
@@counter += 1
end
end
##
# Generates a unique cache id for use in the caching system
#
# === Returns
#
# [String] a cache id in the format TIMEINT-PID-COUNTER-RND
#
def self.generate_cache_id
[Time.now.utc.to_i,
Process.pid,
'%04d' % (CarrierWave::CacheCounter.increment % 1000),
'%04d' % rand(9999)
].map(&:to_s).join('-')
end
module Uploader
module Cache
extend ActiveSupport::Concern
include CarrierWave::Uploader::Callbacks
include CarrierWave::Uploader::Configuration
module ClassMethods
##
# Removes cached files which are older than one day. You could call this method
# from a rake task to clean out old cached files.
#
# You can call this method directly on the module like this:
#
# CarrierWave.clean_cached_files!
#
# === Note
#
# This only works as long as you haven't done anything funky with your cache_dir.
# It's recommended that you keep cache files in one place only.
#
def clean_cached_files!(seconds=60*60*24)
cache_storage.new(CarrierWave::Uploader::Base.new).clean_cache!(seconds)
end
end
##
# Returns true if the uploader has been cached
#
# === Returns
#
# [Bool] whether the current file is cached
#
def cached?
@cache_id
end
##
# Caches the remotely stored file
#
# This is useful when about to process images. Most processing solutions
# require the file to be stored on the local filesystem.
#
def cache_stored_file!
cache!
end
def sanitized_file
_content = file.read
if _content.is_a?(File) # could be if storage is Fog
sanitized = CarrierWave::Storage::Fog.new(self).retrieve!(File.basename(_content.path))
else
sanitized = SanitizedFile.new :tempfile => StringIO.new(_content),
:filename => File.basename(path), :content_type => file.content_type
end
sanitized
end
##
# Returns a String which uniquely identifies the currently cached file for later retrieval
#
# === Returns
#
# [String] a cache name, in the format TIMEINT-PID-COUNTER-RND/filename.txt
#
def cache_name
File.join(cache_id, full_original_filename) if cache_id and original_filename
end
##
# Caches the given file. Calls process! to trigger any process callbacks.
#
# By default, cache!() uses copy_to(), which operates by copying the file
# to the cache, then deleting the original file. If move_to_cache() is
# overriden to return true, then cache!() uses move_to(), which simply
# moves the file to the cache. Useful for large files.
#
# === Parameters
#
# [new_file (File, IOString, Tempfile)] any kind of file object
#
# === Raises
#
# [CarrierWave::FormNotMultipart] if the assigned parameter is a string
#
def cache!(new_file = sanitized_file)
new_file = CarrierWave::SanitizedFile.new(new_file)
return if new_file.empty?
raise CarrierWave::FormNotMultipart if new_file.is_path? && ensure_multipart_form
self.cache_id = CarrierWave.generate_cache_id unless cache_id
@filename = new_file.filename
self.original_filename = new_file.filename
begin
# first, create a workfile on which we perform processings
if move_to_cache
@file = new_file.move_to(File.expand_path(workfile_path, root), permissions, directory_permissions)
else
@file = new_file.copy_to(File.expand_path(workfile_path, root), permissions, directory_permissions)
end
with_callbacks(:cache, @file) do
@file = cache_storage.cache!(@file)
end
ensure
FileUtils.rm_rf(workfile_path(''))
end
end
##
# Retrieves the file with the given cache_name from the cache.
#
# === Parameters
#
# [cache_name (String)] uniquely identifies a cache file
#
# === Raises
#
# [CarrierWave::InvalidParameter] if the cache_name is incorrectly formatted.
#
def retrieve_from_cache!(cache_name)
with_callbacks(:retrieve_from_cache, cache_name) do
self.cache_id, self.original_filename = cache_name.to_s.split('/', 2)
@filename = original_filename
@file = cache_storage.retrieve_from_cache!(full_filename(original_filename))
end
end
##
# Calculates the path where the cache file should be stored.
#
# === Parameters
#
# [for_file (String)] name of the file
#
# === Returns
#
# [String] the cache path
#
def cache_path(for_file=full_filename(original_filename))
File.join(*[cache_dir, @cache_id, for_file].compact)
end
private
def workfile_path(for_file=original_filename)
File.join(CarrierWave.tmp_path, @cache_id, version_name.to_s, for_file)
end
attr_reader :cache_id, :original_filename
# We can override the full_original_filename method in other modules
alias_method :full_original_filename, :original_filename
def cache_id=(cache_id)
# Earlier version used 3 part cache_id. Thus we should allow for
# the cache_id to have both 3 part and 4 part formats.
raise CarrierWave::InvalidParameter, "invalid cache id" unless cache_id =~ /\A(-)?[\d]+\-[\d]+(\-[\d]{4})?\-[\d]{4}\z/
@cache_id = cache_id
end
def original_filename=(filename)
raise CarrierWave::InvalidParameter, "invalid filename" if filename =~ CarrierWave::SanitizedFile.sanitize_regexp
@original_filename = filename
end
def cache_storage
@cache_storage ||= self.class.cache_storage.new(self)
end
end # Cache
end # Uploader
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/uploader/callbacks.rb 0000664 0000000 0000000 00000001674 13222647327 0023205 0 ustar 00root root 0000000 0000000 module CarrierWave
module Uploader
module Callbacks
extend ActiveSupport::Concern
included do
class_attribute :_before_callbacks, :_after_callbacks,
:instance_writer => false
self._before_callbacks = Hash.new []
self._after_callbacks = Hash.new []
end
def with_callbacks(kind, *args)
self.class._before_callbacks[kind].each { |c| send c, *args }
yield
self.class._after_callbacks[kind].each { |c| send c, *args }
end
module ClassMethods
def before(kind, callback)
self._before_callbacks = self._before_callbacks.
merge kind => _before_callbacks[kind] + [callback]
end
def after(kind, callback)
self._after_callbacks = self._after_callbacks.
merge kind => _after_callbacks[kind] + [callback]
end
end # ClassMethods
end # Callbacks
end # Uploader
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/uploader/configuration.rb 0000664 0000000 0000000 00000016004 13222647327 0024126 0 ustar 00root root 0000000 0000000 module CarrierWave
module Uploader
module Configuration
extend ActiveSupport::Concern
included do
class_attribute :_storage, :_cache_storage, :instance_writer => false
add_config :root
add_config :base_path
add_config :asset_host
add_config :permissions
add_config :directory_permissions
add_config :storage_engines
add_config :store_dir
add_config :cache_dir
add_config :enable_processing
add_config :ensure_multipart_form
add_config :delete_tmp_file_after_storage
add_config :move_to_cache
add_config :move_to_store
add_config :remove_previously_stored_files_after_update
# fog
add_config :fog_provider
add_config :fog_attributes
add_config :fog_credentials
add_config :fog_directory
add_config :fog_public
add_config :fog_authenticated_url_expiration
add_config :fog_use_ssl_for_aws
add_config :fog_aws_accelerate
# Mounting
add_config :ignore_integrity_errors
add_config :ignore_processing_errors
add_config :ignore_download_errors
add_config :validate_integrity
add_config :validate_processing
add_config :validate_download
add_config :mount_on
add_config :cache_only
# set default values
reset_config
end
module ClassMethods
##
# Sets the storage engine to be used when storing files with this uploader.
# Can be any class that implements a #store!(CarrierWave::SanitizedFile) and a #retrieve!
# method. See lib/carrierwave/storage/file.rb for an example. Storage engines should
# be added to CarrierWave::Uploader::Base.storage_engines so they can be referred
# to by a symbol, which should be more convenient
#
# If no argument is given, it will simply return the currently used storage engine.
#
# === Parameters
#
# [storage (Symbol, Class)] The storage engine to use for this uploader
#
# === Returns
#
# [Class] the storage engine to be used with this uploader
#
# === Examples
#
# storage :file
# storage CarrierWave::Storage::File
# storage MyCustomStorageEngine
#
def storage(storage = nil)
case storage
when Symbol
if storage_engine = storage_engines[storage]
self._storage = eval storage_engine
else
raise CarrierWave::UnknownStorageError, "Unknown storage: #{storage}"
end
when nil
storage
else
self._storage = storage
end
_storage
end
alias_method :storage=, :storage
##
# Sets the cache storage engine to be used when storing cache files with this uploader.
# Same as .storage except for required methods being #cache!(CarrierWave::SanitizedFile),
# #retrieve_from_cache! and #delete_dir!.
#
# === Parameters
#
# [storage (Symbol, Class)] The cache storage engine to use for this uploader
#
# === Returns
#
# [Class] the cache storage engine to be used with this uploader
#
# === Examples
#
# cache_storage :file
# cache_storage CarrierWave::Storage::File
# cache_storage MyCustomStorageEngine
#
def cache_storage(storage = nil)
if storage
self._cache_storage = storage.is_a?(Symbol) ? eval(storage_engines[storage]) : storage
end
_cache_storage
end
alias_method :cache_storage=, :cache_storage
def add_config(name)
class_eval <<-RUBY, __FILE__, __LINE__ + 1
def self.eager_load_fog(fog_credentials)
# see #1198. This will hopefully no longer be necessary after fog 2.0
require self.fog_provider
require 'carrierwave/storage/fog'
Fog::Storage.new(fog_credentials) if fog_credentials.present?
end
def self.#{name}(value=nil)
@#{name} = value if value
eager_load_fog(value) if value && '#{name}' == 'fog_credentials'
return @#{name} if self.object_id == #{self.object_id} || defined?(@#{name})
name = superclass.#{name}
return nil if name.nil? && !instance_variable_defined?(:@#{name})
@#{name} = name && !name.is_a?(Module) && !name.is_a?(Symbol) && !name.is_a?(Numeric) && !name.is_a?(TrueClass) && !name.is_a?(FalseClass) ? name.dup : name
end
def self.#{name}=(value)
eager_load_fog(value) if '#{name}' == 'fog_credentials' && value.present?
@#{name} = value
end
def #{name}=(value)
self.class.eager_load_fog(value) if '#{name}' == 'fog_credentials' && value.present?
@#{name} = value
end
def #{name}
value = @#{name} if instance_variable_defined?(:@#{name})
value = self.class.#{name} unless instance_variable_defined?(:@#{name})
if value.instance_of?(Proc)
value.arity >= 1 ? value.call(self) : value.call
else
value
end
end
RUBY
end
def configure
yield self
end
##
# sets configuration back to default
#
def reset_config
configure do |config|
config.permissions = 0644
config.directory_permissions = 0755
config.storage_engines = {
:file => "CarrierWave::Storage::File",
:fog => "CarrierWave::Storage::Fog"
}
config.storage = :file
config.cache_storage = :file
config.fog_provider = 'fog'
config.fog_attributes = {}
config.fog_credentials = {}
config.fog_public = true
config.fog_authenticated_url_expiration = 600
config.fog_use_ssl_for_aws = true
config.fog_aws_accelerate = false
config.store_dir = 'uploads'
config.cache_dir = 'uploads/tmp'
config.delete_tmp_file_after_storage = true
config.move_to_cache = false
config.move_to_store = false
config.remove_previously_stored_files_after_update = true
config.ignore_integrity_errors = true
config.ignore_processing_errors = true
config.ignore_download_errors = true
config.validate_integrity = true
config.validate_processing = true
config.validate_download = true
config.root = lambda { CarrierWave.root }
config.base_path = CarrierWave.base_path
config.enable_processing = true
config.ensure_multipart_form = true
end
end
end
end
end
end
carrierwave-1.2.2/lib/carrierwave/uploader/content_type_blacklist.rb 0000664 0000000 0000000 00000002653 13222647327 0026027 0 ustar 00root root 0000000 0000000 module CarrierWave
module Uploader
module ContentTypeBlacklist
extend ActiveSupport::Concern
included do
before :cache, :check_content_type_blacklist!
end
##
# Override this method in your uploader to provide a blacklist of files content types
# which are not allowed to be uploaded.
# Not only strings but Regexp are allowed as well.
#
# === Returns
#
# [NilClass, String, Regexp, Array[String, Regexp]] a blacklist of content types which are not allowed to be uploaded
#
# === Examples
#
# def content_type_blacklist
# %w(text/json application/json)
# end
#
# Basically the same, but using a Regexp:
#
# def content_type_blacklist
# [/(text|application)\/json/]
# end
#
def content_type_blacklist; end
private
def check_content_type_blacklist!(new_file)
content_type = new_file.content_type
if content_type_blacklist && blacklisted_content_type?(content_type)
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.content_type_blacklist_error", content_type: content_type)
end
end
def blacklisted_content_type?(content_type)
Array(content_type_blacklist).any? { |item| content_type =~ /#{item}/ }
end
end # ContentTypeBlacklist
end # Uploader
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/uploader/content_type_whitelist.rb 0000664 0000000 0000000 00000002644 13222647327 0026073 0 ustar 00root root 0000000 0000000 module CarrierWave
module Uploader
module ContentTypeWhitelist
extend ActiveSupport::Concern
included do
before :cache, :check_content_type_whitelist!
end
##
# Override this method in your uploader to provide a whitelist of files content types
# which are allowed to be uploaded.
# Not only strings but Regexp are allowed as well.
#
# === Returns
#
# [NilClass, String, Regexp, Array[String, Regexp]] a whitelist of content types which are allowed to be uploaded
#
# === Examples
#
# def content_type_whitelist
# %w(text/json application/json)
# end
#
# Basically the same, but using a Regexp:
#
# def content_type_whitelist
# [/(text|application)\/json/]
# end
#
def content_type_whitelist; end
private
def check_content_type_whitelist!(new_file)
content_type = new_file.content_type
if content_type_whitelist && !whitelisted_content_type?(content_type)
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.content_type_whitelist_error", content_type: content_type)
end
end
def whitelisted_content_type?(content_type)
Array(content_type_whitelist).any? { |item| content_type =~ /#{item}/ }
end
end # ContentTypeWhitelist
end # Uploader
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/uploader/default_url.rb 0000664 0000000 0000000 00000000550 13222647327 0023564 0 ustar 00root root 0000000 0000000 module CarrierWave
module Uploader
module DefaultUrl
def url(*args)
super || default_url(*args)
end
##
# Override this method in your uploader to provide a default url
# in case no file has been cached/stored yet.
#
def default_url(*args); end
end # DefaultPath
end # Uploader
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/uploader/download.rb 0000664 0000000 0000000 00000006011 13222647327 0023063 0 ustar 00root root 0000000 0000000 require 'open-uri'
module CarrierWave
module Uploader
module Download
extend ActiveSupport::Concern
include CarrierWave::Uploader::Callbacks
include CarrierWave::Uploader::Configuration
include CarrierWave::Uploader::Cache
class RemoteFile
def initialize(uri, remote_headers = {})
@uri = uri
@remote_headers = remote_headers
end
def original_filename
filename = filename_from_header || filename_from_uri
mime_type = MIME::Types[file.content_type].first
unless File.extname(filename).present? || mime_type.blank?
filename = "#{filename}.#{mime_type.extensions.first}"
end
filename
end
def respond_to?(*args)
super or file.respond_to?(*args)
end
def http?
@uri.scheme =~ /^https?$/
end
private
def file
if @file.blank?
headers = @remote_headers.
reverse_merge('User-Agent' => "CarrierWave/#{CarrierWave::VERSION}")
@file = Kernel.open(@uri.to_s, headers)
@file = @file.is_a?(String) ? StringIO.new(@file) : @file
end
@file
rescue StandardError => e
raise CarrierWave::DownloadError, "could not download file: #{e.message}"
end
def filename_from_header
if file.meta.include? 'content-disposition'
match = file.meta['content-disposition'].match(/filename="?([^"]+)/)
return match[1] unless match.nil? || match[1].empty?
end
end
def filename_from_uri
URI.decode(File.basename(file.base_uri.path))
end
def method_missing(*args, &block)
file.send(*args, &block)
end
end
##
# Caches the file by downloading it from the given URL.
#
# === Parameters
#
# [url (String)] The URL where the remote file is stored
# [remote_headers (Hash)] Request headers
#
def download!(uri, remote_headers = {})
processed_uri = process_uri(uri)
file = RemoteFile.new(processed_uri, remote_headers)
raise CarrierWave::DownloadError, "trying to download a file which is not served over HTTP" unless file.http?
cache!(file)
end
##
# Processes the given URL by parsing and escaping it. Public to allow overriding.
#
# === Parameters
#
# [url (String)] The URL where the remote file is stored
#
def process_uri(uri)
URI.parse(uri)
rescue URI::InvalidURIError
uri_parts = uri.split('?')
# regexp from Ruby's URI::Parser#regexp[:UNSAFE], with [] specifically removed
encoded_uri = URI.encode(uri_parts.shift, /[^\-_.!~*'()a-zA-Z\d;\/?:@&=+$,]/)
encoded_uri << '?' << URI.encode(uri_parts.join('?')) if uri_parts.any?
URI.parse(encoded_uri) rescue raise CarrierWave::DownloadError, "couldn't parse URL"
end
end # Download
end # Uploader
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/uploader/extension_blacklist.rb 0000664 0000000 0000000 00000003073 13222647327 0025325 0 ustar 00root root 0000000 0000000 module CarrierWave
module Uploader
module ExtensionBlacklist
extend ActiveSupport::Concern
included do
before :cache, :check_extension_blacklist!
end
##
# Override this method in your uploader to provide a black list of extensions which
# are prohibited to be uploaded. Compares the file's extension case insensitive.
# Furthermore, not only strings but Regexp are allowed as well.
#
# When using a Regexp in the black list, `\A` and `\z` are automatically added to
# the Regexp expression, also case insensitive.
#
# === Returns
# [NilClass, String, Regexp, Array[String, Regexp]] a black list of extensions which are prohibited to be uploaded
#
# === Examples
#
# def extension_blacklist
# %w(swf tiff)
# end
#
# Basically the same, but using a Regexp:
#
# def extension_blacklist
# [/swf/, 'tiff']
# end
#
def extension_blacklist; end
private
def check_extension_blacklist!(new_file)
extension = new_file.extension.to_s
if extension_blacklist && blacklisted_extension?(extension)
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.extension_blacklist_error", extension: new_file.extension.inspect, prohibited_types: Array(extension_blacklist).join(", "))
end
end
def blacklisted_extension?(extension)
Array(extension_blacklist).any? { |item| extension =~ /\A#{item}\z/i }
end
end
end
end
carrierwave-1.2.2/lib/carrierwave/uploader/extension_whitelist.rb 0000664 0000000 0000000 00000003261 13222647327 0025370 0 ustar 00root root 0000000 0000000 module CarrierWave
module Uploader
module ExtensionWhitelist
extend ActiveSupport::Concern
included do
before :cache, :check_extension_whitelist!
end
##
# Override this method in your uploader to provide a white list of extensions which
# are allowed to be uploaded. Compares the file's extension case insensitive.
# Furthermore, not only strings but Regexp are allowed as well.
#
# When using a Regexp in the white list, `\A` and `\z` are automatically added to
# the Regexp expression, also case insensitive.
#
# === Returns
#
# [NilClass, String, Regexp, Array[String, Regexp]] a white list of extensions which are allowed to be uploaded
#
# === Examples
#
# def extension_whitelist
# %w(jpg jpeg gif png)
# end
#
# Basically the same, but using a Regexp:
#
# def extension_whitelist
# [/jpe?g/, 'gif', 'png']
# end
#
def extension_whitelist; end
private
def check_extension_whitelist!(new_file)
extension = new_file.extension.to_s
if extension_whitelist && !whitelisted_extension?(extension)
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.extension_whitelist_error", extension: new_file.extension.inspect, allowed_types: Array(extension_whitelist).join(", "))
end
end
def whitelisted_extension?(extension)
downcase_extension = extension.downcase
Array(extension_whitelist).any? { |item| downcase_extension =~ /\A#{item}\z/i }
end
end # ExtensionWhitelist
end # Uploader
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/uploader/file_size.rb 0000664 0000000 0000000 00000002363 13222647327 0023233 0 ustar 00root root 0000000 0000000 require 'active_support'
module CarrierWave
module Uploader
module FileSize
extend ActiveSupport::Concern
included do
before :cache, :check_size!
end
##
# Override this method in your uploader to provide a Range of Size which
# are allowed to be uploaded.
# === Returns
#
# [NilClass, Range] a size range which are permitted to be uploaded
#
# === Examples
#
# def size_range
# 3256...5748
# end
#
def size_range; end
private
def check_size!(new_file)
size = new_file.size
expected_size_range = size_range
if expected_size_range.is_a?(::Range)
if size < expected_size_range.min
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.min_size_error", :min_size => ActiveSupport::NumberHelper.number_to_human_size(expected_size_range.min))
elsif size > expected_size_range.max
raise CarrierWave::IntegrityError, I18n.translate(:"errors.messages.max_size_error", :max_size => ActiveSupport::NumberHelper.number_to_human_size(expected_size_range.max))
end
end
end
end # FileSize
end # Uploader
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/uploader/magic_mime_blacklist.rb 0000664 0000000 0000000 00000004674 13222647327 0025410 0 ustar 00root root 0000000 0000000 module CarrierWave
module Uploader
##
# This modules validates the content type of a file with the use of
# ruby-filemagic gem and a blacklist regular expression. If you want
# to use this, you'll need to require this file:
#
# require 'carrierwave/uploader/magic_mime_blacklist'
#
# And then include it in your uploader:
#
# class MyUploader < CarrierWave::Uploader::Base
# include CarrierWave::Uploader::MagicMimeBlacklist
#
# def blacklist_mime_type_pattern
# /image\//
# end
# end
#
module MagicMimeBlacklist
extend ActiveSupport::Concern
included do
begin
require "filemagic"
rescue LoadError => e
e.message << " (You may need to install the ruby-filemagic gem)"
raise e
end
before :cache, :check_blacklist_pattern!
end
##
# Override this method in your uploader to provide a black list pattern (regexp)
# of content-types which are prohibited to be uploaded.
# Compares the file's content-type.
#
# === Returns
#
# [Regexp] a black list regexp to match the content_type
#
# === Examples
#
# def blacklist_mime_type_pattern
# /(text|application)\/json/
# end
#
def blacklist_mime_type_pattern; end
private
def check_blacklist_pattern!(new_file)
return if blacklist_mime_type_pattern.nil?
content_type = extract_content_type(new_file)
if content_type.match(blacklist_mime_type_pattern)
raise CarrierWave::IntegrityError,
I18n.translate(:"errors.messages.mime_type_pattern_black_list_error",
:content_type => content_type)
end
end
##
# Extracts the content type of the given file
#
# === Returns
#
# [String] the extracted content type
#
def extract_content_type(new_file)
content_type = nil
File.open(new_file.path) do |fd|
data = fd.read(1024) || ""
content_type = filemagic.buffer(data)
end
content_type
end
##
# FileMagic object with the MAGIC_MIME_TYPE flag set
#
# @return [FileMagic] a filemagic object
def filemagic
@filemagic ||= FileMagic.new(FileMagic::MAGIC_MIME_TYPE)
end
end # MagicMimeblackList
end # Uploader
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/uploader/magic_mime_whitelist.rb 0000664 0000000 0000000 00000004672 13222647327 0025452 0 ustar 00root root 0000000 0000000 module CarrierWave
module Uploader
##
# This modules validates the content type of a file with the use of
# ruby-filemagic gem and a whitelist regular expression. If you want
# to use this, you'll need to require this file:
#
# require 'carrierwave/uploader/magic_mime_whitelist'
#
# And then include it in your uploader:
#
# class MyUploader < CarrierWave::Uploader::Base
# include CarrierWave::Uploader::MagicMimeWhitelist
#
# def whitelist_mime_type_pattern
# /image\//
# end
# end
#
module MagicMimeWhitelist
extend ActiveSupport::Concern
included do
begin
require "filemagic"
rescue LoadError => e
e.message << " (You may need to install the ruby-filemagic gem)"
raise e
end
before :cache, :check_whitelist_pattern!
end
##
# Override this method in your uploader to provide a white list pattern (regexp)
# of content-types which are allowed to be uploaded.
# Compares the file's content-type.
#
# === Returns
#
# [Regexp] a white list regexp to match the content_type
#
# === Examples
#
# def whitelist_mime_type_pattern
# /(text|application)\/json/
# end
#
def whitelist_mime_type_pattern; end
private
def check_whitelist_pattern!(new_file)
return if whitelist_mime_type_pattern.nil?
content_type = extract_content_type(new_file)
if !content_type.match(whitelist_mime_type_pattern)
raise CarrierWave::IntegrityError,
I18n.translate(:"errors.messages.mime_type_pattern_white_list_error",
:content_type => content_type)
end
end
##
# Extracts the content type of the given file
#
# === Returns
#
# [String] the extracted content type
#
def extract_content_type(new_file)
content_type = nil
File.open(new_file.path) do |fd|
data = fd.read(1024) || ""
content_type = filemagic.buffer(data)
end
content_type
end
##
# FileMagic object with the MAGIC_MIME_TYPE flag set
#
# @return [FileMagic] a filemagic object
def filemagic
@filemagic ||= FileMagic.new(FileMagic::MAGIC_MIME_TYPE)
end
end # MagicMimeWhiteList
end # Uploader
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/uploader/mountable.rb 0000664 0000000 0000000 00000002241 13222647327 0023243 0 ustar 00root root 0000000 0000000 module CarrierWave
module Uploader
module Mountable
attr_reader :model, :mounted_as
##
# If a model is given as the first parameter, it will be stored in the
# uploader, and available through +#model+. Likewise, mounted_as stores
# the name of the column where this instance of the uploader is mounted.
# These values can then be used inside your uploader.
#
# If you do not wish to mount your uploaders with the ORM extensions in
# -more then you can override this method inside your uploader. Just be
# sure to call +super+
#
# === Parameters
#
# [model (Object)] Any kind of model object
# [mounted_as (Symbol)] The name of the column where this uploader is mounted
#
# === Examples
#
# class MyUploader < CarrierWave::Uploader::Base
#
# def store_dir
# File.join('public', 'files', mounted_as, model.permalink)
# end
# end
#
def initialize(model=nil, mounted_as=nil)
@model = model
@mounted_as = mounted_as
end
end # Mountable
end # Uploader
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/uploader/processing.rb 0000664 0000000 0000000 00000004771 13222647327 0023443 0 ustar 00root root 0000000 0000000 module CarrierWave
module Uploader
module Processing
extend ActiveSupport::Concern
include CarrierWave::Uploader::Callbacks
included do
class_attribute :processors, :instance_writer => false
self.processors = []
before :cache, :process!
end
module ClassMethods
##
# Adds a processor callback which applies operations as a file is uploaded.
# The argument may be the name of any method of the uploader, expressed as a symbol,
# or a list of such methods, or a hash where the key is a method and the value is
# an array of arguments to call the method with
#
# === Parameters
#
# args (*Symbol, Hash{Symbol => Array[]})
#
# === Examples
#
# class MyUploader < CarrierWave::Uploader::Base
#
# process :sepiatone, :vignette
# process :scale => [200, 200]
# process :scale => [200, 200], :if => :image?
# process :sepiatone, :if => :image?
#
# def sepiatone
# ...
# end
#
# def vignette
# ...
# end
#
# def scale(height, width)
# ...
# end
#
# def image?
# ...
# end
#
# end
#
def process(*args)
new_processors = args.inject({}) do |hash, arg|
arg = { arg => [] } unless arg.is_a?(Hash)
hash.merge!(arg)
end
condition = new_processors.delete(:if)
new_processors.each do |processor, processor_args|
self.processors += [[processor, processor_args, condition]]
end
end
end # ClassMethods
##
# Apply all process callbacks added through CarrierWave.process
#
def process!(new_file=nil)
return unless enable_processing
with_callbacks(:process, new_file) do
self.class.processors.each do |method, args, condition|
if(condition)
if condition.respond_to?(:call)
next unless condition.call(self, :args => args, :method => method, :file => new_file)
else
next unless self.send(condition, new_file)
end
end
self.send(method, *args)
end
end
end
end # Processing
end # Uploader
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/uploader/proxy.rb 0000664 0000000 0000000 00000003102 13222647327 0022433 0 ustar 00root root 0000000 0000000 module CarrierWave
module Uploader
module Proxy
##
# === Returns
#
# [Boolean] Whether the uploaded file is blank
#
def blank?
file.blank?
end
##
# === Returns
#
# [String] the path where the file is currently located.
#
def current_path
file.try(:path)
end
alias_method :path, :current_path
##
# Returns a string that uniquely identifies the last stored file
#
# === Returns
#
# [String] uniquely identifies a file
#
def identifier
storage.try(:identifier)
end
##
# Read the contents of the file
#
# === Returns
#
# [String] contents of the file
#
def read
file.try(:read)
end
##
# Fetches the size of the currently stored/cached file
#
# === Returns
#
# [Integer] size of the file
#
def size
file.try(:size) || 0
end
##
# Return the size of the file when asked for its length
#
# === Returns
#
# [Integer] size of the file
#
# === Note
#
# This was added because of the way Rails handles length/size validations in 3.0.6 and above.
#
def length
size
end
##
# Read the content type of the file
#
# === Returns
#
# [String] content type of the file
#
def content_type
file.try(:content_type)
end
end # Proxy
end # Uploader
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/uploader/remove.rb 0000664 0000000 0000000 00000000623 13222647327 0022554 0 ustar 00root root 0000000 0000000 module CarrierWave
module Uploader
module Remove
extend ActiveSupport::Concern
include CarrierWave::Uploader::Callbacks
##
# Removes the file and reset it
#
def remove!
with_callbacks(:remove) do
@file.delete if @file
@file = nil
@cache_id = nil
end
end
end # Remove
end # Uploader
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/uploader/serialization.rb 0000664 0000000 0000000 00000001214 13222647327 0024131 0 ustar 00root root 0000000 0000000 require "json"
require "active_support/core_ext/hash"
module CarrierWave
module Uploader
module Serialization
extend ActiveSupport::Concern
def serializable_hash(options = nil)
{"url" => url}.merge Hash[versions.map { |name, version| [name, { "url" => version.url }] }]
end
def as_json(options=nil)
serializable_hash
end
def to_json(options=nil)
JSON.generate(as_json)
end
def to_xml(options={})
merged_options = options.merge(:root => mounted_as || "uploader", :type => 'uploader')
serializable_hash.to_xml(merged_options)
end
end
end
end
carrierwave-1.2.2/lib/carrierwave/uploader/store.rb 0000664 0000000 0000000 00000005056 13222647327 0022420 0 ustar 00root root 0000000 0000000 module CarrierWave
module Uploader
module Store
extend ActiveSupport::Concern
include CarrierWave::Uploader::Callbacks
include CarrierWave::Uploader::Configuration
include CarrierWave::Uploader::Cache
##
# Override this in your Uploader to change the filename.
#
# Be careful using record ids as filenames. If the filename is stored in the database
# the record id will be nil when the filename is set. Don't use record ids unless you
# understand this limitation.
#
# Do not use the version_name in the filename, as it will prevent versions from being
# loaded correctly.
#
# === Returns
#
# [String] a filename
#
def filename
@filename
end
##
# Calculates the path where the file should be stored. If +for_file+ is given, it will be
# used as the filename, otherwise +CarrierWave::Uploader#filename+ is assumed.
#
# === Parameters
#
# [for_file (String)] name of the file
#
# === Returns
#
# [String] the store path
#
def store_path(for_file=filename)
File.join([store_dir, full_filename(for_file)].compact)
end
##
# Stores the file by passing it to this Uploader's storage engine.
#
# If new_file is omitted, a previously cached file will be stored.
#
# === Parameters
#
# [new_file (File, IOString, Tempfile)] any kind of file object
#
def store!(new_file=nil)
cache!(new_file) if new_file && ((@cache_id != parent_cache_id) || @cache_id.nil?)
if !cache_only and @file and @cache_id
with_callbacks(:store, new_file) do
new_file = storage.store!(@file)
if delete_tmp_file_after_storage
@file.delete unless move_to_store
cache_storage.delete_dir!(cache_path(nil))
end
@file = new_file
@cache_id = nil
end
end
end
##
# Retrieves the file from the storage.
#
# === Parameters
#
# [identifier (String)] uniquely identifies the file to retrieve
#
def retrieve_from_store!(identifier)
with_callbacks(:retrieve_from_store, identifier) do
@file = storage.retrieve!(identifier)
end
end
private
def full_filename(for_file)
for_file
end
def storage
@storage ||= self.class.storage.new(self)
end
end # Store
end # Uploader
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/uploader/url.rb 0000664 0000000 0000000 00000002000 13222647327 0022050 0 ustar 00root root 0000000 0000000 module CarrierWave
module Uploader
module Url
extend ActiveSupport::Concern
include CarrierWave::Uploader::Configuration
include CarrierWave::Utilities::Uri
##
# === Parameters
#
# [Hash] optional, the query params (only AWS)
#
# === Returns
#
# [String] the location where this file is accessible via a url
#
def url(options = {})
if file.respond_to?(:url) and not (tmp_url = file.url).blank?
file.method(:url).arity == 0 ? tmp_url : file.url(options)
elsif file.respond_to?(:path)
path = encode_path(file.path.sub(File.expand_path(root), ''))
if host = asset_host
if host.respond_to? :call
"#{host.call(file)}#{path}"
else
"#{host}#{path}"
end
else
(base_path || "") + path
end
end
end
def to_s
url || ''
end
end # Url
end # Uploader
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/uploader/versions.rb 0000664 0000000 0000000 00000021722 13222647327 0023132 0 ustar 00root root 0000000 0000000 module CarrierWave
module Uploader
module Versions
extend ActiveSupport::Concern
include CarrierWave::Uploader::Callbacks
included do
class_attribute :versions, :version_names, :version_options, :instance_reader => false, :instance_writer => false
self.versions = {}
self.version_names = []
attr_accessor :parent_cache_id, :parent_version
after :cache, :assign_parent_cache_id
after :cache, :cache_versions!
after :store, :store_versions!
after :remove, :remove_versions!
after :retrieve_from_cache, :retrieve_versions_from_cache!
after :retrieve_from_store, :retrieve_versions_from_store!
end
module ClassMethods
##
# Adds a new version to this uploader
#
# === Parameters
#
# [name (#to_sym)] name of the version
# [options (Hash)] optional options hash
# [&block (Proc)] a block to eval on this version of the uploader
#
# === Examples
#
# class MyUploader < CarrierWave::Uploader::Base
#
# version :thumb do
# process :scale => [200, 200]
# end
#
# version :preview, :if => :image? do
# process :scale => [200, 200]
# end
#
# end
#
def version(name, options = {}, &block)
name = name.to_sym
build_version(name, options)
versions[name].class_eval(&block) if block
versions[name]
end
def recursively_apply_block_to_versions(&block)
versions.each do |name, version|
version.class_eval(&block)
version.recursively_apply_block_to_versions(&block)
end
end
private
def build_version(name, options)
if !versions.has_key?(name)
uploader = Class.new(self)
const_set("Uploader#{uploader.object_id}".tr('-', '_'), uploader)
uploader.version_names += [name]
uploader.versions = {}
uploader.processors = []
uploader.version_options = options
uploader.class_eval <<-RUBY, __FILE__, __LINE__ + 1
# Define the enable_processing method for versions so they get the
# value from the parent class unless explicitly overwritten
def self.enable_processing(value=nil)
self.enable_processing = value if value
if !@enable_processing.nil?
@enable_processing
else
superclass.enable_processing
end
end
# Regardless of what is set in the parent uploader, do not enforce the
# move_to_cache config option on versions because it moves the original
# file to the version's target file.
#
# If you want to enforce this setting on versions, override this method
# in each version:
#
# version :thumb do
# def move_to_cache
# true
# end
# end
#
def move_to_cache
false
end
RUBY
class_eval <<-RUBY, __FILE__, __LINE__ + 1
def #{name}
versions[:#{name}]
end
RUBY
else
uploader = Class.new(versions[name])
const_set("Uploader#{uploader.object_id}".tr('-', '_'), uploader)
uploader.processors = []
uploader.version_options = uploader.version_options.merge(options)
end
# Add the current version hash to class attribute :versions
self.versions = versions.merge(name => uploader)
end
end # ClassMethods
##
# Returns a hash mapping the name of each version of the uploader to an instance of it
#
# === Returns
#
# [Hash{Symbol => CarrierWave::Uploader}] a list of uploader instances
#
def versions
return @versions if @versions
@versions = {}
self.class.versions.each do |name, version|
@versions[name] = version.new(model, mounted_as)
@versions[name].parent_version = self
end
@versions
end
##
# === Returns
#
# [String] the name of this version of the uploader
#
def version_name
self.class.version_names.join('_').to_sym unless self.class.version_names.blank?
end
##
#
# === Parameters
#
# [name (#to_sym)] name of the version
#
# === Returns
#
# [Boolean] True when the version exists according to its :if condition
#
def version_exists?(name)
name = name.to_sym
return false unless self.class.versions.has_key?(name)
condition = self.class.versions[name].version_options[:if]
if(condition)
if(condition.respond_to?(:call))
condition.call(self, :version => name, :file => file)
else
send(condition, file)
end
else
true
end
end
##
# When given a version name as a parameter, will return the url for that version
# This also works with nested versions.
# When given a query hash as a parameter, will return the url with signature that contains query params
# Query hash only works with AWS (S3 storage).
#
# === Example
#
# my_uploader.url # => /path/to/my/uploader.gif
# my_uploader.url(:thumb) # => /path/to/my/thumb_uploader.gif
# my_uploader.url(:thumb, :small) # => /path/to/my/thumb_small_uploader.gif
# my_uploader.url(:query => {"response-content-disposition" => "attachment"})
# my_uploader.url(:version, :sub_version, :query => {"response-content-disposition" => "attachment"})
#
# === Parameters
#
# [*args (Symbol)] any number of versions
# OR/AND
# [Hash] query params
#
# === Returns
#
# [String] the location where this file is accessible via a url
#
def url(*args)
if (version = args.first) && version.respond_to?(:to_sym)
raise ArgumentError, "Version #{version} doesn't exist!" if versions[version.to_sym].nil?
# recursively proxy to version
versions[version.to_sym].url(*args[1..-1])
elsif args.first
super(args.first)
else
super
end
end
##
# Recreate versions and reprocess them. This can be used to recreate
# versions if their parameters somehow have changed.
#
def recreate_versions!(*versions)
# Some files could possibly not be stored on the local disk. This
# doesn't play nicely with processing. Make sure that we're only
# processing a cached file
#
# The call to store! will trigger the necessary callbacks to both
# process this version and all sub-versions
if versions.any?
file = sanitized_file if !cached?
store_versions!(file, versions)
else
cache! if !cached?
store!
end
end
private
def assign_parent_cache_id(file)
active_versions.each do |name, uploader|
uploader.parent_cache_id = @cache_id
end
end
def active_versions
versions.select do |name, uploader|
version_exists?(name)
end
end
def dependent_versions
active_versions.reject do |name, v|
v.class.version_options[:from_version]
end.to_a + sibling_versions.select do |name, v|
v.class.version_options[:from_version] == self.class.version_names.last
end.to_a
end
def sibling_versions
parent_version.try(:versions) || []
end
def full_filename(for_file)
[version_name, super(for_file)].compact.join('_')
end
def full_original_filename
[version_name, super].compact.join('_')
end
def cache_versions!(new_file)
dependent_versions.each do |name, v|
v.send(:cache_id=, @cache_id)
v.cache!(new_file)
end
end
def store_versions!(new_file, versions=nil)
if versions
active = Hash[active_versions]
versions.each { |v| active[v].try(:store!, new_file) } unless active.empty?
else
active_versions.each { |name, v| v.store!(new_file) }
end
end
def remove_versions!
versions.each { |name, v| v.remove! }
end
def retrieve_versions_from_cache!(cache_name)
active_versions.each { |name, v| v.retrieve_from_cache!(cache_name) }
end
def retrieve_versions_from_store!(identifier)
active_versions.each { |name, v| v.retrieve_from_store!(identifier) }
end
end # Versions
end # Uploader
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/utilities.rb 0000664 0000000 0000000 00000000125 13222647327 0021454 0 ustar 00root root 0000000 0000000 require 'carrierwave/utilities/uri'
module CarrierWave
module Utilities
end
end
carrierwave-1.2.2/lib/carrierwave/utilities/ 0000775 0000000 0000000 00000000000 13222647327 0021131 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/lib/carrierwave/utilities/uri.rb 0000664 0000000 0000000 00000000765 13222647327 0022265 0 ustar 00root root 0000000 0000000 require 'uri'
module CarrierWave
module Utilities
module Uri
# based on Ruby < 2.0's URI.encode
SAFE_STRING = URI::REGEXP::PATTERN::UNRESERVED + '\/'
UNSAFE = Regexp.new("[^#{SAFE_STRING}]", false)
private
def encode_path(path)
path.to_s.gsub(UNSAFE) do
us = $&
tmp = ''
us.each_byte do |uc|
tmp << sprintf('%%%02X', uc)
end
tmp
end
end
end # Uri
end # Utilities
end # CarrierWave
carrierwave-1.2.2/lib/carrierwave/validations/ 0000775 0000000 0000000 00000000000 13222647327 0021433 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/lib/carrierwave/validations/active_model.rb 0000664 0000000 0000000 00000004725 13222647327 0024423 0 ustar 00root root 0000000 0000000 require 'active_model/validator'
require 'active_support/concern'
module CarrierWave
# == Active Model Presence Validator
module Validations
module ActiveModel
extend ActiveSupport::Concern
class ProcessingValidator < ::ActiveModel::EachValidator
def validate_each(record, attribute, value)
if e = record.__send__("#{attribute}_processing_error")
message = (e.message == e.class.to_s) ? :carrierwave_processing_error : e.message
record.errors.add(attribute, message)
end
end
end
class IntegrityValidator < ::ActiveModel::EachValidator
def validate_each(record, attribute, value)
if e = record.__send__("#{attribute}_integrity_error")
message = (e.message == e.class.to_s) ? :carrierwave_integrity_error : e.message
record.errors.add(attribute, message)
end
end
end
class DownloadValidator < ::ActiveModel::EachValidator
def validate_each(record, attribute, value)
if e = record.__send__("#{attribute}_download_error")
message = (e.message == e.class.to_s) ? :carrierwave_download_error : e.message
record.errors.add(attribute, message)
end
end
end
module HelperMethods
##
# Makes the record invalid if the file couldn't be uploaded due to an integrity error
#
# Accepts the usual parameters for validations in Rails (:if, :unless, etc...)
#
def validates_integrity_of(*attr_names)
validates_with IntegrityValidator, _merge_attributes(attr_names)
end
##
# Makes the record invalid if the file couldn't be processed (assuming the process failed
# with a CarrierWave::ProcessingError)
#
# Accepts the usual parameters for validations in Rails (:if, :unless, etc...)
#
def validates_processing_of(*attr_names)
validates_with ProcessingValidator, _merge_attributes(attr_names)
end
#
##
# Makes the record invalid if the remote file couldn't be downloaded
#
# Accepts the usual parameters for validations in Rails (:if, :unless, etc...)
#
def validates_download_of(*attr_names)
validates_with DownloadValidator, _merge_attributes(attr_names)
end
end
included do
extend HelperMethods
include HelperMethods
end
end
end
end
carrierwave-1.2.2/lib/carrierwave/version.rb 0000664 0000000 0000000 00000000053 13222647327 0021126 0 ustar 00root root 0000000 0000000 module CarrierWave
VERSION = "1.2.2"
end
carrierwave-1.2.2/lib/generators/ 0000775 0000000 0000000 00000000000 13222647327 0016755 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/lib/generators/templates/ 0000775 0000000 0000000 00000000000 13222647327 0020753 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/lib/generators/templates/uploader.rb 0000664 0000000 0000000 00000002735 13222647327 0023122 0 ustar 00root root 0000000 0000000 class <%= class_name %>Uploader < CarrierWave::Uploader::Base
# Include RMagick or MiniMagick support:
# include CarrierWave::RMagick
# include CarrierWave::MiniMagick
# Choose what kind of storage to use for this uploader:
storage :file
# storage :fog
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
# Provide a default URL as a default if there hasn't been a file uploaded:
# def default_url(*args)
# # For Rails 3.1+ asset pipeline compatibility:
# # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
#
# "/images/fallback/" + [version_name, "default.png"].compact.join('_')
# end
# Process files as they are uploaded:
# process scale: [200, 300]
#
# def scale(width, height)
# # do something
# end
# Create different versions of your uploaded files:
# version :thumb do
# process resize_to_fit: [50, 50]
# end
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
# def extension_whitelist
# %w(jpg jpeg gif png)
# end
# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
# def filename
# "something.jpg" if original_filename
# end
end
carrierwave-1.2.2/lib/generators/uploader_generator.rb 0000664 0000000 0000000 00000000364 13222647327 0023166 0 ustar 00root root 0000000 0000000 class UploaderGenerator < Rails::Generators::NamedBase
source_root File.expand_path("../templates", __FILE__)
def create_uploader_file
template "uploader.rb", File.join('app/uploaders', class_path, "#{file_name}_uploader.rb")
end
end carrierwave-1.2.2/script/ 0000775 0000000 0000000 00000000000 13222647327 0015342 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/script/console 0000775 0000000 0000000 00000000674 13222647327 0016741 0 ustar 00root root 0000000 0000000 #!/usr/bin/env ruby
# File: script/console
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
libs = " -r irb/completion"
# Perhaps use a console_lib to store any extra methods I may want available in the cosole
# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
libs << " -r #{File.dirname(__FILE__) + '/../lib/carrierwave.rb'}"
puts "Loading carrierwave gem"
exec "#{irb} #{libs} --simple-prompt" carrierwave-1.2.2/script/destroy 0000775 0000000 0000000 00000000603 13222647327 0016760 0 ustar 00root root 0000000 0000000 #!/usr/bin/env ruby
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
begin
require 'rubigen'
rescue LoadError
require 'rubygems'
require 'rubigen'
end
require 'rubigen/scripts/destroy'
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
RubiGen::Scripts::Destroy.new.run(ARGV)
carrierwave-1.2.2/script/generate 0000775 0000000 0000000 00000000605 13222647327 0017063 0 ustar 00root root 0000000 0000000 #!/usr/bin/env ruby
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
begin
require 'rubigen'
rescue LoadError
require 'rubygems'
require 'rubigen'
end
require 'rubigen/scripts/generate'
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
RubiGen::Scripts::Generate.new.run(ARGV)
carrierwave-1.2.2/spec/ 0000775 0000000 0000000 00000000000 13222647327 0014770 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/spec/compatibility/ 0000775 0000000 0000000 00000000000 13222647327 0017641 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/spec/compatibility/paperclip_spec.rb 0000664 0000000 0000000 00000007703 13222647327 0023166 0 ustar 00root root 0000000 0000000 require 'spec_helper'
require 'carrierwave/orm/activerecord'
module Rails; end unless defined?(Rails)
describe CarrierWave::Compatibility::Paperclip do
let(:uploader_class) do
Class.new(CarrierWave::Uploader::Base) do
include CarrierWave::Compatibility::Paperclip
version :thumb
version :list
end
end
let(:model) { double('model') }
let(:uploader) { uploader_class.new(model, :monkey) }
before do
allow(Rails).to receive(:root).and_return('/rails/root')
allow(Rails).to receive(:env).and_return('test')
allow(model).to receive(:id).and_return(23)
allow(model).to receive(:ook).and_return('eek')
allow(model).to receive(:money).and_return('monkey.png')
end
after { FileUtils.rm_rf(public_path) }
describe '#store_path' do
subject { uploader.store_path("monkey.png") }
it "mimics paperclip default" do
is_expected.to eq("/rails/root/public/system/monkeys/23/original/monkey.png")
end
it "interpolates the root path" do
allow(uploader).to receive(:paperclip_path).and_return(":rails_root/foo/bar")
is_expected.to eq(Rails.root + "/foo/bar")
end
it "interpolates the attachment" do
allow(uploader).to receive(:paperclip_path).and_return("/foo/:attachment/bar")
is_expected.to eq("/foo/monkeys/bar")
end
it "interpolates the id" do
allow(uploader).to receive(:paperclip_path).and_return("/foo/:id/bar")
is_expected.to eq("/foo/23/bar")
end
it "interpolates the id partition" do
allow(uploader).to receive(:paperclip_path).and_return("/foo/:id_partition/bar")
is_expected.to eq("/foo/000/000/023/bar")
end
it "interpolates the basename" do
allow(uploader).to receive(:paperclip_path).and_return("/foo/:basename/bar")
is_expected.to eq("/foo/monkey/bar")
end
it "interpolates the extension" do
allow(uploader).to receive(:paperclip_path).and_return("/foo/:extension/bar")
is_expected.to eq("/foo/png/bar")
end
end
describe '.interpolate' do
subject { uploader.store_path("monkey.png") }
before do
uploader_class.interpolate :ook do |custom, style|
custom.model.ook
end
uploader_class.interpolate :aak do |model, style|
style
end
end
it 'allows you to add custom interpolations' do
allow(uploader).to receive(:paperclip_path).and_return("/foo/:id/:ook")
is_expected.to eq('/foo/23/eek')
end
it 'mimics paperclips arguments' do
allow(uploader).to receive(:paperclip_path).and_return("/foo/:aak")
is_expected.to eq('/foo/original')
end
context 'when multiple uploaders include the compatibility module' do
let(:uploader) { uploader_class_other.new(model, :monkey) }
let(:uploader_class_other) do
Class.new(CarrierWave::Uploader::Base) do
include CarrierWave::Compatibility::Paperclip
version :thumb
version :list
end
end
before { allow(uploader).to receive(:paperclip_path).and_return("/foo/:id/:ook") }
it "doesn't share custom interpolations" do
is_expected.to eq('/foo/23/:ook')
end
end
context 'when there are multiple versions' do
let(:complex_uploader_class) do
Class.new(CarrierWave::Uploader::Base) do
include CarrierWave::Compatibility::Paperclip
interpolate :ook do |model, style|
'eek'
end
version :thumb
version :list
def paperclip_path
"#{public_path}/foo/:ook/:id/:style"
end
end
end
let(:uploader) { complex_uploader_class.new(model, :monkey) }
let!(:file) { File.open(file_path('test.jpg')) }
before { uploader.store!(file) }
it 'interpolates for all versions correctly' do
expect(uploader.thumb.path).to eq("#{public_path}/foo/eek/23/thumb")
expect(uploader.list.path).to eq("#{public_path}/foo/eek/23/list")
end
end
end
end
carrierwave-1.2.2/spec/fixtures/ 0000775 0000000 0000000 00000000000 13222647327 0016641 5 ustar 00root root 0000000 0000000 carrierwave-1.2.2/spec/fixtures/Uppercase.jpg 0000664 0000000 0000000 00000000015 13222647327 0021266 0 ustar 00root root 0000000 0000000 this is stuff carrierwave-1.2.2/spec/fixtures/bork.ttxt 0000664 0000000 0000000 00000000715 13222647327 0020526 0 ustar 00root root 0000000 0000000 bork bork bork Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. carrierwave-1.2.2/spec/fixtures/bork.txt 0000664 0000000 0000000 00000000715 13222647327 0020342 0 ustar 00root root 0000000 0000000 bork bork bork Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. carrierwave-1.2.2/spec/fixtures/bork.txtt 0000664 0000000 0000000 00000000715 13222647327 0020526 0 ustar 00root root 0000000 0000000 bork bork bork Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. carrierwave-1.2.2/spec/fixtures/case.JPG 0000664 0000000 0000000 00000000015 13222647327 0020112 0 ustar 00root root 0000000 0000000 this is stuff carrierwave-1.2.2/spec/fixtures/landscape.jpg 0000664 0000000 0000000 00000511326 13222647327 0021305 0 ustar 00root root 0000000 0000000 ˙Ř˙ŕ JFIF ˙áHiExif II*
† ( 1 ¨ 2 Ä i‡ Ř \ Panasonic DMC-FZ5 H H ACD Systems Digital Imaging 2005:07:18 13:17:36 # š‚ ‚ ť‚ Š " ' P 0220 ’ ¦ ‘ ‘ ş ’
 ’ Ę ’ ’ ’
’ Ň |’ \ Ú ’ 718 0100 € ŕ 6 ˘ Ł Ł ¤ ¤ ¤ ¤ T ¤ K ¤ ¤ ¤ ¤
¤
Ä (
2005:07:15 11:58:30 2005:07:15 11:58:30 d
(
Panasonic ! ú ę " # $ % ä &