Commit cce95085b60147dca5e5d3d3fe77bed193b1578b

Authored by Braulio Bhavamitra
1 parent 3ffe1796

rails4.1: upgrade will_paginate, delayed_job and attachment_fu

Showing 142 changed files with 6 additions and 9253 deletions   Show diff stats
Gemfile
1 1 source "https://rubygems.org"
2   -gem 'rails', '~> 4.0'
  2 +gem 'rails', '~> 4.1'
3 3 gem 'minitest', '~> 3.2.0'
4 4 gem 'fast_gettext', '~> 0.6.8'
5 5 gem 'acts-as-taggable-on', '~> 3.4.2'
... ... @@ -7,11 +7,14 @@ gem 'rails_autolink', '~> 1.1.5'
7 7 gem 'pg', '~> 0.13.2'
8 8 gem 'rmagick', '~> 2.13.1'
9 9 gem 'RedCloth', '~> 4.2.9'
10   -gem 'will_paginate', '~> 3.0.3'
11 10 gem 'ruby-feedparser', '~> 0.7'
12 11 gem 'daemons', '~> 1.1.5'
13 12 gem 'thin', '~> 1.3.1'
14 13 gem 'nokogiri', '~> 1.5.5'
  14 +gem 'will_paginate'
  15 +gem 'pothoven-attachment_fu'
  16 +gem 'delayed_job'
  17 +gem 'delayed_job_active_record'
15 18 gem 'rake', :require => false
16 19 gem 'rest-client', '~> 1.6.7'
17 20 gem 'exception_notification', '~> 4.0.1'
... ... @@ -30,6 +33,7 @@ gem 'rails-observers'
30 33 gem 'actionpack-page_caching'
31 34 gem 'actionpack-action_caching'
32 35 gem 'activerecord-session_store'
  36 +gem 'activerecord-deprecated_finders', require: 'active_record/deprecated_finders'
33 37  
34 38  
35 39 # FIXME list here all actual dependencies (i.e. the ones in debian/control),
... ...
vendor/plugins/delayed_job/.rspec
... ... @@ -1,3 +0,0 @@
1   ---color
2   ---fail-fast
3   ---order random
vendor/plugins/delayed_job/.travis.yml
... ... @@ -1,22 +0,0 @@
1   -language: ruby
2   -only:
3   - - master
4   -rvm:
5   - - jruby-19mode
6   - - rbx-19mode
7   - - 1.9.2
8   - - 1.9.3
9   - - 2.0.0
10   -env:
11   - matrix:
12   - - "RAILS_VERSION=\"~> 3.0.0\""
13   - - "RAILS_VERSION=\"~> 3.1.0\""
14   - - "RAILS_VERSION=\"~> 3.2.0\""
15   - - "RAILS_VERSION=\"~> 4.0.0\""
16   -matrix:
17   - exclude:
18   - - rvm: 1.9.2
19   - env: "RAILS_VERSION=\"~> 4.0.0\""
20   - allow_failures:
21   - - rvm: jruby-19mode
22   - - rvm: rbx-19mode
23 0 \ No newline at end of file
vendor/plugins/delayed_job/CHANGELOG.md
... ... @@ -1,170 +0,0 @@
1   -4.0.0 - 2013-07-30
2   -==================
3   -* Rails 4 compatibility
4   -* Reverted threaded startup due to daemons incompatibilities
5   -* Attempt to recover from job reservation errors
6   -
7   -4.0.0.beta2 - 2013-05-28
8   -========================
9   -* Rails 4 compatibility
10   -* Threaded startup script for faster multi-worker startup
11   -* YAML compatibility changes
12   -* Added jobs:check rake task
13   -
14   -4.0.0.beta1 - 2013-03-02
15   -========================
16   -* Rails 4 compatibility
17   -
18   -3.0.5 - 2013-01-28
19   -==================
20   -* Better job timeout error logging
21   -* psych support for delayed_job_data_mapper deserialization
22   -* User can configure the worker to raise a SignalException on TERM and/or INT
23   -* Add the ability to run all available jobs and exit when complete
24   -
25   -3.0.4 - 2012-11-09
26   -==================
27   -* Allow the app to specify a default queue name
28   -* Capistrano script now allows user to specify the DJ command, allowing the user to add "bundle exec" if necessary
29   -* Persisted record check is now more general
30   -
31   -3.0.3 - 2012-05-25
32   -==================
33   -* Fix a bug where the worker would not respect the exit condition
34   -* Properly handle sleep delay command line argument
35   -
36   -3.0.2 - 2012-04-02
37   -==================
38   -* Fix deprecation warnings
39   -* Raise ArgumentError if attempting to enqueue a performable method on an object that hasn't been persisted yet
40   -* Allow the number of jobs read at a time to be configured from the command line using --read-ahead
41   -* Allow custom logger to be configured through Delayed::Worker.logger
42   -* Various documentation improvements
43   -
44   -3.0.1 - 2012-01-24
45   -==================
46   -* Added RecordNotFound message to deserialization error
47   -* Direct JRuby's yecht parser to syck extensions
48   -* Updated psych extensions for better compatibility with ruby 1.9.2
49   -* Updated syck extension for increased compatibility with class methods
50   -* Test grooming
51   -
52   -3.0.0 - 2011-12-30
53   -==================
54   -* New: Named queues
55   -* New: Job/Worker lifecycle callbacks
56   -* Change: daemons is no longer a runtime dependency
57   -* Change: Active Record backend support is provided by a separate gem
58   -* Change: Enqueue hook is called before jobs are saved so that they may be modified
59   -* Fix problem deserializing models that use a custom primary key column
60   -* Fix deserializing AR models when the object isn't in the default scope
61   -* Fix hooks not getting called when delay_jobs is false
62   -
63   -2.1.4 - 2011-02-11
64   -==================
65   -* Working around issues when psych is loaded, fixes issues with bundler 1.0.10 and Rails 3.0.4
66   -* Added -p/--prefix option to help differentiate multiple delayed job workers on the same host.
67   -
68   -2.1.3 - 2011-01-20
69   -==================
70   -* Revert worker contention fix due to regressions
71   -* Added Delayed::Worker.delay_jobs flag to support running jobs immediately
72   -
73   -2.1.2 - 2010-12-01
74   -==================
75   -* Remove contention between multiple workers by performing an update to lock a job before fetching it
76   -* Job payloads may implement #max_attempts to control how many times it should be retried
77   -* Fix for loading ActionMailer extension
78   -* Added 'delayed_job_server_role' Capistrano variable to allow delayed_job to run on its own worker server
79   - set :delayed_job_server_role, :worker
80   -* Fix `rake jobs:work` so it outputs to the console
81   -
82   -2.1.1 - 2010-11-14
83   -==================
84   -* Fix issue with worker name not getting properly set when locking a job
85   -* Fixes for YAML serialization
86   -
87   -2.1.0 - 2010-11-14
88   -==================
89   -* Added enqueue, before, after, success, error, and failure. See the README
90   -* Remove Merb support
91   -* Remove all non Active Record backends into separate gems. See https://github.com/collectiveidea/delayed_job/wiki/Backends
92   -* remove rails 2 support. delayed_job 2.1 will only support Rails 3
93   -* New pure-YAML serialization
94   -* Added Rails 3 railtie and generator
95   -* Changed @@sleep_delay to self.class.sleep_delay to be consistent with other class variable usage
96   -* Added --sleep-delay command line option
97   -
98   -2.0.8 - Unreleased
99   -==================
100   -* Backport fix for deserialization errors that bring down the daemon
101   -
102   -2.0.7 - 2011-02-10
103   -==================
104   -* Fixed missing generators and recipes for Rails 2.x
105   -
106   -2.0.6 - 2011-01-20
107   -==================
108   -* Revert worker contention fix due to regressions
109   -
110   -2.0.5 - 2010-12-01
111   -==================
112   -* Added #reschedule_at hook on payload to determine when the job should be rescheduled [backported from 2.1]
113   -* Added --sleep-delay command line option [backported from 2.1]
114   -* Added 'delayed_job_server_role' Capistrano variable to allow delayed_job to run on its own worker server
115   - set :delayed_job_server_role, :worker
116   -* Changed AR backend to reserve jobs using an UPDATE query to reduce worker contention [backported from 2.1]
117   -
118   -2.0.4 - 2010-11-14
119   -==================
120   -* Fix issue where dirty tracking prevented job from being properly unlocked
121   -* Add delayed_job_args variable for Capistrano recipe to allow configuration of started workers (e.g. "-n 2 --max-priority 10")
122   -* Added options to handle_asynchronously
123   -* Added Delayed::Worker.default_priority
124   -* Allow private methods to be delayed
125   -* Fixes for Ruby 1.9
126   -* Added -m command line option to start a monitor process
127   -* normalize logging in worker
128   -* Deprecate #send_later and #send_at in favor of new #delay method
129   -* Added @#delay@ to Object that allows you to delay any method and pass options:
130   - options = {:priority => 19, :run_at => 5.minutes.from_now}
131   - UserMailer.delay(options).deliver_confirmation(@user)
132   -
133   -2.0.3 - 2010-04-16
134   -==================
135   -* Fix initialization for Rails 2.x
136   -
137   -2.0.2 - 2010-04-08
138   -==================
139   -* Fixes to Mongo Mapper backend [ "14be7a24":http://github.com/collectiveidea/delayed_job/commit/14be7a24, "dafd5f46":http://github.com/collectiveidea/delayed_job/commit/dafd5f46, "54d40913":http://github.com/collectiveidea/delayed_job/commit/54d40913 ]
140   -* DataMapper backend performance improvements [ "93833cce":http://github.com/collectiveidea/delayed_job/commit/93833cce, "e9b1573e":http://github.com/collectiveidea/delayed_job/commit/e9b1573e, "37a16d11":http://github.com/collectiveidea/delayed_job/commit/37a16d11, "803f2bfa":http://github.com/collectiveidea/delayed_job/commit/803f2bfa ]
141   -* Fixed Delayed::Command to create tmp/pids directory [ "8ec8ca41":http://github.com/collectiveidea/delayed_job/commit/8ec8ca41 ]
142   -* Railtie to perform Rails 3 initialization [ "3e0fc41f":http://github.com/collectiveidea/delayed_job/commit/3e0fc41f ]
143   -* Added on_permanent_failure hook [ "d2f14cd6":http://github.com/collectiveidea/delayed_job/commit/d2f14cd6 ]
144   -
145   -2.0.1 - 2010-04-03
146   -==================
147   -* Bug fix for using ActiveRecord backend with daemon [martinbtt]
148   -
149   -2.0.0 - 2010-04-03
150   -==================
151   -* Multiple backend support (See README for more details)
152   -* Added MongoMapper backend [zbelzer, moneypools]
153   -* Added DataMapper backend [lpetre]
154   -* Reverse priority so the jobs table can be indexed. Lower numbers have higher priority. The default priority is 0, so increase it for jobs that are not important.
155   -* Move most of the heavy lifting from Job to Worker (#work_off, #reschedule, #run, #min_priority, #max_priority, #max_run_time, #max_attempts, #worker_name) [albus522]
156   -* Remove EvaledJob. Implement your own if you need this functionality.
157   -* Only use Time.zone if it is set. Closes #20
158   -* Fix for last_error recording when destroy_failed_jobs = false, max_attempts = 1
159   -* Implemented worker name_prefix to maintain dynamic nature of pid detection
160   -* Some Rails 3 compatibility fixes [fredwu]
161   -
162   -1.8.5 - 2010-03-15
163   -==================
164   -* Set auto_flushing=true on Rails logger to fix logging in production
165   -* Fix error message when trying to send_later on a method that doesn't exist
166   -* Don't use rails_env in capistrano if it's not set. closes #22
167   -* Delayed job should append to delayed_job.log not overwrite
168   -* Version bump to 1.8.5
169   -* fixing Time.now to be Time.zone.now if set to honor the app set local TimeZone
170   -* Replaced @Worker::SLEEP@, @Job::MAX_ATTEMPTS@, and @Job::MAX_RUN_TIME@ with class methods that can be overridden.
vendor/plugins/delayed_job/CONTRIBUTING.md
... ... @@ -1,27 +0,0 @@
1   -How to contribute
2   -=================
3   -
4   -If you find what looks like a bug:
5   -
6   -* Search the "mailing list":http://groups.google.com/group/delayed_job to see
7   - if anyone else had the same issue.
8   -* Check the "GitHub issue tracker":http://github.com/collectiveidea/delayed_job/issues/
9   - to see if anyone else has reported issue.
10   -* Make sure you are using the latest version of delayed_job
11   - ![Gem Version](https://badge.fury.io/rb/delayed_job.png)
12   -* Make sure you are using the latest backend gem for delayed_job
13   - * Active Record ![Gem Version](https://badge.fury.io/rb/delayed_job_active_record.png)
14   - * Mongoid ![Gem Version](https://badge.fury.io/rb/delayed_job_mongoid.png)
15   -* If you are still having an issue, create an issue including:
16   - * Ruby version
17   - * Gemfile.lock contents or at least major gem versions, such as Rails version
18   - * Steps to reproduce the issue
19   - * Full backtrace for any errors encountered
20   -
21   -If you want to contribute an enhancement or a fix:
22   -
23   -* Fork the project on GitHub.
24   -* Make your changes with tests.
25   -* Commit the changes without making changes to the Rakefile or any other files
26   - that aren't related to your enhancement or fix.
27   -* Send a pull request.
vendor/plugins/delayed_job/Gemfile
... ... @@ -1,22 +0,0 @@
1   -source 'https://rubygems.org'
2   -
3   -gem 'rake'
4   -
5   -platforms :ruby do
6   - gem 'sqlite3'
7   -end
8   -
9   -platforms :jruby do
10   - gem 'jruby-openssl'
11   - gem 'activerecord-jdbcsqlite3-adapter'
12   -end
13   -
14   -group :test do
15   - gem 'activerecord', (ENV['RAILS_VERSION'] || ['>= 3.0', '< 4.1'])
16   - gem 'actionmailer', (ENV['RAILS_VERSION'] || ['>= 3.0', '< 4.1'])
17   - gem 'coveralls', :require => false
18   - gem 'rspec', '>= 2.11'
19   - gem 'simplecov', :require => false
20   -end
21   -
22   -gemspec
vendor/plugins/delayed_job/LICENSE.md
... ... @@ -1,20 +0,0 @@
1   -Copyright (c) 2005 Tobias Lütke
2   -
3   -Permission is hereby granted, free of charge, to any person obtaining
4   -a copy of this software and associated documentation files (the
5   -"Software"), to deal in the Software without restriction, including
6   -without limitation the rights to use, copy, modify, merge, publish,
7   -distribute, sublicense, and/or sell copies of the Software, and to
8   -permit persons to whom the Software is furnished to do so, subject to
9   -the following conditions:
10   -
11   -The above copyright notice and this permission notice shall be
12   -included in all copies or substantial portions of the Software.
13   -
14   -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15   -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16   -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOa AND
17   -NONINFRINGEMENT. IN NO EVENT SaALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18   -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19   -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20   -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
vendor/plugins/delayed_job/README.md
... ... @@ -1,346 +0,0 @@
1   -Delayed::Job
2   -============
3   -[![Gem Version](https://badge.fury.io/rb/delayed_job.png)][gem]
4   -[![Build Status](https://secure.travis-ci.org/collectiveidea/delayed_job.png?branch=master)][travis]
5   -[![Dependency Status](https://gemnasium.com/collectiveidea/delayed_job.png?travis)][gemnasium]
6   -[![Code Climate](https://codeclimate.com/github/collectiveidea/delayed_job.png)][codeclimate]
7   -[![Coverage Status](https://coveralls.io/repos/collectiveidea/delayed_job/badge.png?branch=master)][coveralls]
8   -
9   -[gem]: https://rubygems.org/gems/delayed_job
10   -[travis]: http://travis-ci.org/collectiveidea/delayed_job
11   -[gemnasium]: https://gemnasium.com/collectiveidea/delayed_job
12   -[codeclimate]: https://codeclimate.com/github/collectiveidea/delayed_job
13   -[coveralls]: https://coveralls.io/r/collectiveidea/delayed_job
14   -
15   -Delayed::Job (or DJ) encapsulates the common pattern of asynchronously executing
16   -longer tasks in the background.
17   -
18   -It is a direct extraction from Shopify where the job table is responsible for a
19   -multitude of core tasks. Amongst those tasks are:
20   -
21   -* sending massive newsletters
22   -* image resizing
23   -* http downloads
24   -* updating smart collections
25   -* updating solr, our search server, after product changes
26   -* batch imports
27   -* spam checks
28   -
29   -[Follow us on Twitter][twitter] to get updates and notices about new releases.
30   -
31   -[twitter]: https://twitter.com/delayedjob
32   -
33   -Installation
34   -============
35   -delayed_job 3.0.0 only supports Rails 3.0+. See the [2.0
36   -branch](https://github.com/collectiveidea/delayed_job/tree/v2.0) for Rails 2.
37   -
38   -delayed_job supports multiple backends for storing the job queue. [See the wiki
39   -for other backends](http://wiki.github.com/collectiveidea/delayed_job/backends).
40   -
41   -If you plan to use delayed_job with Active Record, add `delayed_job_active_record` to your `Gemfile`.
42   -
43   -```ruby
44   -gem 'delayed_job_active_record'
45   -```
46   -
47   -If you plan to use delayed_job with Mongoid, add `delayed_job_mongoid` to your `Gemfile`.
48   -
49   -```ruby
50   -gem 'delayed_job_mongoid'
51   -```
52   -
53   -Run `bundle install` to install the backend and delayed_job gems.
54   -
55   -The Active Record backend requires a jobs table. You can create that table by
56   -running the following command:
57   -
58   - rails generate delayed_job:active_record
59   - rake db:migrate
60   -
61   -Rails 4
62   -=======
63   -If you are using the protected_attributes gem, it must appear before delayed_job in your gemfile.
64   -
65   -Upgrading from 2.x to 3.0.0 on Active Record
66   -============================================
67   -Delayed Job 3.0.0 introduces a new column to the delayed_jobs table.
68   -
69   -If you're upgrading from Delayed Job 2.x, run the upgrade generator to create a migration to add the column.
70   -
71   - rails generate delayed_job:upgrade
72   - rake db:migrate
73   -
74   -Queuing Jobs
75   -============
76   -Call `.delay.method(params)` on any object and it will be processed in the background.
77   -
78   -```ruby
79   -# without delayed_job
80   -@user.activate!(@device)
81   -
82   -# with delayed_job
83   -@user.delay.activate!(@device)
84   -```
85   -
86   -If a method should always be run in the background, you can call
87   -`#handle_asynchronously` after the method declaration:
88   -
89   -```ruby
90   -class Device
91   - def deliver
92   - # long running method
93   - end
94   - handle_asynchronously :deliver
95   -end
96   -
97   -device = Device.new
98   -device.deliver
99   -```
100   -
101   -handle_asynchronously can take as options anything you can pass to delay. In
102   -addition, the values can be Proc objects allowing call time evaluation of the
103   -value. For some examples:
104   -
105   -```ruby
106   -class LongTasks
107   - def send_mailer
108   - # Some other code
109   - end
110   - handle_asynchronously :send_mailer, :priority => 20
111   -
112   - def in_the_future
113   - # Some other code
114   - end
115   - # 5.minutes.from_now will be evaluated when in_the_future is called
116   - handle_asynchronously :in_the_future, :run_at => Proc.new { 5.minutes.from_now }
117   -
118   - def self.when_to_run
119   - 2.hours.from_now
120   - end
121   -
122   - def call_a_class_method
123   - # Some other code
124   - end
125   - handle_asynchronously :call_a_class_method, :run_at => Proc.new { when_to_run }
126   -
127   - attr_reader :how_important
128   -
129   - def call_an_instance_method
130   - # Some other code
131   - end
132   - handle_asynchronously :call_an_instance_method, :priority => Proc.new {|i| i.how_important }
133   -end
134   -```
135   -
136   -If you ever want to call a `handle_asynchronously`'d method without Delayed Job, for instance while debugging something at the console, just add `_without_delay` to the method name. For instance, if your original method was `foo`, then call `foo_without_delay`.
137   -
138   -Rails 3 Mailers
139   -===============
140   -Due to how mailers are implemented in Rails 3, we had to do a little work around to get delayed_job to work.
141   -
142   -```ruby
143   -# without delayed_job
144   -Notifier.signup(@user).deliver
145   -
146   -# with delayed_job
147   -Notifier.delay.signup(@user)
148   -```
149   -
150   -Remove the `.deliver` method to make it work. It's not ideal, but it's the best
151   -we could do for now.
152   -
153   -Named Queues
154   -============
155   -DJ 3 introduces Resque-style named queues while still retaining DJ-style
156   -priority. The goal is to provide a system for grouping tasks to be worked by
157   -separate pools of workers, which may be scaled and controlled individually.
158   -
159   -Jobs can be assigned to a queue by setting the `queue` option:
160   -
161   -```ruby
162   -object.delay(:queue => 'tracking').method
163   -
164   -Delayed::Job.enqueue job, :queue => 'tracking'
165   -
166   -handle_asynchronously :tweet_later, :queue => 'tweets'
167   -```
168   -
169   -Running Jobs
170   -============
171   -`script/delayed_job` can be used to manage a background process which will
172   -start working off jobs.
173   -
174   -To do so, add `gem "daemons"` to your `Gemfile` and make sure you've run `rails
175   -generate delayed_job`.
176   -
177   -You can then do the following:
178   -
179   - RAILS_ENV=production script/delayed_job start
180   - RAILS_ENV=production script/delayed_job stop
181   -
182   - # Runs two workers in separate processes.
183   - RAILS_ENV=production script/delayed_job -n 2 start
184   - RAILS_ENV=production script/delayed_job stop
185   -
186   - # Set the --queue or --queues option to work from a particular queue.
187   - RAILS_ENV=production script/delayed_job --queue=tracking start
188   - RAILS_ENV=production script/delayed_job --queues=mailers,tasks start
189   -
190   - # Runs all available jobs and then exits
191   - RAILS_ENV=production script/delayed_job start --exit-on-complete
192   - # or to run in the foreground
193   - RAILS_ENV=production script/delayed_job run --exit-on-complete
194   -
195   -**Rails 4:** *replace script/delayed_job with bin/delayed_job*
196   -
197   -Workers can be running on any computer, as long as they have access to the
198   -database and their clock is in sync. Keep in mind that each worker will check
199   -the database at least every 5 seconds.
200   -
201   -You can also invoke `rake jobs:work` which will start working off jobs. You can
202   -cancel the rake task with `CTRL-C`.
203   -
204   -If you want to just run all available jobs and exit you can use `rake jobs:workoff`
205   -
206   -Work off queues by setting the `QUEUE` or `QUEUES` environment variable.
207   -
208   - QUEUE=tracking rake jobs:work
209   - QUEUES=mailers,tasks rake jobs:work
210   -
211   -Restarting delayed_job
212   -======================
213   -
214   -The following syntax will restart delayed jobs:
215   -
216   - RAILS_ENV=production script/delayed_job restart
217   -
218   -To restart multiple delayed_job workers:
219   -
220   - RAILS_ENV=production script/delayed_job -n2 restart
221   -
222   -**Rails 4:** *replace script/delayed_job with bin/delayed_job*
223   -
224   -
225   -
226   -Custom Jobs
227   -===========
228   -Jobs are simple ruby objects with a method called perform. Any object which responds to perform can be stuffed into the jobs table. Job objects are serialized to yaml so that they can later be resurrected by the job runner.
229   -
230   -```ruby
231   -class NewsletterJob < Struct.new(:text, :emails)
232   - def perform
233   - emails.each { |e| NewsletterMailer.deliver_text_to_email(text, e) }
234   - end
235   -end
236   -
237   -Delayed::Job.enqueue NewsletterJob.new('lorem ipsum...', Customers.find(:all).collect(&:email))
238   -```
239   -To set a per-job max attempts that overrides the Delayed::Worker.max_attempts you can define a max_attempts method on the job
240   -```ruby
241   -class NewsletterJob < Struct.new(:text, :emails)
242   - def perform
243   - emails.each { |e| NewsletterMailer.deliver_text_to_email(text, e) }
244   - end
245   -
246   - def max_attempts
247   - return 3
248   - end
249   -end
250   -````
251   -
252   -
253   -Hooks
254   -=====
255   -You can define hooks on your job that will be called at different stages in the process:
256   -
257   -```ruby
258   -class ParanoidNewsletterJob < NewsletterJob
259   - def enqueue(job)
260   - record_stat 'newsletter_job/enqueue'
261   - end
262   -
263   - def perform
264   - emails.each { |e| NewsletterMailer.deliver_text_to_email(text, e) }
265   - end
266   -
267   - def before(job)
268   - record_stat 'newsletter_job/start'
269   - end
270   -
271   - def after(job)
272   - record_stat 'newsletter_job/after'
273   - end
274   -
275   - def success(job)
276   - record_stat 'newsletter_job/success'
277   - end
278   -
279   - def error(job, exception)
280   - Airbrake.notify(exception)
281   - end
282   -
283   - def failure(job)
284   - page_sysadmin_in_the_middle_of_the_night
285   - end
286   -end
287   -```
288   -
289   -Gory Details
290   -============
291   -The library revolves around a delayed_jobs table which looks as follows:
292   -
293   -```ruby
294   -create_table :delayed_jobs, :force => true do |table|
295   - table.integer :priority, :default => 0 # Allows some jobs to jump to the front of the queue
296   - table.integer :attempts, :default => 0 # Provides for retries, but still fail eventually.
297   - table.text :handler # YAML-encoded string of the object that will do work
298   - table.text :last_error # reason for last failure (See Note below)
299   - table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future.
300   - table.datetime :locked_at # Set when a client is working on this object
301   - table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
302   - table.string :locked_by # Who is working on this object (if locked)
303   - table.string :queue # The name of the queue this job is in
304   - table.timestamps
305   -end
306   -```
307   -
308   -On failure, the job is scheduled again in 5 seconds + N ** 4, where N is the number of retries.
309   -
310   -The default Worker.max_attempts is 25. After this, the job either deleted (default), or left in the database with "failed_at" set.
311   -With the default of 25 attempts, the last retry will be 20 days later, with the last interval being almost 100 hours.
312   -
313   -The default Worker.max_run_time is 4.hours. If your job takes longer than that, another computer could pick it up. It's up to you to
314   -make sure your job doesn't exceed this time. You should set this to the longest time you think the job could take.
315   -
316   -By default, it will delete failed jobs (and it always deletes successful jobs). If you want to keep failed jobs, set
317   -Delayed::Worker.destroy_failed_jobs = false. The failed jobs will be marked with non-null failed_at.
318   -
319   -By default all jobs are scheduled with priority = 0, which is top priority. You can change this by setting Delayed::Worker.default_priority to something else. Lower numbers have higher priority.
320   -
321   -The default behavior is to read 5 jobs from the queue when finding an available job. You can configure this by setting Delayed::Worker.read_ahead.
322   -
323   -By default all jobs will be queued without a named queue. A default named queue can be specified by using Delayed::Worker.default_queue_name.
324   -
325   -It is possible to disable delayed jobs for testing purposes. Set Delayed::Worker.delay_jobs = false to execute all jobs realtime.
326   -
327   -Here is an example of changing job parameters in Rails:
328   -
329   -```ruby
330   -# config/initializers/delayed_job_config.rb
331   -Delayed::Worker.destroy_failed_jobs = false
332   -Delayed::Worker.sleep_delay = 60
333   -Delayed::Worker.max_attempts = 3
334   -Delayed::Worker.max_run_time = 5.minutes
335   -Delayed::Worker.read_ahead = 10
336   -Delayed::Worker.default_queue_name = 'default'
337   -Delayed::Worker.delay_jobs = !Rails.env.test?
338   -```
339   -
340   -Cleaning up
341   -===========
342   -You can invoke `rake jobs:clear` to delete all jobs in the queue.
343   -
344   -Mailing List
345   -============
346   -Join us on the [mailing list](http://groups.google.com/group/delayed_job)
vendor/plugins/delayed_job/Rakefile
... ... @@ -1,11 +0,0 @@
1   -# -*- encoding: utf-8 -*-
2   -require 'bundler/setup'
3   -Bundler::GemHelper.install_tasks
4   -
5   -require 'rspec/core/rake_task'
6   -desc 'Run the specs'
7   -RSpec::Core::RakeTask.new do |r|
8   - r.verbose = false
9   -end
10   -
11   -task :default => :spec
vendor/plugins/delayed_job/benchmarks.rb
... ... @@ -1,13 +0,0 @@
1   -require 'spec/helper'
2   -require 'logger'
3   -require 'benchmark'
4   -
5   -# Delayed::Worker.logger = Logger.new('/dev/null')
6   -
7   -Benchmark.bm(10) do |x|
8   - Delayed::Job.delete_all
9   - n = 10000
10   - n.times { "foo".delay.length }
11   -
12   - x.report { Delayed::Worker.new(:quiet => true).work_off(n) }
13   -end
vendor/plugins/delayed_job/contrib/delayed_job.monitrc
... ... @@ -1,14 +0,0 @@
1   -# an example Monit configuration file for delayed_job
2   -# See: http://stackoverflow.com/questions/1226302/how-to-monitor-delayedjob-with-monit/1285611
3   -#
4   -# To use:
5   -# 1. copy to /var/www/apps/{app_name}/shared/delayed_job.monitrc
6   -# 2. replace {app_name} as appropriate
7   -# 3. add this to your /etc/monit/monitrc
8   -#
9   -# include /var/www/apps/{app_name}/shared/delayed_job.monitrc
10   -
11   -check process delayed_job
12   - with pidfile /var/www/apps/{app_name}/shared/pids/delayed_job.pid
13   - start program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/script/delayed_job start"
14   - stop program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/script/delayed_job stop"
vendor/plugins/delayed_job/contrib/delayed_job_multiple.monitrc
... ... @@ -1,34 +0,0 @@
1   -# an example Monit configuration file for delayed_job running multiple processes
2   -#
3   -# To use:
4   -# 1. copy to /var/www/apps/{app_name}/shared/delayed_job.monitrc
5   -# 2. replace {app_name} as appropriate
6   -# you might also need to change the program strings to
7   -# "/bin/su - {username} -c '/usr/bin/env ...'"
8   -# to load your shell environment.
9   -#
10   -# 3. add this to your /etc/monit/monitrc
11   -#
12   -# include /var/www/apps/{app_name}/shared/delayed_job.monitrc
13   -#
14   -# The processes are grouped so that monit can act on them as a whole, e.g.
15   -#
16   -# monit -g delayed_job restart
17   -
18   -check process delayed_job_0
19   - with pidfile /var/www/apps/{app_name}/shared/pids/delayed_job.0.pid
20   - start program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/script/delayed_job start -i 0"
21   - stop program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/script/delayed_job stop -i 0"
22   - group delayed_job
23   -
24   -check process delayed_job_1
25   - with pidfile /var/www/apps/{app_name}/shared/pids/delayed_job.1.pid
26   - start program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/script/delayed_job start -i 1"
27   - stop program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/script/delayed_job stop -i 1"
28   - group delayed_job
29   -
30   -check process delayed_job_2
31   - with pidfile /var/www/apps/{app_name}/shared/pids/delayed_job.2.pid
32   - start program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/script/delayed_job start -i 2"
33   - stop program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/script/delayed_job stop -i 2"
34   - group delayed_job
vendor/plugins/delayed_job/contrib/delayed_job_rails_4.monitrc
... ... @@ -1,14 +0,0 @@
1   -# an example Monit configuration file for delayed_job
2   -# See: http://stackoverflow.com/questions/1226302/how-to-monitor-delayedjob-with-monit/1285611
3   -#
4   -# To use:
5   -# 1. copy to /var/www/apps/{app_name}/shared/delayed_job.monitrc
6   -# 2. replace {app_name} as appropriate
7   -# 3. add this to your /etc/monit/monitrc
8   -#
9   -# include /var/www/apps/{app_name}/shared/delayed_job.monitrc
10   -
11   -check process delayed_job
12   - with pidfile /var/www/apps/{app_name}/shared/pids/delayed_job.pid
13   - start program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/bin/delayed_job start"
14   - stop program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/bin/delayed_job stop"
vendor/plugins/delayed_job/contrib/delayed_job_rails_4_multiple.monitrc
... ... @@ -1,34 +0,0 @@
1   -# an example Monit configuration file for delayed_job running multiple processes
2   -#
3   -# To use:
4   -# 1. copy to /var/www/apps/{app_name}/shared/delayed_job.monitrc
5   -# 2. replace {app_name} as appropriate
6   -# you might also need to change the program strings to
7   -# "/bin/su - {username} -c '/usr/bin/env ...'"
8   -# to load your shell environment.
9   -#
10   -# 3. add this to your /etc/monit/monitrc
11   -#
12   -# include /var/www/apps/{app_name}/shared/delayed_job.monitrc
13   -#
14   -# The processes are grouped so that monit can act on them as a whole, e.g.
15   -#
16   -# monit -g delayed_job restart
17   -
18   -check process delayed_job_0
19   - with pidfile /var/www/apps/{app_name}/shared/pids/delayed_job.0.pid
20   - start program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/bin/delayed_job start -i 0"
21   - stop program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/bin/delayed_job stop -i 0"
22   - group delayed_job
23   -
24   -check process delayed_job_1
25   - with pidfile /var/www/apps/{app_name}/shared/pids/delayed_job.1.pid
26   - start program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/bin/delayed_job start -i 1"
27   - stop program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/bin/delayed_job stop -i 1"
28   - group delayed_job
29   -
30   -check process delayed_job_2
31   - with pidfile /var/www/apps/{app_name}/shared/pids/delayed_job.2.pid
32   - start program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/bin/delayed_job start -i 2"
33   - stop program = "/usr/bin/env RAILS_ENV=production /var/www/apps/{app_name}/current/bin/delayed_job stop -i 2"
34   - group delayed_job
vendor/plugins/delayed_job/delayed_job.gemspec
... ... @@ -1,17 +0,0 @@
1   -# -*- encoding: utf-8 -*-
2   -
3   -Gem::Specification.new do |spec|
4   - spec.add_dependency 'activesupport', ['>= 3.0', '< 4.1']
5   - spec.authors = ["Brandon Keepers", "Brian Ryckbost", "Chris Gaffney", "David Genord II", "Erik Michaels-Ober", "Matt Griffin", "Steve Richert", "Tobias Lütke"]
6   - spec.description = "Delayed_job (or DJ) encapsulates the common pattern of asynchronously executing longer tasks in the background. It is a direct extraction from Shopify where the job table is responsible for a multitude of core tasks."
7   - spec.email = ['brian@collectiveidea.com']
8   - spec.files = %w(CHANGELOG.md CONTRIBUTING.md LICENSE.md README.md Rakefile delayed_job.gemspec)
9   - spec.files += Dir.glob('{contrib,lib,recipes,spec}/**/*')
10   - spec.homepage = 'http://github.com/collectiveidea/delayed_job'
11   - spec.licenses = ['MIT']
12   - spec.name = 'delayed_job'
13   - spec.require_paths = ['lib']
14   - spec.summary = 'Database-backed asynchronous priority queue system -- Extracted from Shopify'
15   - spec.test_files = Dir.glob('spec/**/*')
16   - spec.version = '4.0.0'
17   -end
vendor/plugins/delayed_job/lib/delayed/backend/base.rb
... ... @@ -1,156 +0,0 @@
1   -module Delayed
2   - module Backend
3   - module Base
4   - def self.included(base)
5   - base.extend ClassMethods
6   - end
7   -
8   - module ClassMethods
9   - # Add a job to the queue
10   - def enqueue(*args)
11   - options = {
12   - :priority => Delayed::Worker.default_priority,
13   - :queue => Delayed::Worker.default_queue_name
14   - }.merge!(args.extract_options!)
15   -
16   - options[:payload_object] ||= args.shift
17   -
18   - if args.size > 0
19   - warn "[DEPRECATION] Passing multiple arguments to `#enqueue` is deprecated. Pass a hash with :priority and :run_at."
20   - options[:priority] = args.first || options[:priority]
21   - options[:run_at] = args[1]
22   - end
23   -
24   - unless options[:payload_object].respond_to?(:perform)
25   - raise ArgumentError, 'Cannot enqueue items which do not respond to perform'
26   - end
27   -
28   - if Delayed::Worker.delay_jobs
29   - self.new(options).tap do |job|
30   - Delayed::Worker.lifecycle.run_callbacks(:enqueue, job) do
31   - job.hook(:enqueue)
32   - job.save
33   - end
34   - end
35   - else
36   - Delayed::Job.new(:payload_object => options[:payload_object]).tap do |job|
37   - job.invoke_job
38   - end
39   - end
40   - end
41   -
42   - def reserve(worker, max_run_time = Worker.max_run_time)
43   - # We get up to 5 jobs from the db. In case we cannot get exclusive access to a job we try the next.
44   - # this leads to a more even distribution of jobs across the worker processes
45   - find_available(worker.name, worker.read_ahead, max_run_time).detect do |job|
46   - job.lock_exclusively!(max_run_time, worker.name)
47   - end
48   - end
49   -
50   - # Allow the backend to attempt recovery from reserve errors
51   - def recover_from(error)
52   - end
53   -
54   - # Hook method that is called before a new worker is forked
55   - def before_fork
56   - end
57   -
58   - # Hook method that is called after a new worker is forked
59   - def after_fork
60   - end
61   -
62   - def work_off(num = 100)
63   - warn "[DEPRECATION] `Delayed::Job.work_off` is deprecated. Use `Delayed::Worker.new.work_off instead."
64   - Delayed::Worker.new.work_off(num)
65   - end
66   - end
67   -
68   - def failed?
69   - !!failed_at
70   - end
71   - alias_method :failed, :failed?
72   -
73   - ParseObjectFromYaml = /\!ruby\/\w+\:([^\s]+)/
74   -
75   - def name
76   - obj = payload_object
77   - @name ||= obj.respond_to?(:display_name) ? obj.display_name : obj.class.name
78   - rescue DeserializationError
79   - ParseObjectFromYaml.match(handler)[1]
80   - end
81   -
82   - def payload_object=(object)
83   - @payload_object = object
84   - self.handler = object.to_yaml
85   - end
86   -
87   - def payload_object
88   - if YAML.respond_to?(:unsafe_load)
89   - #See https://github.com/dtao/safe_yaml
90   - #When the method is there, we need to load our YAML like this...
91   - @payload_object ||= YAML.load(self.handler, :safe => false)
92   - else
93   - @payload_object ||= YAML.load(self.handler)
94   - end
95   - rescue TypeError, LoadError, NameError, ArgumentError => e
96   - raise DeserializationError,
97   - "Job failed to load: #{e.message}. Handler: #{handler.inspect}"
98   - end
99   -
100   - def invoke_job
101   - Delayed::Worker.lifecycle.run_callbacks(:invoke_job, self) do
102   - begin
103   - hook :before
104   - payload_object.perform
105   - hook :success
106   - rescue Exception => e
107   - hook :error, e
108   - raise e
109   - ensure
110   - hook :after
111   - end
112   - end
113   - end
114   -
115   - # Unlock this job (note: not saved to DB)
116   - def unlock
117   - self.locked_at = nil
118   - self.locked_by = nil
119   - end
120   -
121   - def hook(name, *args)
122   - if payload_object.respond_to?(name)
123   - method = payload_object.method(name)
124   - method.arity == 0 ? method.call : method.call(self, *args)
125   - end
126   - rescue DeserializationError
127   - # do nothing
128   - end
129   -
130   - def reschedule_at
131   - payload_object.respond_to?(:reschedule_at) ?
132   - payload_object.reschedule_at(self.class.db_time_now, attempts) :
133   - self.class.db_time_now + (attempts ** 4) + 5
134   - end
135   -
136   - def max_attempts
137   - payload_object.max_attempts if payload_object.respond_to?(:max_attempts)
138   - end
139   -
140   - def fail!
141   - update_attributes(:failed_at => self.class.db_time_now)
142   - end
143   -
144   - protected
145   -
146   - def set_default_run_at
147   - self.run_at ||= self.class.db_time_now
148   - end
149   -
150   - # Call during reload operation to clear out internal state
151   - def reset
152   - @payload_object = nil
153   - end
154   - end
155   - end
156   -end
vendor/plugins/delayed_job/lib/delayed/backend/shared_spec.rb
... ... @@ -1,594 +0,0 @@
1   -require File.expand_path('../../../../spec/sample_jobs', __FILE__)
2   -
3   -require 'active_support/core_ext'
4   -
5   -shared_examples_for "a delayed_job backend" do
6   - let(:worker) { Delayed::Worker.new }
7   -
8   - def create_job(opts = {})
9   - described_class.create(opts.merge(:payload_object => SimpleJob.new))
10   - end
11   -
12   - before do
13   - Delayed::Worker.max_priority = nil
14   - Delayed::Worker.min_priority = nil
15   - Delayed::Worker.default_priority = 99
16   - Delayed::Worker.delay_jobs = true
17   - SimpleJob.runs = 0
18   - described_class.delete_all
19   - end
20   -
21   - after do
22   - Delayed::Worker.reset
23   - end
24   -
25   - it "sets run_at automatically if not set" do
26   - expect(described_class.create(:payload_object => ErrorJob.new ).run_at).not_to be_nil
27   - end
28   -
29   - it "does not set run_at automatically if already set" do
30   - later = described_class.db_time_now + 5.minutes
31   - job = described_class.create(:payload_object => ErrorJob.new, :run_at => later)
32   - expect(job.run_at).to be_within(1).of(later)
33   - end
34   -
35   - describe "#reload" do
36   - it "reloads the payload" do
37   - job = described_class.enqueue :payload_object => SimpleJob.new
38   - expect(job.payload_object.object_id).not_to eq(job.reload.payload_object.object_id)
39   - end
40   - end
41   -
42   - describe "enqueue" do
43   - context "with a hash" do
44   - it "raises ArgumentError when handler doesn't respond_to :perform" do
45   - expect{described_class.enqueue(:payload_object => Object.new)}.to raise_error(ArgumentError)
46   - end
47   -
48   - it "is able to set priority" do
49   - job = described_class.enqueue :payload_object => SimpleJob.new, :priority => 5
50   - expect(job.priority).to eq(5)
51   - end
52   -
53   - it "uses default priority" do
54   - job = described_class.enqueue :payload_object => SimpleJob.new
55   - expect(job.priority).to eq(99)
56   - end
57   -
58   - it "is able to set run_at" do
59   - later = described_class.db_time_now + 5.minutes
60   - job = described_class.enqueue :payload_object => SimpleJob.new, :run_at => later
61   - expect(job.run_at).to be_within(1).of(later)
62   - end
63   -
64   - it "is able to set queue" do
65   - job = described_class.enqueue :payload_object => SimpleJob.new, :queue => 'tracking'
66   - expect(job.queue).to eq('tracking')
67   - end
68   - end
69   -
70   - context "with multiple arguments" do
71   - it "raises ArgumentError when handler doesn't respond_to :perform" do
72   - expect{described_class.enqueue(Object.new)}.to raise_error(ArgumentError)
73   - end
74   -
75   - it "increases count after enqueuing items" do
76   - described_class.enqueue SimpleJob.new
77   - expect(described_class.count).to eq(1)
78   - end
79   -
80   - it "is able to set priority [DEPRECATED]" do
81   - silence_warnings do
82   - job = described_class.enqueue SimpleJob.new, 5
83   - expect(job.priority).to eq(5)
84   - end
85   - end
86   -
87   - it "uses default priority when it is not set" do
88   - @job = described_class.enqueue SimpleJob.new
89   - expect(@job.priority).to eq(99)
90   - end
91   -
92   - it "is able to set run_at [DEPRECATED]" do
93   - silence_warnings do
94   - later = described_class.db_time_now + 5.minutes
95   - @job = described_class.enqueue SimpleJob.new, 5, later
96   - expect(@job.run_at).to be_within(1).of(later)
97   - end
98   - end
99   -
100   - it "works with jobs in modules" do
101   - M::ModuleJob.runs = 0
102   - job = described_class.enqueue M::ModuleJob.new
103   - expect{job.invoke_job}.to change { M::ModuleJob.runs }.from(0).to(1)
104   - end
105   - end
106   -
107   - context "with delay_jobs = false" do
108   - before(:each) do
109   - Delayed::Worker.delay_jobs = false
110   - end
111   -
112   - it "does not increase count after enqueuing items" do
113   - described_class.enqueue SimpleJob.new
114   - expect(described_class.count).to eq(0)
115   - end
116   -
117   - it "invokes the enqueued job" do
118   - job = SimpleJob.new
119   - job.should_receive(:perform)
120   - described_class.enqueue job
121   - end
122   -
123   - it "returns a job, not the result of invocation" do
124   - expect(described_class.enqueue(SimpleJob.new)).to be_instance_of(described_class)
125   - end
126   - end
127   - end
128   -
129   - describe "callbacks" do
130   - before(:each) do
131   - CallbackJob.messages = []
132   - end
133   -
134   - %w(before success after).each do |callback|
135   - it "calls #{callback} with job" do
136   - job = described_class.enqueue(CallbackJob.new)
137   - job.payload_object.should_receive(callback).with(job)
138   - job.invoke_job
139   - end
140   - end
141   -
142   - it "calls before and after callbacks" do
143   - job = described_class.enqueue(CallbackJob.new)
144   - expect(CallbackJob.messages).to eq(["enqueue"])
145   - job.invoke_job
146   - expect(CallbackJob.messages).to eq(["enqueue", "before", "perform", "success", "after"])
147   - end
148   -
149   - it "calls the after callback with an error" do
150   - job = described_class.enqueue(CallbackJob.new)
151   - job.payload_object.should_receive(:perform).and_raise(RuntimeError.new("fail"))
152   -
153   - expect{job.invoke_job}.to raise_error
154   - expect(CallbackJob.messages).to eq(["enqueue", "before", "error: RuntimeError", "after"])
155   - end
156   -
157   - it "calls error when before raises an error" do
158   - job = described_class.enqueue(CallbackJob.new)
159   - job.payload_object.should_receive(:before).and_raise(RuntimeError.new("fail"))
160   - expect{job.invoke_job}.to raise_error(RuntimeError)
161   - expect(CallbackJob.messages).to eq(["enqueue", "error: RuntimeError", "after"])
162   - end
163   - end
164   -
165   - describe "payload_object" do
166   - it "raises a DeserializationError when the job class is totally unknown" do
167   - job = described_class.new :handler => "--- !ruby/object:JobThatDoesNotExist {}"
168   - expect{job.payload_object}.to raise_error(Delayed::DeserializationError)
169   - end
170   -
171   - it "raises a DeserializationError when the job struct is totally unknown" do
172   - job = described_class.new :handler => "--- !ruby/struct:StructThatDoesNotExist {}"
173   - expect{job.payload_object}.to raise_error(Delayed::DeserializationError)
174   - end
175   -
176   - it "raises a DeserializationError when the YAML.load raises argument error" do
177   - job = described_class.new :handler => "--- !ruby/struct:GoingToRaiseArgError {}"
178   - YAML.should_receive(:load).and_raise(ArgumentError)
179   - expect{job.payload_object}.to raise_error(Delayed::DeserializationError)
180   - end
181   - end
182   -
183   - describe "reserve" do
184   - before do
185   - Delayed::Worker.max_run_time = 2.minutes
186   - end
187   -
188   - after do
189   - Time.zone = nil
190   - end
191   -
192   - it "does not reserve failed jobs" do
193   - create_job :attempts => 50, :failed_at => described_class.db_time_now
194   - expect(described_class.reserve(worker)).to be_nil
195   - end
196   -
197   - it "does not reserve jobs scheduled for the future" do
198   - create_job :run_at => described_class.db_time_now + 1.minute
199   - expect(described_class.reserve(worker)).to be_nil
200   - end
201   -
202   - it "reserves jobs scheduled for the past" do
203   - job = create_job :run_at => described_class.db_time_now - 1.minute
204   - expect(described_class.reserve(worker)).to eq(job)
205   - end
206   -
207   - it "reserves jobs scheduled for the past when time zones are involved" do
208   - Time.zone = 'US/Eastern'
209   - job = create_job :run_at => described_class.db_time_now - 1.minute
210   - expect(described_class.reserve(worker)).to eq(job)
211   - end
212   -
213   - it "does not reserve jobs locked by other workers" do
214   - job = create_job
215   - other_worker = Delayed::Worker.new
216   - other_worker.name = 'other_worker'
217   - expect(described_class.reserve(other_worker)).to eq(job)
218   - expect(described_class.reserve(worker)).to be_nil
219   - end
220   -
221   - it "reserves open jobs" do
222   - job = create_job
223   - expect(described_class.reserve(worker)).to eq(job)
224   - end
225   -
226   - it "reserves expired jobs" do
227   - job = create_job(:locked_by => 'some other worker', :locked_at => described_class.db_time_now - Delayed::Worker.max_run_time - 1.minute)
228   - expect(described_class.reserve(worker)).to eq(job)
229   - end
230   -
231   - it "reserves own jobs" do
232   - job = create_job(:locked_by => worker.name, :locked_at => (described_class.db_time_now - 1.minutes))
233   - expect(described_class.reserve(worker)).to eq(job)
234   - end
235   - end
236   -
237   - context "#name" do
238   - it "is the class name of the job that was enqueued" do
239   - expect(described_class.create(:payload_object => ErrorJob.new ).name).to eq('ErrorJob')
240   - end
241   -
242   - it "is the method that will be called if its a performable method object" do
243   - job = described_class.new(:payload_object => NamedJob.new)
244   - expect(job.name).to eq('named_job')
245   - end
246   -
247   - it "is the instance method that will be called if its a performable method object" do
248   - job = Story.create(:text => "...").delay.save
249   - expect(job.name).to eq('Story#save')
250   - end
251   -
252   - it "parses from handler on deserialization error" do
253   - job = Story.create(:text => "...").delay.text
254   - job.payload_object.object.destroy
255   - expect(job.reload.name).to eq('Delayed::PerformableMethod')
256   - end
257   - end
258   -
259   - context "worker prioritization" do
260   - after do
261   - Delayed::Worker.max_priority = nil
262   - Delayed::Worker.min_priority = nil
263   - end
264   -
265   - it "fetches jobs ordered by priority" do
266   - 10.times { described_class.enqueue SimpleJob.new, :priority => rand(10) }
267   - jobs = []
268   - 10.times { jobs << described_class.reserve(worker) }
269   - expect(jobs.size).to eq(10)
270   - jobs.each_cons(2) do |a, b|
271   - expect(a.priority).to be <= b.priority
272   - end
273   - end
274   -
275   - it "only finds jobs greater than or equal to min priority" do
276   - min = 5
277   - Delayed::Worker.min_priority = min
278   - [4,5,6].sort_by {|i| rand }.each {|i| create_job :priority => i }
279   - 2.times do
280   - job = described_class.reserve(worker)
281   - expect(job.priority).to be >= min
282   - job.destroy
283   - end
284   - expect(described_class.reserve(worker)).to be_nil
285   - end
286   -
287   - it "only finds jobs less than or equal to max priority" do
288   - max = 5
289   - Delayed::Worker.max_priority = max
290   - [4,5,6].sort_by {|i| rand }.each {|i| create_job :priority => i }
291   - 2.times do
292   - job = described_class.reserve(worker)
293   - expect(job.priority).to be <= max
294   - job.destroy
295   - end
296   - expect(described_class.reserve(worker)).to be_nil
297   - end
298   - end
299   -
300   - context "clear_locks!" do
301   - before do
302   - @job = create_job(:locked_by => 'worker1', :locked_at => described_class.db_time_now)
303   - end
304   -
305   - it "clears locks for the given worker" do
306   - described_class.clear_locks!('worker1')
307   - expect(described_class.reserve(worker)).to eq(@job)
308   - end
309   -
310   - it "does not clear locks for other workers" do
311   - described_class.clear_locks!('different_worker')
312   - expect(described_class.reserve(worker)).not_to eq(@job)
313   - end
314   - end
315   -
316   - context "unlock" do
317   - before do
318   - @job = create_job(:locked_by => 'worker', :locked_at => described_class.db_time_now)
319   - end
320   -
321   - it "clears locks" do
322   - @job.unlock
323   - expect(@job.locked_by).to be_nil
324   - expect(@job.locked_at).to be_nil
325   - end
326   - end
327   -
328   - context "large handler" do
329   - before do
330   - text = "Lorem ipsum dolor sit amet. " * 1000
331   - @job = described_class.enqueue Delayed::PerformableMethod.new(text, :length, {})
332   - end
333   -
334   - it "has an id" do
335   - expect(@job.id).not_to be_nil
336   - end
337   - end
338   -
339   - context "named queues" do
340   - context "when worker has one queue set" do
341   - before(:each) do
342   - worker.queues = ['large']
343   - end
344   -
345   - it "only works off jobs which are from its queue" do
346   - expect(SimpleJob.runs).to eq(0)
347   -
348   - create_job(:queue => "large")
349   - create_job(:queue => "small")
350   - worker.work_off
351   -
352   - expect(SimpleJob.runs).to eq(1)
353   - end
354   - end
355   -
356   - context "when worker has two queue set" do
357   - before(:each) do
358   - worker.queues = ['large', 'small']
359   - end
360   -
361   - it "only works off jobs which are from its queue" do
362   - expect(SimpleJob.runs).to eq(0)
363   -
364   - create_job(:queue => "large")
365   - create_job(:queue => "small")
366   - create_job(:queue => "medium")
367   - create_job
368   - worker.work_off
369   -
370   - expect(SimpleJob.runs).to eq(2)
371   - end
372   - end
373   -
374   - context "when worker does not have queue set" do
375   - before(:each) do
376   - worker.queues = []
377   - end
378   -
379   - it "works off all jobs" do
380   - expect(SimpleJob.runs).to eq(0)
381   -
382   - create_job(:queue => "one")
383   - create_job(:queue => "two")
384   - create_job
385   - worker.work_off
386   -
387   - expect(SimpleJob.runs).to eq(3)
388   - end
389   - end
390   - end
391   -
392   - context "max_attempts" do
393   - before(:each) do
394   - @job = described_class.enqueue SimpleJob.new
395   - end
396   -
397   - it "is not defined" do
398   - expect(@job.max_attempts).to be_nil
399   - end
400   -
401   - it "uses the max_retries value on the payload when defined" do
402   - @job.payload_object.stub(:max_attempts).and_return(99)
403   - expect(@job.max_attempts).to eq(99)
404   - end
405   - end
406   -
407   - describe "yaml serialization" do
408   - it "reloads changed attributes" do
409   - story = Story.create(:text => 'hello')
410   - job = story.delay.tell
411   - story.update_attributes :text => 'goodbye'
412   - expect(job.reload.payload_object.object.text).to eq('goodbye')
413   - end
414   -
415   - it "raises error ArgumentError the record is not persisted" do
416   - story = Story.new(:text => 'hello')
417   - if story.respond_to?(:new_record?)
418   - expect {
419   - story.delay.tell
420   - }.to raise_error(ArgumentError, "Jobs cannot be created for records before they've been persisted")
421   - end
422   - end
423   -
424   - it "raises deserialization error for destroyed records" do
425   - story = Story.create(:text => 'hello')
426   - job = story.delay.tell
427   - story.destroy
428   - expect {
429   - job.reload.payload_object
430   - }.to raise_error(Delayed::DeserializationError)
431   - end
432   - end
433   -
434   - describe "worker integration" do
435   - before do
436   - Delayed::Job.delete_all
437   - SimpleJob.runs = 0
438   - end
439   -
440   - describe "running a job" do
441   - it "fails after Worker.max_run_time" do
442   - Delayed::Worker.max_run_time = 1.second
443   - job = Delayed::Job.create :payload_object => LongRunningJob.new
444   - worker.run(job)
445   - expect(job.reload.last_error).to match(/expired/)
446   - expect(job.reload.last_error).to match(/Delayed::Worker.max_run_time is only 1 second/)
447   - expect(job.attempts).to eq(1)
448   - end
449   -
450   - context "when the job raises a deserialization error" do
451   - after do
452   - Delayed::Worker.destroy_failed_jobs = true
453   - end
454   -
455   - it "marks the job as failed" do
456   - Delayed::Worker.destroy_failed_jobs = false
457   - job = described_class.create! :handler => "--- !ruby/object:JobThatDoesNotExist {}"
458   - worker.work_off
459   - job.reload
460   - expect(job).to be_failed
461   - end
462   - end
463   - end
464   -
465   - describe "failed jobs" do
466   - before do
467   - @job = Delayed::Job.enqueue(ErrorJob.new, :run_at => described_class.db_time_now - 1)
468   - end
469   -
470   - after do
471   - # reset default
472   - Delayed::Worker.destroy_failed_jobs = true
473   - end
474   -
475   - it "records last_error when destroy_failed_jobs = false, max_attempts = 1" do
476   - Delayed::Worker.destroy_failed_jobs = false
477   - Delayed::Worker.max_attempts = 1
478   - worker.run(@job)
479   - @job.reload
480   - expect(@job.last_error).to match(/did not work/)
481   - expect(@job.attempts).to eq(1)
482   - expect(@job).to be_failed
483   - end
484   -
485   - it "re-schedules jobs after failing" do
486   - worker.work_off
487   - @job.reload
488   - expect(@job.last_error).to match(/did not work/)
489   - expect(@job.last_error).to match(/sample_jobs.rb:\d+:in `perform'/)
490   - expect(@job.attempts).to eq(1)
491   - expect(@job.run_at).to be > Delayed::Job.db_time_now - 10.minutes
492   - expect(@job.run_at).to be < Delayed::Job.db_time_now + 10.minutes
493   - expect(@job.locked_by).to be_nil
494   - expect(@job.locked_at).to be_nil
495   - end
496   -
497   - it "re-schedules jobs with handler provided time if present" do
498   - job = Delayed::Job.enqueue(CustomRescheduleJob.new(99.minutes))
499   - worker.run(job)
500   - job.reload
501   -
502   - expect((Delayed::Job.db_time_now + 99.minutes - job.run_at).abs).to be < 1
503   - end
504   -
505   - it "does not fail when the triggered error doesn't have a message" do
506   - error_with_nil_message = StandardError.new
507   - error_with_nil_message.stub(:message).and_return nil
508   - @job.stub(:invoke_job).and_raise error_with_nil_message
509   - expect{worker.run(@job)}.not_to raise_error
510   - end
511   - end
512   -
513   - context "reschedule" do
514   - before do
515   - @job = Delayed::Job.create :payload_object => SimpleJob.new
516   - end
517   -
518   - share_examples_for "any failure more than Worker.max_attempts times" do
519   - context "when the job's payload has a #failure hook" do
520   - before do
521   - @job = Delayed::Job.create :payload_object => OnPermanentFailureJob.new
522   - expect(@job.payload_object).to respond_to :failure
523   - end
524   -
525   - it "runs that hook" do
526   - @job.payload_object.should_receive :failure
527   - worker.reschedule(@job)
528   - end
529   - end
530   -
531   - context "when the job's payload has no #failure hook" do
532   - # It's a little tricky to test this in a straightforward way,
533   - # because putting a should_not_receive expectation on
534   - # @job.payload_object.failure makes that object
535   - # incorrectly return true to
536   - # payload_object.respond_to? :failure, which is what
537   - # reschedule uses to decide whether to call failure.
538   - # So instead, we just make sure that the payload_object as it
539   - # already stands doesn't respond_to? failure, then
540   - # shove it through the iterated reschedule loop and make sure we
541   - # don't get a NoMethodError (caused by calling that nonexistent
542   - # failure method).
543   -
544   - before do
545   - expect(@job.payload_object).not_to respond_to(:failure)
546   - end
547   -
548   - it "does not try to run that hook" do
549   - expect {
550   - Delayed::Worker.max_attempts.times { worker.reschedule(@job) }
551   - }.not_to raise_exception
552   - end
553   - end
554   - end
555   -
556   - context "and we want to destroy jobs" do
557   - it_should_behave_like "any failure more than Worker.max_attempts times"
558   -
559   - it "is destroyed if it failed more than Worker.max_attempts times" do
560   - @job.should_receive(:destroy)
561   - Delayed::Worker.max_attempts.times { worker.reschedule(@job) }
562   - end
563   -
564   - it "is not destroyed if failed fewer than Worker.max_attempts times" do
565   - @job.should_not_receive(:destroy)
566   - (Delayed::Worker.max_attempts - 1).times { worker.reschedule(@job) }
567   - end
568   - end
569   -
570   - context "and we don't want to destroy jobs" do
571   - before do
572   - Delayed::Worker.destroy_failed_jobs = false
573   - end
574   -
575   - after do
576   - Delayed::Worker.destroy_failed_jobs = true
577   - end
578   -
579   - it_should_behave_like "any failure more than Worker.max_attempts times"
580   -
581   - it "is failed if it failed more than Worker.max_attempts times" do
582   - expect(@job.reload).not_to be_failed
583   - Delayed::Worker.max_attempts.times { worker.reschedule(@job) }
584   - expect(@job.reload).to be_failed
585   - end
586   -
587   - it "is not failed if it failed fewer than Worker.max_attempts times" do
588   - (Delayed::Worker.max_attempts - 1).times { worker.reschedule(@job) }
589   - expect(@job.reload).not_to be_failed
590   - end
591   - end
592   - end
593   - end
594   -end
vendor/plugins/delayed_job/lib/delayed/command.rb
... ... @@ -1,111 +0,0 @@
1   -begin
2   - require 'daemons'
3   -rescue LoadError
4   - raise "You need to add gem 'daemons' to your Gemfile if you wish to use it."
5   -end
6   -require 'optparse'
7   -
8   -module Delayed
9   - class Command
10   - attr_accessor :worker_count
11   -
12   - def initialize(args)
13   - @options = {
14   - :quiet => true,
15   - :pid_dir => "#{Rails.root}/tmp/pids"
16   - }
17   -
18   - @worker_count = 1
19   - @monitor = false
20   -
21   - opts = OptionParser.new do |opts|
22   - opts.banner = "Usage: #{File.basename($0)} [options] start|stop|restart|run"
23   -
24   - opts.on('-h', '--help', 'Show this message') do
25   - puts opts
26   - exit 1
27   - end
28   - opts.on('-e', '--environment=NAME', 'Specifies the environment to run this delayed jobs under (test/development/production).') do |e|
29   - STDERR.puts "The -e/--environment option has been deprecated and has no effect. Use RAILS_ENV and see http://github.com/collectiveidea/delayed_job/issues/#issue/7"
30   - end
31   - opts.on('--min-priority N', 'Minimum priority of jobs to run.') do |n|
32   - @options[:min_priority] = n
33   - end
34   - opts.on('--max-priority N', 'Maximum priority of jobs to run.') do |n|
35   - @options[:max_priority] = n
36   - end
37   - opts.on('-n', '--number_of_workers=workers', "Number of unique workers to spawn") do |worker_count|
38   - @worker_count = worker_count.to_i rescue 1
39   - end
40   - opts.on('--pid-dir=DIR', 'Specifies an alternate directory in which to store the process ids.') do |dir|
41   - @options[:pid_dir] = dir
42   - end
43   - opts.on('-i', '--identifier=n', 'A numeric identifier for the worker.') do |n|
44   - @options[:identifier] = n
45   - end
46   - opts.on('-m', '--monitor', 'Start monitor process.') do
47   - @monitor = true
48   - end
49   - opts.on('--sleep-delay N', "Amount of time to sleep when no jobs are found") do |n|
50   - @options[:sleep_delay] = n.to_i
51   - end
52   - opts.on('--read-ahead N', "Number of jobs from the queue to consider") do |n|
53   - @options[:read_ahead] = n
54   - end
55   - opts.on('-p', '--prefix NAME', "String to be prefixed to worker process names") do |prefix|
56   - @options[:prefix] = prefix
57   - end
58   - opts.on('--queues=queues', "Specify which queue DJ must look up for jobs") do |queues|
59   - @options[:queues] = queues.split(',')
60   - end
61   - opts.on('--queue=queue', "Specify which queue DJ must look up for jobs") do |queue|
62   - @options[:queues] = queue.split(',')
63   - end
64   - opts.on('--exit-on-complete', "Exit when no more jobs are available to run. This will exit if all jobs are scheduled to run in the future.") do
65   - @options[:exit_on_complete] = true
66   - end
67   - end
68   - @args = opts.parse!(args)
69   - end
70   -
71   - def daemonize
72   - dir = @options[:pid_dir]
73   - Dir.mkdir(dir) unless File.exists?(dir)
74   -
75   - if @worker_count > 1 && @options[:identifier]
76   - raise ArgumentError, 'Cannot specify both --number-of-workers and --identifier'
77   - elsif @worker_count == 1 && @options[:identifier]
78   - process_name = "delayed_job.#{@options[:identifier]}"
79   - run_process(process_name, dir)
80   - else
81   - worker_count.times do |worker_index|
82   - process_name = worker_count == 1 ? "delayed_job" : "delayed_job.#{worker_index}"
83   - run_process(process_name, dir)
84   - end
85   - end
86   - end
87   -
88   - def run_process(process_name, dir)
89   - Delayed::Worker.before_fork
90   - Daemons.run_proc(process_name, :dir => dir, :dir_mode => :normal, :monitor => @monitor, :ARGV => @args) do |*args|
91   - $0 = File.join(@options[:prefix], process_name) if @options[:prefix]
92   - run process_name
93   - end
94   - end
95   -
96   - def run(worker_name = nil)
97   - Dir.chdir(Rails.root)
98   -
99   - Delayed::Worker.after_fork
100   - Delayed::Worker.logger = Logger.new(File.join(Rails.root, 'log', "#{Rails.env}_delayed_job.log"))
101   -
102   - worker = Delayed::Worker.new(@options)
103   - worker.name_prefix = "#{worker_name} "
104   - worker.start
105   - rescue => e
106   - Rails.logger.fatal e
107   - STDERR.puts e.message
108   - exit 1
109   - end
110   - end
111   -end
vendor/plugins/delayed_job/lib/delayed/compatibility.rb
... ... @@ -1,27 +0,0 @@
1   -require 'active_support/version'
2   -
3   -module Delayed
4   - module Compatibility
5   - if ActiveSupport::VERSION::MAJOR >= 4
6   - require 'active_support/proxy_object'
7   -
8   - def self.executable_prefix
9   - 'bin'
10   - end
11   -
12   - def self.proxy_object_class
13   - ActiveSupport::ProxyObject
14   - end
15   - else
16   - require 'active_support/basic_object'
17   -
18   - def self.executable_prefix
19   - 'script'
20   - end
21   -
22   - def self.proxy_object_class
23   - ActiveSupport::BasicObject
24   - end
25   - end
26   - end
27   -end
vendor/plugins/delayed_job/lib/delayed/deserialization_error.rb
... ... @@ -1,4 +0,0 @@
1   -module Delayed
2   - class DeserializationError < StandardError
3   - end
4   -end
vendor/plugins/delayed_job/lib/delayed/exceptions.rb
... ... @@ -1,9 +0,0 @@
1   -require 'timeout'
2   -
3   -module Delayed
4   - class WorkerTimeout < Timeout::Error
5   - def message
6   - "#{super} (Delayed::Worker.max_run_time is only #{Delayed::Worker.max_run_time.to_i} seconds)"
7   - end
8   - end
9   -end
vendor/plugins/delayed_job/lib/delayed/lifecycle.rb
... ... @@ -1,84 +0,0 @@
1   -module Delayed
2   - class InvalidCallback < Exception; end
3   -
4   - class Lifecycle
5   - EVENTS = {
6   - :enqueue => [:job],
7   - :execute => [:worker],
8   - :loop => [:worker],
9   - :perform => [:worker, :job],
10   - :error => [:worker, :job],
11   - :failure => [:worker, :job],
12   - :invoke_job => [:job]
13   - }
14   -
15   - def initialize
16   - @callbacks = EVENTS.keys.inject({}) { |hash, e| hash[e] = Callback.new; hash }
17   - end
18   -
19   - def before(event, &block)
20   - add(:before, event, &block)
21   - end
22   -
23   - def after(event, &block)
24   - add(:after, event, &block)
25   - end
26   -
27   - def around(event, &block)
28   - add(:around, event, &block)
29   - end
30   -
31   - def run_callbacks(event, *args, &block)
32   - missing_callback(event) unless @callbacks.has_key?(event)
33   -
34   - unless EVENTS[event].size == args.size
35   - raise ArgumentError, "Callback #{event} expects #{EVENTS[event].size} parameter(s): #{EVENTS[event].join(', ')}"
36   - end
37   -
38   - @callbacks[event].execute(*args, &block)
39   - end
40   -
41   - private
42   -
43   - def add(type, event, &block)
44   - missing_callback(event) unless @callbacks.has_key?(event)
45   -
46   - @callbacks[event].add(type, &block)
47   - end
48   -
49   - def missing_callback(event)
50   - raise InvalidCallback, "Unknown callback event: #{event}"
51   - end
52   - end
53   -
54   - class Callback
55   - def initialize
56   - @before = []
57   - @after = []
58   -
59   - # Identity proc. Avoids special cases when there is no existing around chain.
60   - @around = lambda { |*args, &block| block.call(*args) }
61   - end
62   -
63   - def execute(*args, &block)
64   - @before.each { |c| c.call(*args) }
65   - result = @around.call(*args, &block)
66   - @after.each { |c| c.call(*args) }
67   - result
68   - end
69   -
70   - def add(type, &callback)
71   - case type
72   - when :before
73   - @before << callback
74   - when :after
75   - @after << callback
76   - when :around
77   - chain = @around # use a local variable so that the current chain is closed over in the following lambda
78   - @around = lambda { |*a, &block| chain.call(*a) { |*b| callback.call(*b, &block) } }
79   - else
80   - raise InvalidCallback, "Invalid callback type: #{type}"
81   - end
82   - end
83   - end
84   -end
vendor/plugins/delayed_job/lib/delayed/message_sending.rb
... ... @@ -1,53 +0,0 @@
1   -require 'active_support/core_ext/module/aliasing'
2   -
3   -module Delayed
4   - class DelayProxy < Delayed::Compatibility.proxy_object_class
5   - def initialize(payload_class, target, options)
6   - @payload_class = payload_class
7   - @target = target
8   - @options = options
9   - end
10   -
11   - def method_missing(method, *args)
12   - Job.enqueue({:payload_object => @payload_class.new(@target, method.to_sym, args)}.merge(@options))
13   - end
14   - end
15   -
16   - module MessageSending
17   - def delay(options = {})
18   - DelayProxy.new(PerformableMethod, self, options)
19   - end
20   - alias __delay__ delay
21   -
22   - def send_later(method, *args)
23   - warn "[DEPRECATION] `object.send_later(:method)` is deprecated. Use `object.delay.method"
24   - __delay__.__send__(method, *args)
25   - end
26   -
27   - def send_at(time, method, *args)
28   - warn "[DEPRECATION] `object.send_at(time, :method)` is deprecated. Use `object.delay(:run_at => time).method"
29   - __delay__(:run_at => time).__send__(method, *args)
30   - end
31   -
32   - module ClassMethods
33   - def handle_asynchronously(method, opts = {})
34   - aliased_method, punctuation = method.to_s.sub(/([?!=])$/, ''), $1
35   - with_method, without_method = "#{aliased_method}_with_delay#{punctuation}", "#{aliased_method}_without_delay#{punctuation}"
36   - define_method(with_method) do |*args|
37   - curr_opts = opts.clone
38   - curr_opts.each_key do |key|
39   - if (val = curr_opts[key]).is_a?(Proc)
40   - curr_opts[key] = if val.arity == 1
41   - val.call(self)
42   - else
43   - val.call
44   - end
45   - end
46   - end
47   - delay(curr_opts).__send__(without_method, *args)
48   - end
49   - alias_method_chain method, :delay
50   - end
51   - end
52   - end
53   -end
vendor/plugins/delayed_job/lib/delayed/performable_mailer.rb
... ... @@ -1,21 +0,0 @@
1   -require 'mail'
2   -
3   -module Delayed
4   - class PerformableMailer < PerformableMethod
5   - def perform
6   - object.send(method_name, *args).deliver
7   - end
8   - end
9   -
10   - module DelayMail
11   - def delay(options = {})
12   - DelayProxy.new(PerformableMailer, self, options)
13   - end
14   - end
15   -end
16   -
17   -Mail::Message.class_eval do
18   - def delay(*args)
19   - raise RuntimeError, "Use MyMailer.delay.mailer_action(args) to delay sending of emails."
20   - end
21   -end
vendor/plugins/delayed_job/lib/delayed/performable_method.rb
... ... @@ -1,37 +0,0 @@
1   -require 'active_support/core_ext/module/delegation'
2   -
3   -module Delayed
4   - class PerformableMethod
5   - attr_accessor :object, :method_name, :args
6   -
7   - delegate :method, :to => :object
8   -
9   - def initialize(object, method_name, args)
10   - raise NoMethodError, "undefined method `#{method_name}' for #{object.inspect}" unless object.respond_to?(method_name, true)
11   -
12   - if object.respond_to?(:new_record?) && object.new_record?
13   - raise(ArgumentError, 'Jobs cannot be created for records before they\'ve been persisted')
14   - end
15   -
16   - self.object = object
17   - self.args = args
18   - self.method_name = method_name.to_sym
19   - end
20   -
21   - def display_name
22   - "#{object.class}##{method_name}"
23   - end
24   -
25   - def perform
26   - object.send(method_name, *args) if object
27   - end
28   -
29   - def method_missing(symbol, *args)
30   - object.send(symbol, *args)
31   - end
32   -
33   - def respond_to?(symbol, include_private=false)
34   - super || object.respond_to?(symbol, include_private)
35   - end
36   - end
37   -end
vendor/plugins/delayed_job/lib/delayed/plugin.rb
... ... @@ -1,15 +0,0 @@
1   -require 'active_support/core_ext/class/attribute'
2   -
3   -module Delayed
4   - class Plugin
5   - class_attribute :callback_block
6   -
7   - def self.callbacks(&block)
8   - self.callback_block = block
9   - end
10   -
11   - def initialize
12   - self.class.callback_block.call(Delayed::Worker.lifecycle) if self.class.callback_block
13   - end
14   - end
15   -end
vendor/plugins/delayed_job/lib/delayed/plugins/clear_locks.rb
... ... @@ -1,15 +0,0 @@
1   -module Delayed
2   - module Plugins
3   - class ClearLocks < Plugin
4   - callbacks do |lifecycle|
5   - lifecycle.around(:execute) do |worker, &block|
6   - begin
7   - block.call(worker)
8   - ensure
9   - Delayed::Job.clear_locks!(worker.name)
10   - end
11   - end
12   - end
13   - end
14   - end
15   -end
vendor/plugins/delayed_job/lib/delayed/psych_ext.rb
... ... @@ -1,146 +0,0 @@
1   -if defined?(ActiveRecord)
2   - ActiveRecord::Base.class_eval do
3   - if instance_methods.include?(:encode_with)
4   - def encode_with_override(coder)
5   - encode_with_without_override(coder)
6   - coder.tag = "!ruby/ActiveRecord:#{self.class.name}"
7   - end
8   - alias_method :encode_with_without_override, :encode_with
9   - alias_method :encode_with, :encode_with_override
10   - else
11   - def encode_with(coder)
12   - coder["attributes"] = attributes
13   - coder.tag = "!ruby/ActiveRecord:#{self.class.name}"
14   - end
15   - end
16   - end
17   -end
18   -
19   -class Delayed::PerformableMethod
20   - # serialize to YAML
21   - def encode_with(coder)
22   - coder.map = {
23   - "object" => object,
24   - "method_name" => method_name,
25   - "args" => args
26   - }
27   - end
28   -end
29   -
30   -module Psych
31   - module Visitors
32   - class YAMLTree
33   - def visit_Class(klass)
34   - @emitter.scalar klass.name, nil, '!ruby/class', false, false, Nodes::Scalar::SINGLE_QUOTED
35   - end
36   - end
37   -
38   - class ToRuby
39   - def visit_Psych_Nodes_Scalar(o)
40   - @st[o.anchor] = o.value if o.anchor
41   -
42   - if klass = Psych.load_tags[o.tag]
43   - instance = klass.allocate
44   -
45   - if instance.respond_to?(:init_with)
46   - coder = Psych::Coder.new(o.tag)
47   - coder.scalar = o.value
48   - instance.init_with coder
49   - end
50   -
51   - return instance
52   - end
53   -
54   - return o.value if o.quoted
55   - return @ss.tokenize(o.value) unless o.tag
56   -
57   - case o.tag
58   - when '!binary', 'tag:yaml.org,2002:binary'
59   - o.value.unpack('m').first
60   - when '!str', 'tag:yaml.org,2002:str'
61   - o.value
62   - when "!ruby/object:DateTime"
63   - require 'date'
64   - @ss.parse_time(o.value).to_datetime
65   - when "!ruby/object:Complex"
66   - Complex(o.value)
67   - when "!ruby/object:Rational"
68   - Rational(o.value)
69   - when "!ruby/class", "!ruby/module"
70   - resolve_class o.value
71   - when "tag:yaml.org,2002:float", "!float"
72   - Float(@ss.tokenize(o.value))
73   - when "!ruby/regexp"
74   - o.value =~ /^\/(.*)\/([mixn]*)$/
75   - source = $1
76   - options = 0
77   - lang = nil
78   - ($2 || '').split('').each do |option|
79   - case option
80   - when 'x' then options |= Regexp::EXTENDED
81   - when 'i' then options |= Regexp::IGNORECASE
82   - when 'm' then options |= Regexp::MULTILINE
83   - when 'n' then options |= Regexp::NOENCODING
84   - else lang = option
85   - end
86   - end
87   - Regexp.new(*[source, options, lang].compact)
88   - when "!ruby/range"
89   - args = o.value.split(/([.]{2,3})/, 2).map { |s|
90   - accept Nodes::Scalar.new(s)
91   - }
92   - args.push(args.delete_at(1) == '...')
93   - Range.new(*args)
94   - when /^!ruby\/sym(bol)?:?(.*)?$/
95   - o.value.to_sym
96   - else
97   - @ss.tokenize o.value
98   - end
99   - end
100   -
101   - def visit_Psych_Nodes_Mapping_with_class(object)
102   - return revive(Psych.load_tags[object.tag], object) if Psych.load_tags[object.tag]
103   -
104   - case object.tag
105   - when /^!ruby\/ActiveRecord:(.+)$/
106   - klass = resolve_class($1)
107   - payload = Hash[*object.children.map { |c| accept c }]
108   - id = payload["attributes"][klass.primary_key]
109   - begin
110   - klass.unscoped.find(id)
111   - rescue ActiveRecord::RecordNotFound
112   - raise Delayed::DeserializationError
113   - end
114   - when /^!ruby\/Mongoid:(.+)$/
115   - klass = resolve_class($1)
116   - payload = Hash[*object.children.map { |c| accept c }]
117   - begin
118   - klass.find(payload["attributes"]["_id"])
119   - rescue Mongoid::Errors::DocumentNotFound
120   - raise Delayed::DeserializationError
121   - end
122   - when /^!ruby\/DataMapper:(.+)$/
123   - klass = resolve_class($1)
124   - payload = Hash[*object.children.map { |c| accept c }]
125   - begin
126   - primary_keys = klass.properties.select { |p| p.key? }
127   - key_names = primary_keys.map { |p| p.name.to_s }
128   - klass.get!(*key_names.map { |k| payload["attributes"][k] })
129   - rescue DataMapper::ObjectNotFoundError
130   - raise Delayed::DeserializationError
131   - end
132   - else
133   - visit_Psych_Nodes_Mapping_without_class(object)
134   - end
135   - end
136   - alias_method_chain :visit_Psych_Nodes_Mapping, :class
137   -
138   - def resolve_class_with_constantize(klass_name)
139   - klass_name.constantize
140   - rescue
141   - resolve_class_without_constantize(klass_name)
142   - end
143   - alias_method_chain :resolve_class, :constantize
144   - end
145   - end
146   -end
vendor/plugins/delayed_job/lib/delayed/railtie.rb
... ... @@ -1,16 +0,0 @@
1   -require 'delayed_job'
2   -require 'rails'
3   -
4   -module Delayed
5   - class Railtie < Rails::Railtie
6   - initializer :after_initialize do
7   - ActiveSupport.on_load(:action_mailer) do
8   - ActionMailer::Base.send(:extend, Delayed::DelayMail)
9   - end
10   - end
11   -
12   - rake_tasks do
13   - load 'delayed/tasks.rb'
14   - end
15   - end
16   -end
vendor/plugins/delayed_job/lib/delayed/recipes.rb
... ... @@ -1,54 +0,0 @@
1   -# Capistrano Recipes for managing delayed_job
2   -#
3   -# Add these callbacks to have the delayed_job process restart when the server
4   -# is restarted:
5   -#
6   -# after "deploy:stop", "delayed_job:stop"
7   -# after "deploy:start", "delayed_job:start"
8   -# after "deploy:restart", "delayed_job:restart"
9   -#
10   -# If you want to use command line options, for example to start multiple workers,
11   -# define a Capistrano variable delayed_job_args:
12   -#
13   -# set :delayed_job_args, "-n 2"
14   -#
15   -# If you've got delayed_job workers running on a servers, you can also specify
16   -# which servers have delayed_job running and should be restarted after deploy.
17   -#
18   -# set :delayed_job_server_role, :worker
19   -#
20   -
21   -Capistrano::Configuration.instance.load do
22   - namespace :delayed_job do
23   - def rails_env
24   - fetch(:rails_env, false) ? "RAILS_ENV=#{fetch(:rails_env)}" : ''
25   - end
26   -
27   - def args
28   - fetch(:delayed_job_args, "")
29   - end
30   -
31   - def roles
32   - fetch(:delayed_job_server_role, :app)
33   - end
34   -
35   - def delayed_job_command
36   - fetch(:delayed_job_command, "script/delayed_job")
37   - end
38   -
39   - desc "Stop the delayed_job process"
40   - task :stop, :roles => lambda { roles } do
41   - run "cd #{current_path};#{rails_env} #{delayed_job_command} stop"
42   - end
43   -
44   - desc "Start the delayed_job process"
45   - task :start, :roles => lambda { roles } do
46   - run "cd #{current_path};#{rails_env} #{delayed_job_command} start #{args}"
47   - end
48   -
49   - desc "Restart the delayed_job process"
50   - task :restart, :roles => lambda { roles } do
51   - run "cd #{current_path};#{rails_env} #{delayed_job_command} restart #{args}"
52   - end
53   - end
54   -end
vendor/plugins/delayed_job/lib/delayed/serialization/active_record.rb
... ... @@ -1,15 +0,0 @@
1   -if defined?(ActiveRecord)
2   - class ActiveRecord::Base
3   - yaml_as "tag:ruby.yaml.org,2002:ActiveRecord"
4   -
5   - def self.yaml_new(klass, tag, val)
6   - klass.unscoped.find(val['attributes'][klass.primary_key])
7   - rescue ActiveRecord::RecordNotFound
8   - raise Delayed::DeserializationError, "ActiveRecord::RecordNotFound, class: #{klass} , primary key: #{val['attributes'][klass.primary_key]} "
9   - end
10   -
11   - def to_yaml_properties
12   - ['@attributes']
13   - end
14   - end
15   -end
vendor/plugins/delayed_job/lib/delayed/syck_ext.rb
... ... @@ -1,34 +0,0 @@
1   -class Module
2   - yaml_as "tag:ruby.yaml.org,2002:module"
3   -
4   - def self.yaml_new(klass, tag, val)
5   - val.constantize
6   - end
7   -
8   - def to_yaml(options = {})
9   - YAML.quick_emit(nil, options) do |out|
10   - out.scalar(taguri, name, :plain)
11   - end
12   - end
13   -
14   - def yaml_tag_read_class(name)
15   - # Constantize the object so that ActiveSupport can attempt
16   - # its auto loading magic. Will raise LoadError if not successful.
17   - name.constantize
18   - name
19   - end
20   -end
21   -
22   -class Class
23   - yaml_as "tag:ruby.yaml.org,2002:class"
24   - remove_method :to_yaml if respond_to?(:to_yaml) && method(:to_yaml).owner == Class # use Module's to_yaml
25   -end
26   -
27   -class Struct
28   - def self.yaml_tag_read_class(name)
29   - # Constantize the object so that ActiveSupport can attempt
30   - # its auto loading magic. Will raise LoadError if not successful.
31   - name.constantize
32   - "Struct::#{ name }"
33   - end
34   -end
vendor/plugins/delayed_job/lib/delayed/tasks.rb
... ... @@ -1,38 +0,0 @@
1   -namespace :jobs do
2   - desc "Clear the delayed_job queue."
3   - task :clear => :environment do
4   - Delayed::Job.delete_all
5   - end
6   -
7   - desc "Start a delayed_job worker."
8   - task :work => :environment_options do
9   - Delayed::Worker.new(@worker_options).start
10   - end
11   -
12   - desc "Start a delayed_job worker and exit when all available jobs are complete."
13   - task :workoff => :environment_options do
14   - Delayed::Worker.new(@worker_options.merge({:exit_on_complete => true})).start
15   - end
16   -
17   - task :environment_options => :environment do
18   - @worker_options = {
19   - :min_priority => ENV['MIN_PRIORITY'],
20   - :max_priority => ENV['MAX_PRIORITY'],
21   - :queues => (ENV['QUEUES'] || ENV['QUEUE'] || '').split(','),
22   - :quiet => false
23   - }
24   - end
25   -
26   - desc "Exit with error status if any jobs older than max_age seconds haven't been attempted yet."
27   - task :check, [:max_age] => :environment do |_, args|
28   - args.with_defaults(:max_age => 300)
29   -
30   - unprocessed_jobs = Delayed::Job.where('attempts = 0 AND created_at < ?', Time.now - args[:max_age].to_i).count
31   -
32   - if unprocessed_jobs > 0
33   - fail "#{unprocessed_jobs} jobs older than #{args[:max_age]} seconds have not been processed yet"
34   - end
35   -
36   - end
37   -
38   -end
vendor/plugins/delayed_job/lib/delayed/worker.rb
... ... @@ -1,283 +0,0 @@
1   -require 'timeout'
2   -require 'active_support/core_ext/numeric/time'
3   -require 'active_support/core_ext/class/attribute_accessors'
4   -require 'active_support/core_ext/kernel'
5   -require 'active_support/core_ext/enumerable'
6   -require 'logger'
7   -require 'benchmark'
8   -
9   -module Delayed
10   - class Worker
11   - DEFAULT_LOG_LEVEL = Logger::INFO
12   - DEFAULT_SLEEP_DELAY = 5
13   - DEFAULT_MAX_ATTEMPTS = 25
14   - DEFAULT_MAX_RUN_TIME = 4.hours
15   - DEFAULT_DEFAULT_PRIORITY = 0
16   - DEFAULT_DELAY_JOBS = true
17   - DEFAULT_QUEUES = []
18   - DEFAULT_READ_AHEAD = 5
19   -
20   - cattr_accessor :min_priority, :max_priority, :max_attempts, :max_run_time,
21   - :default_priority, :sleep_delay, :logger, :delay_jobs, :queues,
22   - :read_ahead, :plugins, :destroy_failed_jobs, :exit_on_complete
23   -
24   - # Named queue into which jobs are enqueued by default
25   - cattr_accessor :default_queue_name
26   -
27   - cattr_reader :backend
28   -
29   - # name_prefix is ignored if name is set directly
30   - attr_accessor :name_prefix
31   -
32   - def self.reset
33   - self.sleep_delay = DEFAULT_SLEEP_DELAY
34   - self.max_attempts = DEFAULT_MAX_ATTEMPTS
35   - self.max_run_time = DEFAULT_MAX_RUN_TIME
36   - self.default_priority = DEFAULT_DEFAULT_PRIORITY
37   - self.delay_jobs = DEFAULT_DELAY_JOBS
38   - self.queues = DEFAULT_QUEUES
39   - self.read_ahead = DEFAULT_READ_AHEAD
40   - end
41   -
42   - reset
43   -
44   - # Add or remove plugins in this list before the worker is instantiated
45   - self.plugins = [Delayed::Plugins::ClearLocks]
46   -
47   - # By default failed jobs are destroyed after too many attempts. If you want to keep them around
48   - # (perhaps to inspect the reason for the failure), set this to false.
49   - self.destroy_failed_jobs = true
50   -
51   - # By default, Signals INT and TERM set @exit, and the worker exits upon completion of the current job.
52   - # If you would prefer to raise a SignalException and exit immediately you can use this.
53   - # Be aware daemons uses TERM to stop and restart
54   - # false - No exceptions will be raised
55   - # :term - Will only raise an exception on TERM signals but INT will wait for the current job to finish
56   - # true - Will raise an exception on TERM and INT
57   - cattr_accessor :raise_signal_exceptions
58   - self.raise_signal_exceptions = false
59   -
60   - self.logger = if defined?(Rails)
61   - Rails.logger
62   - elsif defined?(RAILS_DEFAULT_LOGGER)
63   - RAILS_DEFAULT_LOGGER
64   - end
65   -
66   - def self.backend=(backend)
67   - if backend.is_a? Symbol
68   - require "delayed/serialization/#{backend}"
69   - require "delayed/backend/#{backend}"
70   - backend = "Delayed::Backend::#{backend.to_s.classify}::Job".constantize
71   - end
72   - @@backend = backend
73   - silence_warnings { ::Delayed.const_set(:Job, backend) }
74   - end
75   -
76   - def self.guess_backend
77   - warn "[DEPRECATION] guess_backend is deprecated. Please remove it from your code."
78   - end
79   -
80   - def self.before_fork
81   - unless @files_to_reopen
82   - @files_to_reopen = []
83   - ObjectSpace.each_object(File) do |file|
84   - @files_to_reopen << file unless file.closed?
85   - end
86   - end
87   -
88   - backend.before_fork
89   - end
90   -
91   - def self.after_fork
92   - # Re-open file handles
93   - @files_to_reopen.each do |file|
94   - begin
95   - file.reopen file.path, "a+"
96   - file.sync = true
97   - rescue ::Exception
98   - end
99   - end
100   -
101   - backend.after_fork
102   - end
103   -
104   - def self.lifecycle
105   - @lifecycle ||= Delayed::Lifecycle.new
106   - end
107   -
108   - def initialize(options={})
109   - @quiet = options.has_key?(:quiet) ? options[:quiet] : true
110   - @failed_reserve_count = 0
111   -
112   - [:min_priority, :max_priority, :sleep_delay, :read_ahead, :queues, :exit_on_complete].each do |option|
113   - self.class.send("#{option}=", options[option]) if options.has_key?(option)
114   - end
115   -
116   - self.plugins.each { |klass| klass.new }
117   - end
118   -
119   - # Every worker has a unique name which by default is the pid of the process. There are some
120   - # advantages to overriding this with something which survives worker restarts: Workers can
121   - # safely resume working on tasks which are locked by themselves. The worker will assume that
122   - # it crashed before.
123   - def name
124   - return @name unless @name.nil?
125   - "#{@name_prefix}host:#{Socket.gethostname} pid:#{Process.pid}" rescue "#{@name_prefix}pid:#{Process.pid}"
126   - end
127   -
128   - # Sets the name of the worker.
129   - # Setting the name to nil will reset the default worker name
130   - def name=(val)
131   - @name = val
132   - end
133   -
134   - def start
135   - trap('TERM') do
136   - say 'Exiting...'
137   - stop
138   - raise SignalException.new('TERM') if self.class.raise_signal_exceptions
139   - end
140   -
141   - trap('INT') do
142   - say 'Exiting...'
143   - stop
144   - raise SignalException.new('INT') if self.class.raise_signal_exceptions && self.class.raise_signal_exceptions != :term
145   - end
146   -
147   - say "Starting job worker"
148   -
149   - self.class.lifecycle.run_callbacks(:execute, self) do
150   - loop do
151   - self.class.lifecycle.run_callbacks(:loop, self) do
152   - @realtime = Benchmark.realtime do
153   - @result = work_off
154   - end
155   - end
156   -
157   - count = @result.sum
158   -
159   - if count.zero?
160   - if self.class.exit_on_complete
161   - say "No more jobs available. Exiting"
162   - break
163   - else
164   - sleep(self.class.sleep_delay) unless stop?
165   - end
166   - else
167   - say "#{count} jobs processed at %.4f j/s, %d failed" % [count / @realtime, @result.last]
168   - end
169   -
170   - break if stop?
171   - end
172   - end
173   - end
174   -
175   - def stop
176   - @exit = true
177   - end
178   -
179   - def stop?
180   - !!@exit
181   - end
182   -
183   - # Do num jobs and return stats on success/failure.
184   - # Exit early if interrupted.
185   - def work_off(num = 100)
186   - success, failure = 0, 0
187   -
188   - num.times do
189   - case reserve_and_run_one_job
190   - when true
191   - success += 1
192   - when false
193   - failure += 1
194   - else
195   - break # leave if no work could be done
196   - end
197   - break if stop? # leave if we're exiting
198   - end
199   -
200   - return [success, failure]
201   - end
202   -
203   - def run(job)
204   - job_say job, 'RUNNING'
205   - runtime = Benchmark.realtime do
206   - Timeout.timeout(self.class.max_run_time.to_i, WorkerTimeout) { job.invoke_job }
207   - job.destroy
208   - end
209   - job_say job, 'COMPLETED after %.4f' % runtime
210   - return true # did work
211   - rescue DeserializationError => error
212   - job.last_error = "#{error.message}\n#{error.backtrace.join("\n")}"
213   - failed(job)
214   - rescue Exception => error
215   - self.class.lifecycle.run_callbacks(:error, self, job){ handle_failed_job(job, error) }
216   - return false # work failed
217   - end
218   -
219   - # Reschedule the job in the future (when a job fails).
220   - # Uses an exponential scale depending on the number of failed attempts.
221   - def reschedule(job, time = nil)
222   - if (job.attempts += 1) < max_attempts(job)
223   - time ||= job.reschedule_at
224   - job.run_at = time
225   - job.unlock
226   - job.save!
227   - else
228   - job_say job, "REMOVED permanently because of #{job.attempts} consecutive failures", Logger::ERROR
229   - failed(job)
230   - end
231   - end
232   -
233   - def failed(job)
234   - self.class.lifecycle.run_callbacks(:failure, self, job) do
235   - job.hook(:failure)
236   - self.class.destroy_failed_jobs ? job.destroy : job.fail!
237   - end
238   - end
239   -
240   - def job_say(job, text, level = DEFAULT_LOG_LEVEL)
241   - text = "Job #{job.name} (id=#{job.id}) #{text}"
242   - say text, level
243   - end
244   -
245   - def say(text, level = DEFAULT_LOG_LEVEL)
246   - text = "[Worker(#{name})] #{text}"
247   - puts text unless @quiet
248   - logger.add level, "#{Time.now.strftime('%FT%T%z')}: #{text}" if logger
249   - end
250   -
251   - def max_attempts(job)
252   - job.max_attempts || self.class.max_attempts
253   - end
254   -
255   - protected
256   -
257   - def handle_failed_job(job, error)
258   - job.last_error = "#{error.message}\n#{error.backtrace.join("\n")}"
259   - job_say job, "FAILED (#{job.attempts} prior attempts) with #{error.class.name}: #{error.message}", Logger::ERROR
260   - reschedule(job)
261   - end
262   -
263   - # Run the next job we can get an exclusive lock on.
264   - # If no jobs are left we return nil
265   - def reserve_and_run_one_job
266   - job = reserve_job
267   - self.class.lifecycle.run_callbacks(:perform, self, job){ run(job) } if job
268   - end
269   -
270   - def reserve_job
271   - job = Delayed::Job.reserve(self)
272   - @failed_reserve_count = 0
273   - job
274   - rescue Exception => error
275   - say "Error while reserving job: #{error}"
276   - Delayed::Job.recover_from(error)
277   - @failed_reserve_count += 1
278   - raise FatalBackendError if @failed_reserve_count >= 10
279   - nil
280   - end
281   - end
282   -
283   -end
vendor/plugins/delayed_job/lib/delayed/yaml_ext.rb
... ... @@ -1,10 +0,0 @@
1   -# These extensions allow properly serializing and autoloading of
2   -# Classes, Modules and Structs
3   -
4   -require 'yaml'
5   -if YAML.parser.class.name =~ /syck|yecht/i
6   - require File.expand_path('../syck_ext', __FILE__)
7   - require File.expand_path('../serialization/active_record', __FILE__)
8   -else
9   - require File.expand_path('../psych_ext', __FILE__)
10   -end
vendor/plugins/delayed_job/lib/delayed_job.rb
... ... @@ -1,22 +0,0 @@
1   -require 'active_support'
2   -require 'delayed/compatibility'
3   -require 'delayed/exceptions'
4   -require 'delayed/message_sending'
5   -require 'delayed/performable_method'
6   -
7   -if defined?(ActionMailer)
8   - require 'action_mailer/version'
9   - require 'delayed/performable_mailer'
10   -end
11   -
12   -require 'delayed/yaml_ext'
13   -require 'delayed/lifecycle'
14   -require 'delayed/plugin'
15   -require 'delayed/plugins/clear_locks'
16   -require 'delayed/backend/base'
17   -require 'delayed/worker'
18   -require 'delayed/deserialization_error'
19   -require 'delayed/railtie' if defined?(Rails::Railtie)
20   -
21   -Object.send(:include, Delayed::MessageSending)
22   -Module.send(:include, Delayed::MessageSending::ClassMethods)
vendor/plugins/delayed_job/lib/generators/delayed_job/delayed_job_generator.rb
... ... @@ -1,12 +0,0 @@
1   -require 'rails/generators'
2   -require 'delayed/compatibility'
3   -
4   -class DelayedJobGenerator < Rails::Generators::Base
5   -
6   - self.source_paths << File.join(File.dirname(__FILE__), 'templates')
7   -
8   - def create_executable_file
9   - template "script", "#{Delayed::Compatibility.executable_prefix}/delayed_job"
10   - chmod "#{Delayed::Compatibility.executable_prefix}/delayed_job", 0755
11   - end
12   -end
vendor/plugins/delayed_job/lib/generators/delayed_job/templates/script
... ... @@ -1,5 +0,0 @@
1   -#!/usr/bin/env ruby
2   -
3   -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment'))
4   -require 'delayed/command'
5   -Delayed::Command.new(ARGV).daemonize
vendor/plugins/delayed_job/recipes/delayed_job.rb
... ... @@ -1 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'delayed', 'recipes'))
vendor/plugins/delayed_job/spec/autoloaded/clazz.rb
... ... @@ -1,7 +0,0 @@
1   -# Make sure this file does not get required manually
2   -module Autoloaded
3   - class Clazz
4   - def perform
5   - end
6   - end
7   -end
vendor/plugins/delayed_job/spec/autoloaded/instance_clazz.rb
... ... @@ -1,6 +0,0 @@
1   -module Autoloaded
2   - class InstanceClazz
3   - def perform
4   - end
5   - end
6   -end
vendor/plugins/delayed_job/spec/autoloaded/instance_struct.rb
... ... @@ -1,6 +0,0 @@
1   -module Autoloaded
2   - class InstanceStruct < ::Struct.new(nil)
3   - def perform
4   - end
5   - end
6   -end
vendor/plugins/delayed_job/spec/autoloaded/struct.rb
... ... @@ -1,7 +0,0 @@
1   -# Make sure this file does not get required manually
2   -module Autoloaded
3   - class Struct < ::Struct.new(nil)
4   - def perform
5   - end
6   - end
7   -end
vendor/plugins/delayed_job/spec/delayed/backend/test.rb
... ... @@ -1,112 +0,0 @@
1   -require 'ostruct'
2   -
3   -# An in-memory backend suitable only for testing. Tries to behave as if it were an ORM.
4   -module Delayed
5   - module Backend
6   - module Test
7   - class Job
8   - attr_accessor :id
9   - attr_accessor :priority
10   - attr_accessor :attempts
11   - attr_accessor :handler
12   - attr_accessor :last_error
13   - attr_accessor :run_at
14   - attr_accessor :locked_at
15   - attr_accessor :locked_by
16   - attr_accessor :failed_at
17   - attr_accessor :queue
18   -
19   - include Delayed::Backend::Base
20   -
21   - cattr_accessor :id
22   - self.id = 0
23   -
24   - def initialize(hash = {})
25   - self.attempts = 0
26   - self.priority = 0
27   - self.id = (self.class.id += 1)
28   - hash.each{|k,v| send(:"#{k}=", v)}
29   - end
30   -
31   - @jobs = []
32   - def self.all
33   - @jobs
34   - end
35   -
36   - def self.count
37   - all.size
38   - end
39   -
40   - def self.delete_all
41   - all.clear
42   - end
43   -
44   - def self.create(attrs = {})
45   - new(attrs).tap do |o|
46   - o.save
47   - end
48   - end
49   -
50   - def self.create!(*args); create(*args); end
51   -
52   - def self.clear_locks!(worker_name)
53   - all.select{|j| j.locked_by == worker_name}.each {|j| j.locked_by = nil; j.locked_at = nil}
54   - end
55   -
56   - # Find a few candidate jobs to run (in case some immediately get locked by others).
57   - def self.find_available(worker_name, limit = 5, max_run_time = Worker.max_run_time)
58   - jobs = all.select do |j|
59   - j.run_at <= db_time_now &&
60   - (j.locked_at.nil? || j.locked_at < db_time_now - max_run_time || j.locked_by == worker_name) &&
61   - !j.failed?
62   - end
63   -
64   - jobs = jobs.select{|j| Worker.queues.include?(j.queue)} if Worker.queues.any?
65   - jobs = jobs.select{|j| j.priority >= Worker.min_priority} if Worker.min_priority
66   - jobs = jobs.select{|j| j.priority <= Worker.max_priority} if Worker.max_priority
67   - jobs.sort_by{|j| [j.priority, j.run_at]}[0..limit-1]
68   - end
69   -
70   - # Lock this job for this worker.
71   - # Returns true if we have the lock, false otherwise.
72   - def lock_exclusively!(max_run_time, worker)
73   - now = self.class.db_time_now
74   - if locked_by != worker
75   - # We don't own this job so we will update the locked_by name and the locked_at
76   - self.locked_at = now
77   - self.locked_by = worker
78   - end
79   -
80   - return true
81   - end
82   -
83   - def self.db_time_now
84   - Time.current
85   - end
86   -
87   - def update_attributes(attrs = {})
88   - attrs.each{|k,v| send(:"#{k}=", v)}
89   - save
90   - end
91   -
92   - def destroy
93   - self.class.all.delete(self)
94   - end
95   -
96   - def save
97   - self.run_at ||= Time.current
98   -
99   - self.class.all << self unless self.class.all.include?(self)
100   - true
101   - end
102   -
103   - def save!; save; end
104   -
105   - def reload
106   - reset
107   - self
108   - end
109   - end
110   - end
111   - end
112   -end
vendor/plugins/delayed_job/spec/delayed/serialization/test.rb
vendor/plugins/delayed_job/spec/helper.rb
... ... @@ -1,61 +0,0 @@
1   -require 'logger'
2   -require 'rspec'
3   -
4   -require 'action_mailer'
5   -require 'active_support/dependencies'
6   -require 'active_record'
7   -
8   -require 'delayed_job'
9   -require 'delayed/backend/shared_spec'
10   -
11   -require 'simplecov'
12   -require 'coveralls'
13   -
14   -SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
15   - SimpleCov::Formatter::HTMLFormatter,
16   - Coveralls::SimpleCov::Formatter
17   -]
18   -SimpleCov.start
19   -
20   -Delayed::Worker.logger = Logger.new('/tmp/dj.log')
21   -ENV['RAILS_ENV'] = 'test'
22   -
23   -Delayed::Worker.backend = :test
24   -
25   -# Add this directory so the ActiveSupport autoloading works
26   -ActiveSupport::Dependencies.autoload_paths << File.dirname(__FILE__)
27   -
28   -# Add this to simulate Railtie initializer being executed
29   -ActionMailer::Base.send(:extend, Delayed::DelayMail)
30   -
31   -
32   -# Used to test interactions between DJ and an ORM
33   -ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ':memory:'
34   -ActiveRecord::Base.logger = Delayed::Worker.logger
35   -ActiveRecord::Migration.verbose = false
36   -
37   -ActiveRecord::Schema.define do
38   - create_table :stories, :primary_key => :story_id, :force => true do |table|
39   - table.string :text
40   - table.boolean :scoped, :default => true
41   - end
42   -end
43   -
44   -class Story < ActiveRecord::Base
45   - self.primary_key = 'story_id'
46   - def tell; text; end
47   - def whatever(n, _); tell*n; end
48   - default_scope { where(:scoped => true) }
49   -
50   - handle_asynchronously :whatever
51   -end
52   -
53   -RSpec.configure do |config|
54   - config.after(:each) do
55   - Delayed::Worker.reset
56   - end
57   -
58   - config.expect_with :rspec do |c|
59   - c.syntax = :expect
60   - end
61   -end
vendor/plugins/delayed_job/spec/lifecycle_spec.rb
... ... @@ -1,67 +0,0 @@
1   -require 'helper'
2   -
3   -describe Delayed::Lifecycle do
4   - let(:lifecycle) { Delayed::Lifecycle.new }
5   - let(:callback) { lambda {|*args|} }
6   - let(:arguments) { [1] }
7   - let(:behavior) { double(Object, :before! => nil, :after! => nil, :inside! => nil) }
8   - let(:wrapped_block) { Proc.new { behavior.inside! } }
9   -
10   - describe "before callbacks" do
11   - before(:each) do
12   - lifecycle.before(:execute, &callback)
13   - end
14   -
15   - it "executes before wrapped block" do
16   - callback.should_receive(:call).with(*arguments).ordered
17   - behavior.should_receive(:inside!).ordered
18   - lifecycle.run_callbacks :execute, *arguments, &wrapped_block
19   - end
20   - end
21   -
22   - describe "after callbacks" do
23   - before(:each) do
24   - lifecycle.after(:execute, &callback)
25   - end
26   -
27   - it "executes after wrapped block" do
28   - behavior.should_receive(:inside!).ordered
29   - callback.should_receive(:call).with(*arguments).ordered
30   - lifecycle.run_callbacks :execute, *arguments, &wrapped_block
31   - end
32   - end
33   -
34   - describe "around callbacks" do
35   - before(:each) do
36   - lifecycle.around(:execute) do |*args, &block|
37   - behavior.before!
38   - block.call(*args)
39   - behavior.after!
40   - end
41   - end
42   -
43   - it "wraps a block" do
44   - behavior.should_receive(:before!).ordered
45   - behavior.should_receive(:inside!).ordered
46   - behavior.should_receive(:after!).ordered
47   - lifecycle.run_callbacks :execute, *arguments, &wrapped_block
48   - end
49   -
50   - it "executes multiple callbacks in order" do
51   - behavior.should_receive(:one).ordered
52   - behavior.should_receive(:two).ordered
53   - behavior.should_receive(:three).ordered
54   -
55   - lifecycle.around(:execute) { |*args, &block| behavior.one; block.call(*args) }
56   - lifecycle.around(:execute) { |*args, &block| behavior.two; block.call(*args) }
57   - lifecycle.around(:execute) { |*args, &block| behavior.three; block.call(*args) }
58   -
59   - lifecycle.run_callbacks(:execute, *arguments, &wrapped_block)
60   - end
61   - end
62   -
63   - it "raises if callback is executed with wrong number of parameters" do
64   - lifecycle.before(:execute, &callback)
65   - expect { lifecycle.run_callbacks(:execute, 1,2,3) {} }.to raise_error(ArgumentError, /1 parameter/)
66   - end
67   -end
vendor/plugins/delayed_job/spec/message_sending_spec.rb
... ... @@ -1,122 +0,0 @@
1   -require 'helper'
2   -
3   -describe Delayed::MessageSending do
4   - describe "handle_asynchronously" do
5   - class Story
6   - def tell!(arg);end
7   - handle_asynchronously :tell!
8   - end
9   -
10   - it "aliases original method" do
11   - expect(Story.new).to respond_to(:tell_without_delay!)
12   - expect(Story.new).to respond_to(:tell_with_delay!)
13   - end
14   -
15   - it "creates a PerformableMethod" do
16   - story = Story.create
17   - expect {
18   - job = story.tell!(1)
19   - expect(job.payload_object.class).to eq(Delayed::PerformableMethod)
20   - expect(job.payload_object.method_name).to eq(:tell_without_delay!)
21   - expect(job.payload_object.args).to eq([1])
22   - }.to change { Delayed::Job.count }
23   - end
24   -
25   - describe "with options" do
26   - class Fable
27   - cattr_accessor :importance
28   - def tell;end
29   - handle_asynchronously :tell, :priority => Proc.new { self.importance }
30   - end
31   -
32   - it "sets the priority based on the Fable importance" do
33   - Fable.importance = 10
34   - job = Fable.new.tell
35   - expect(job.priority).to eq(10)
36   -
37   - Fable.importance = 20
38   - job = Fable.new.tell
39   - expect(job.priority).to eq(20)
40   - end
41   -
42   - describe "using a proc with parameters" do
43   - class Yarn
44   - attr_accessor :importance
45   - def spin
46   - end
47   - handle_asynchronously :spin, :priority => Proc.new {|y| y.importance }
48   - end
49   -
50   - it "sets the priority based on the Fable importance" do
51   - job = Yarn.new.tap {|y| y.importance = 10 }.spin
52   - expect(job.priority).to eq(10)
53   -
54   - job = Yarn.new.tap {|y| y.importance = 20 }.spin
55   - expect(job.priority).to eq(20)
56   - end
57   - end
58   - end
59   - end
60   -
61   - context "delay" do
62   - class FairyTail
63   - attr_accessor :happy_ending
64   - def self.princesses;end
65   - def tell
66   - @happy_ending = true
67   - end
68   - end
69   -
70   - after do
71   - Delayed::Worker.default_queue_name = nil
72   - end
73   -
74   - it "creates a new PerformableMethod job" do
75   - expect {
76   - job = "hello".delay.count('l')
77   - expect(job.payload_object.class).to eq(Delayed::PerformableMethod)
78   - expect(job.payload_object.method_name).to eq(:count)
79   - expect(job.payload_object.args).to eq(['l'])
80   - }.to change { Delayed::Job.count }.by(1)
81   - end
82   -
83   - it "sets default priority" do
84   - Delayed::Worker.default_priority = 99
85   - job = FairyTail.delay.to_s
86   - expect(job.priority).to eq(99)
87   - end
88   -
89   - it "sets default queue name" do
90   - Delayed::Worker.default_queue_name = 'abbazabba'
91   - job = FairyTail.delay.to_s
92   - expect(job.queue).to eq('abbazabba')
93   - end
94   -
95   - it "sets job options" do
96   - run_at = Time.parse('2010-05-03 12:55 AM')
97   - job = FairyTail.delay(:priority => 20, :run_at => run_at).to_s
98   - expect(job.run_at).to eq(run_at)
99   - expect(job.priority).to eq(20)
100   - end
101   -
102   - it "does not delay the job when delay_jobs is false" do
103   - Delayed::Worker.delay_jobs = false
104   - fairy_tail = FairyTail.new
105   - expect {
106   - expect {
107   - fairy_tail.delay.tell
108   - }.to change(fairy_tail, :happy_ending).from(nil).to(true)
109   - }.not_to change { Delayed::Job.count }
110   - end
111   -
112   - it "does delay the job when delay_jobs is true" do
113   - Delayed::Worker.delay_jobs = true
114   - fairy_tail = FairyTail.new
115   - expect {
116   - expect {
117   - fairy_tail.delay.tell
118   - }.not_to change(fairy_tail, :happy_ending)
119   - }.to change { Delayed::Job.count }.by(1)
120   - end
121   - end
122   -end
vendor/plugins/delayed_job/spec/performable_mailer_spec.rb
... ... @@ -1,44 +0,0 @@
1   -require 'helper'
2   -
3   -require 'action_mailer'
4   -class MyMailer < ActionMailer::Base
5   - def signup(email)
6   - mail :to => email, :subject => "Delaying Emails", :from => "delayedjob@example.com",:body => 'Delaying Emails Body'
7   - end
8   -end
9   -
10   -describe ActionMailer::Base do
11   - describe "delay" do
12   - it "enqueues a PerformableEmail job" do
13   - expect {
14   - job = MyMailer.delay.signup('john@example.com')
15   - expect(job.payload_object.class).to eq(Delayed::PerformableMailer)
16   - expect(job.payload_object.method_name).to eq(:signup)
17   - expect(job.payload_object.args).to eq(['john@example.com'])
18   - }.to change { Delayed::Job.count }.by(1)
19   - end
20   - end
21   -
22   - describe "delay on a mail object" do
23   - it "raises an exception" do
24   - expect {
25   - MyMailer.signup('john@example.com').delay
26   - }.to raise_error(RuntimeError)
27   - end
28   - end
29   -
30   - describe Delayed::PerformableMailer do
31   - describe "perform" do
32   - it "calls the method and #deliver on the mailer" do
33   - email = double('email', :deliver => true)
34   - mailer_class = double('MailerClass', :signup => email)
35   - mailer = Delayed::PerformableMailer.new(mailer_class, :signup, ['john@example.com'])
36   -
37   - mailer_class.should_receive(:signup).with('john@example.com')
38   - email.should_receive(:deliver)
39   - mailer.perform
40   - end
41   - end
42   - end
43   -
44   -end
vendor/plugins/delayed_job/spec/performable_method_spec.rb
... ... @@ -1,136 +0,0 @@
1   -require 'helper'
2   -
3   -describe Delayed::PerformableMethod do
4   - describe "perform" do
5   - before do
6   - @method = Delayed::PerformableMethod.new("foo", :count, ['o'])
7   - end
8   -
9   - context "with the persisted record cannot be found" do
10   - before do
11   - @method.object = nil
12   - end
13   -
14   - it "does nothing if object is nil" do
15   - expect{@method.perform}.not_to raise_error
16   - end
17   - end
18   -
19   - it "calls the method on the object" do
20   - @method.object.should_receive(:count).with('o')
21   - @method.perform
22   - end
23   - end
24   -
25   - it "raises a NoMethodError if target method doesn't exist" do
26   - expect {
27   - Delayed::PerformableMethod.new(Object, :method_that_does_not_exist, [])
28   - }.to raise_error(NoMethodError)
29   - end
30   -
31   - it "does not raise NoMethodError if target method is private" do
32   - clazz = Class.new do
33   - def private_method
34   - end
35   - private :private_method
36   - end
37   - expect {
38   - Delayed::PerformableMethod.new(clazz.new, :private_method, [])
39   - }.not_to raise_error
40   - end
41   -
42   - describe "hooks" do
43   - %w(before after success).each do |hook|
44   - it "delegates #{hook} hook to object" do
45   - story = Story.create
46   - job = story.delay.tell
47   -
48   - story.should_receive(hook).with(job)
49   - job.invoke_job
50   - end
51   - end
52   -
53   - %w(before after success).each do |hook|
54   - it "delegates #{hook} hook to object" do
55   - story = Story.create
56   - job = story.delay.tell
57   -
58   - story.should_receive(hook).with(job)
59   - job.invoke_job
60   - end
61   - end
62   -
63   - it "delegates enqueue hook to object" do
64   - story = Story.create
65   - story.should_receive(:enqueue).with(an_instance_of(Delayed::Job))
66   - story.delay.tell
67   - end
68   -
69   - it "delegates error hook to object" do
70   - story = Story.create
71   - story.should_receive(:error).with(an_instance_of(Delayed::Job), an_instance_of(RuntimeError))
72   - story.should_receive(:tell).and_raise(RuntimeError)
73   - expect { story.delay.tell.invoke_job }.to raise_error
74   - end
75   -
76   - it "delegates error hook to object when delay_jobs = false" do
77   - story = Story.create
78   - story.should_receive(:error).with(an_instance_of(Delayed::Job), an_instance_of(RuntimeError))
79   - story.should_receive(:tell).and_raise(RuntimeError)
80   - expect { story.delay.tell.invoke_job }.to raise_error
81   - end
82   -
83   - it "delegates failure hook to object" do
84   - method = Delayed::PerformableMethod.new("object", :size, [])
85   - method.object.should_receive(:failure)
86   - method.failure
87   - end
88   -
89   - context 'with delay_job == false' do
90   - before do
91   - Delayed::Worker.delay_jobs = false
92   - end
93   -
94   - after do
95   - Delayed::Worker.delay_jobs = true
96   - end
97   -
98   - %w(before after success).each do |hook|
99   - it "delegates #{hook} hook to object" do
100   - story = Story.create
101   - story.should_receive(hook).with(an_instance_of(Delayed::Job))
102   - story.delay.tell
103   - end
104   - end
105   -
106   - %w(before after success).each do |hook|
107   - it "delegates #{hook} hook to object" do
108   - story = Story.create
109   - story.should_receive(hook).with(an_instance_of(Delayed::Job))
110   - story.delay.tell
111   - end
112   - end
113   -
114   - it "delegates error hook to object" do
115   - story = Story.create
116   - story.should_receive(:error).with(an_instance_of(Delayed::Job), an_instance_of(RuntimeError))
117   - story.should_receive(:tell).and_raise(RuntimeError)
118   - expect { story.delay.tell }.to raise_error
119   - end
120   -
121   - it "delegates error hook to object when delay_jobs = false" do
122   - story = Story.create
123   - story.should_receive(:error).with(an_instance_of(Delayed::Job), an_instance_of(RuntimeError))
124   - story.should_receive(:tell).and_raise(RuntimeError)
125   - expect { story.delay.tell }.to raise_error
126   - end
127   -
128   - it "delegates failure hook to object when delay_jobs = false" do
129   - Delayed::Worker.delay_jobs = false
130   - method = Delayed::PerformableMethod.new("object", :size, [])
131   - method.object.should_receive(:failure)
132   - method.failure
133   - end
134   - end
135   - end
136   -end
vendor/plugins/delayed_job/spec/sample_jobs.rb
... ... @@ -1,75 +0,0 @@
1   -class NamedJob < Struct.new(:perform)
2   - def display_name
3   - 'named_job'
4   - end
5   -end
6   -
7   -class SimpleJob
8   - cattr_accessor :runs; self.runs = 0
9   - def perform; @@runs += 1; end
10   -end
11   -
12   -class ErrorJob
13   - cattr_accessor :runs; self.runs = 0
14   - def perform; raise 'did not work'; end
15   -end
16   -
17   -class CustomRescheduleJob < Struct.new(:offset)
18   - cattr_accessor :runs; self.runs = 0
19   - def perform; raise 'did not work'; end
20   - def reschedule_at(time, attempts); time + offset; end
21   -end
22   -
23   -class LongRunningJob
24   - def perform; sleep 250; end
25   -end
26   -
27   -class OnPermanentFailureJob < SimpleJob
28   - def failure; end
29   - def max_attempts; 1; end
30   -end
31   -
32   -module M
33   - class ModuleJob
34   - cattr_accessor :runs; self.runs = 0
35   - def perform; @@runs += 1; end
36   - end
37   -end
38   -
39   -class CallbackJob
40   - cattr_accessor :messages
41   -
42   - def enqueue(job)
43   - self.class.messages << 'enqueue'
44   - end
45   -
46   - def before(job)
47   - self.class.messages << 'before'
48   - end
49   -
50   - def perform
51   - self.class.messages << 'perform'
52   - end
53   -
54   - def after(job)
55   - self.class.messages << 'after'
56   - end
57   -
58   - def success(job)
59   - self.class.messages << 'success'
60   - end
61   -
62   - def error(job, error)
63   - self.class.messages << "error: #{error.class}"
64   - end
65   -
66   - def failure(job)
67   - self.class.messages << 'failure'
68   - end
69   -end
70   -
71   -class EnqueueJobMod < SimpleJob
72   - def enqueue(job)
73   - job.run_at = 20.minutes.from_now
74   - end
75   -end
vendor/plugins/delayed_job/spec/test_backend_spec.rb
... ... @@ -1,13 +0,0 @@
1   -require 'helper'
2   -
3   -describe Delayed::Backend::Test::Job do
4   - it_should_behave_like 'a delayed_job backend'
5   -
6   - describe "#reload" do
7   - it "causes the payload object to be reloaded" do
8   - job = "foo".delay.length
9   - o = job.payload_object
10   - expect(o.object_id).not_to eq(job.reload.payload_object.object_id)
11   - end
12   - end
13   -end
vendor/plugins/delayed_job/spec/worker_spec.rb
... ... @@ -1,102 +0,0 @@
1   -require 'helper'
2   -
3   -describe Delayed::Worker do
4   - describe "backend=" do
5   - before do
6   - @clazz = Class.new
7   - Delayed::Worker.backend = @clazz
8   - end
9   -
10   - after do
11   - Delayed::Worker.backend = :test
12   - end
13   -
14   - it "sets the Delayed::Job constant to the backend" do
15   - expect(Delayed::Job).to eq(@clazz)
16   - end
17   -
18   - it "sets backend with a symbol" do
19   - Delayed::Worker.backend = :test
20   - expect(Delayed::Worker.backend).to eq(Delayed::Backend::Test::Job)
21   - end
22   - end
23   -
24   - describe "job_say" do
25   - before do
26   - @worker = Delayed::Worker.new
27   - @job = double('job', :id => 123, :name => 'ExampleJob')
28   - end
29   -
30   - it "logs with job name and id" do
31   - @worker.should_receive(:say).
32   - with('Job ExampleJob (id=123) message', Delayed::Worker::DEFAULT_LOG_LEVEL)
33   - @worker.job_say(@job, 'message')
34   - end
35   - end
36   -
37   - context "worker read-ahead" do
38   - before do
39   - @read_ahead = Delayed::Worker.read_ahead
40   - end
41   -
42   - after do
43   - Delayed::Worker.read_ahead = @read_ahead
44   - end
45   -
46   - it "reads five jobs" do
47   - Delayed::Job.should_receive(:find_available).with(anything, 5, anything).and_return([])
48   - Delayed::Job.reserve(Delayed::Worker.new)
49   - end
50   -
51   - it "reads a configurable number of jobs" do
52   - Delayed::Worker.read_ahead = 15
53   - Delayed::Job.should_receive(:find_available).with(anything, Delayed::Worker.read_ahead, anything).and_return([])
54   - Delayed::Job.reserve(Delayed::Worker.new)
55   - end
56   - end
57   -
58   - context "worker exit on complete" do
59   - before do
60   - Delayed::Worker.exit_on_complete = true
61   - end
62   -
63   - after do
64   - Delayed::Worker.exit_on_complete = false
65   - end
66   -
67   - it "exits the loop when no jobs are available" do
68   - worker = Delayed::Worker.new
69   - Timeout::timeout(2) do
70   - worker.start
71   - end
72   - end
73   - end
74   -
75   - context "worker job reservation" do
76   - before do
77   - Delayed::Worker.exit_on_complete = true
78   - end
79   -
80   - after do
81   - Delayed::Worker.exit_on_complete = false
82   - end
83   -
84   - it "handles error during job reservation" do
85   - Delayed::Job.should_receive(:reserve).and_raise(Exception)
86   - Delayed::Worker.new.work_off
87   - end
88   -
89   - it "gives up after 10 backend failures" do
90   - Delayed::Job.stub(:reserve).and_raise(Exception)
91   - worker = Delayed::Worker.new
92   - 9.times { worker.work_off }
93   - expect(lambda { worker.work_off }).to raise_exception
94   - end
95   -
96   - it "allows the backend to attempt recovery from reservation errors" do
97   - Delayed::Job.should_receive(:reserve).and_raise(Exception)
98   - Delayed::Job.should_receive(:recover_from).with(instance_of(Exception))
99   - Delayed::Worker.new.work_off
100   - end
101   - end
102   -end
vendor/plugins/delayed_job/spec/yaml_ext_spec.rb
... ... @@ -1,35 +0,0 @@
1   -require 'helper'
2   -
3   -describe "YAML" do
4   - it "autoloads classes" do
5   - expect {
6   - yaml = "--- !ruby/class Autoloaded::Clazz\n"
7   - expect(YAML.load(yaml)).to eq(Autoloaded::Clazz)
8   - }.not_to raise_error
9   - end
10   -
11   - it "autoloads the class of a struct" do
12   - expect {
13   - yaml = "--- !ruby/class Autoloaded::Struct\n"
14   - expect(YAML.load(yaml)).to eq(Autoloaded::Struct)
15   - }.not_to raise_error
16   - end
17   -
18   - it "autoloads the class for the instance of a struct" do
19   - expect {
20   - yaml = "--- !ruby/struct:Autoloaded::InstanceStruct {}"
21   - expect(YAML.load(yaml).class).to eq(Autoloaded::InstanceStruct)
22   - }.not_to raise_error
23   - end
24   -
25   - it "autoloads the class for the instance" do
26   - expect {
27   - yaml = "--- !ruby/object:Autoloaded::InstanceClazz {}\n"
28   - expect(YAML.load(yaml).class).to eq(Autoloaded::InstanceClazz)
29   - }.not_to raise_error
30   - end
31   -
32   - it "does not throw an uninitialized constant Syck::Syck when using YAML.load with poorly formed yaml" do
33   - expect{ YAML.load(YAML.dump("foo: *bar"))}.not_to raise_error
34   - end
35   -end
vendor/plugins/delayed_job_active_record/.rspec
... ... @@ -1,2 +0,0 @@
1   ---color
2   ---fail-fast
vendor/plugins/delayed_job_active_record/.travis.yml
... ... @@ -1,28 +0,0 @@
1   -language: ruby
2   -before_script:
3   - - mysql -e 'create database delayed_job_test;'
4   - - psql -c 'create database delayed_job_test;' -U postgres
5   -script: bundle exec rspec
6   -gemfile:
7   - - gemfiles/mysql/3-0.gemfile
8   - - gemfiles/mysql/3-1.gemfile
9   - - gemfiles/mysql/3-2.gemfile
10   - - gemfiles/mysql/4-0.gemfile
11   - - gemfiles/postgresql/3-0.gemfile
12   - - gemfiles/postgresql/3-1.gemfile
13   - - gemfiles/postgresql/3-2.gemfile
14   - - gemfiles/postgresql/4-0.gemfile
15   - - gemfiles/sqlite3/3-0.gemfile
16   - - gemfiles/sqlite3/3-1.gemfile
17   - - gemfiles/sqlite3/3-2.gemfile
18   - - gemfiles/sqlite3/4-0.gemfile
19   - - gemfiles/sqlite3/4-0-protected_attributes.gemfile
20   -rvm:
21   - - rbx-19mode
22   - - jruby-19mode
23   - - 1.9.3
24   - - 2.0.0
25   -matrix:
26   - allow_failures:
27   - - rvm: rbx-19mode
28   - - rvm: jruby-19mode
vendor/plugins/delayed_job_active_record/CONTRIBUTING.md
... ... @@ -1,14 +0,0 @@
1   -## How to contribute
2   -
3   -If you find what looks like a bug:
4   -
5   -* Search the [mailing list](http://groups.google.com/group/delayed_job) to see if anyone else had the same issue.
6   -* Check the [GitHub issue tracker](http://github.com/collectiveidea/delayed_job_active_record/issues/) to see if anyone else has reported issue.
7   -* If you don't see anything, create an issue with information on how to reproduce it.
8   -
9   -If you want to contribute an enhancement or a fix:
10   -
11   -* Fork the project on github.
12   -* Make your changes with tests.
13   -* Commit the changes without making changes to the Rakefile or any other files that aren't related to your enhancement or fix
14   -* Send a pull request.
vendor/plugins/delayed_job_active_record/Gemfile
... ... @@ -1,28 +0,0 @@
1   -source 'https://rubygems.org'
2   -
3   -gem 'rake'
4   -
5   -group :test do
6   - platforms :jruby do
7   - gem 'activerecord-jdbcmysql-adapter'
8   - gem 'jdbc-mysql'
9   -
10   - gem 'activerecord-jdbcpostgresql-adapter'
11   - gem 'jdbc-postgres'
12   -
13   - gem 'activerecord-jdbcsqlite3-adapter'
14   - gem 'jdbc-sqlite3'
15   - end
16   -
17   - platforms :ruby, :mswin, :mingw do
18   - gem 'mysql', '~> 2.8.1'
19   - gem 'pg'
20   - gem 'sqlite3'
21   - end
22   -
23   - gem 'coveralls', :require => false
24   - gem 'rspec', '>= 2.11'
25   - gem 'simplecov', :require => false
26   -end
27   -
28   -gemspec
vendor/plugins/delayed_job_active_record/LICENSE.md
... ... @@ -1,20 +0,0 @@
1   -Copyright (c) 2005 Tobias Lütke
2   -
3   -Permission is hereby granted, free of charge, to any person obtaining
4   -a copy of this software and associated documentation files (the
5   -"Software"), to deal in the Software without restriction, including
6   -without limitation the rights to use, copy, modify, merge, publish,
7   -distribute, sublicense, and/or sell copies of the Software, and to
8   -permit persons to whom the Software is furnished to do so, subject to
9   -the following conditions:
10   -
11   -The above copyright notice and this permission notice shall be
12   -included in all copies or substantial portions of the Software.
13   -
14   -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15   -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16   -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOa AND
17   -NONINFRINGEMENT. IN NO EVENT SaALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18   -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19   -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20   -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
vendor/plugins/delayed_job_active_record/README.md
... ... @@ -1,31 +0,0 @@
1   -# DelayedJob ActiveRecord Backend
2   -
3   -[![Gem Version](https://badge.fury.io/rb/delayed_job_active_record.png)](https://rubygems.org/gems/delayed_job_active_record)
4   -[![Build Status](https://travis-ci.org/collectiveidea/delayed_job_active_record.png)](https://travis-ci.org/collectiveidea/delayed_job_active_record)
5   -[![Dependency Status](https://gemnasium.com/collectiveidea/delayed_job_active_record.png)](https://gemnasium.com/collectiveidea/delayed_job_active_record)
6   -[![Code Climate](https://codeclimate.com/github/collectiveidea/delayed_job_active_record.png)](https://codeclimate.com/github/collectiveidea/delayed_job_active_record)
7   -[![Coverage Status](https://coveralls.io/repos/collectiveidea/delayed_job_active_record/badge.png?branch=master)](https://coveralls.io/r/collectiveidea/delayed_job_active_record)
8   -
9   -## Installation
10   -
11   -Add the gem to your Gemfile:
12   -
13   - gem 'delayed_job_active_record'
14   -
15   -Run `bundle install`.
16   -
17   -If you're using Rails, run the generator to create the migration for the
18   -delayed_job table.
19   -
20   - rails g delayed_job:active_record
21   - rake db:migrate
22   -
23   -## Upgrading from 2.x to 3.0.0
24   -
25   -If you're upgrading from Delayed Job 2.x, run the upgrade generator to create a
26   -migration to add a column to your delayed_jobs table.
27   -
28   - rails g delayed_job:upgrade
29   - rake db:migrate
30   -
31   -That's it. Use [delayed_job as normal](http://github.com/collectiveidea/delayed_job).
vendor/plugins/delayed_job_active_record/Rakefile
... ... @@ -1,35 +0,0 @@
1   -# -*- encoding: utf-8 -*-
2   -require "bundler/gem_helper"
3   -Bundler::GemHelper.install_tasks
4   -
5   -require "rspec/core/rake_task"
6   -
7   -ADAPTERS = %w(mysql postgresql sqlite3)
8   -
9   -ADAPTERS.each do |adapter|
10   - desc "Run RSpec code examples for #{adapter} adapter"
11   - RSpec::Core::RakeTask.new(adapter => "#{adapter}:adapter")
12   -
13   - namespace adapter do
14   - task :adapter do
15   - ENV["ADAPTER"] = adapter
16   - end
17   - end
18   -end
19   -
20   -task :coverage do
21   - ENV["COVERAGE"] = "true"
22   -end
23   -
24   -task :adapter do
25   - ENV["ADAPTER"] = nil
26   -end
27   -
28   -Rake::Task[:spec].enhance do
29   - require "simplecov"
30   - require "coveralls"
31   -
32   - Coveralls::SimpleCov::Formatter.new.format(SimpleCov.result)
33   -end
34   -
35   -task default: ([:coverage] + ADAPTERS + [:adapter])
vendor/plugins/delayed_job_active_record/delayed_job_active_record.gemspec
... ... @@ -1,19 +0,0 @@
1   -# coding: utf-8
2   -
3   -Gem::Specification.new do |spec|
4   - spec.add_dependency 'activerecord', ['>= 3.0', '< 4.1']
5   - spec.add_dependency 'delayed_job', ['>= 3.0', '< 4.1']
6   - spec.authors = ["Brian Ryckbost", "Matt Griffin", "Erik Michaels-Ober"]
7   - spec.description = 'ActiveRecord backend for Delayed::Job, originally authored by Tobias Lütke'
8   - spec.email = ['bryckbost@gmail.com', 'matt@griffinonline.org', 'sferik@gmail.com']
9   - spec.files = %w(CONTRIBUTING.md LICENSE.md README.md Rakefile delayed_job_active_record.gemspec)
10   - spec.files += Dir.glob("lib/**/*.rb")
11   - spec.files += Dir.glob("spec/**/*")
12   - spec.homepage = 'http://github.com/collectiveidea/delayed_job_active_record'
13   - spec.licenses = ['MIT']
14   - spec.name = 'delayed_job_active_record'
15   - spec.require_paths = ['lib']
16   - spec.summary = 'ActiveRecord backend for DelayedJob'
17   - spec.test_files = Dir.glob("spec/**/*")
18   - spec.version = '4.0.0'
19   -end
vendor/plugins/delayed_job_active_record/gemfiles/mysql/3-0.gemfile
... ... @@ -1,23 +0,0 @@
1   -source 'https://rubygems.org'
2   -
3   -gem 'rake'
4   -
5   -group :test do
6   - platforms :jruby do
7   - gem 'activerecord-jdbc-adapter'
8   - gem 'activerecord-jdbcmysql-adapter'
9   - gem 'jdbc-mysql'
10   - end
11   -
12   - platforms :ruby, :mswin, :mingw do
13   - gem 'mysql', '~> 2.8.1'
14   - end
15   -
16   - gem 'coveralls', :require => false
17   - gem 'rspec', '>= 2.11'
18   - gem 'simplecov', :require => false
19   -
20   - gem 'activerecord', "~> 3.0.0"
21   -end
22   -
23   -gemspec :path => "../../"
vendor/plugins/delayed_job_active_record/gemfiles/mysql/3-1.gemfile
... ... @@ -1,23 +0,0 @@
1   -source 'https://rubygems.org'
2   -
3   -gem 'rake'
4   -
5   -group :test do
6   - platforms :jruby do
7   - gem 'activerecord-jdbc-adapter'
8   - gem 'activerecord-jdbcmysql-adapter'
9   - gem 'jdbc-mysql'
10   - end
11   -
12   - platforms :ruby, :mswin, :mingw do
13   - gem 'mysql', '~> 2.8.1'
14   - end
15   -
16   - gem 'coveralls', :require => false
17   - gem 'rspec', '>= 2.11'
18   - gem 'simplecov', :require => false
19   -
20   - gem 'activerecord', "~> 3.1.0"
21   -end
22   -
23   -gemspec :path => "../../"
vendor/plugins/delayed_job_active_record/gemfiles/mysql/3-2.gemfile
... ... @@ -1,23 +0,0 @@
1   -source 'https://rubygems.org'
2   -
3   -gem 'rake'
4   -
5   -group :test do
6   - platforms :jruby do
7   - gem 'activerecord-jdbc-adapter'
8   - gem 'activerecord-jdbcmysql-adapter'
9   - gem 'jdbc-mysql'
10   - end
11   -
12   - platforms :ruby, :mswin, :mingw do
13   - gem 'mysql', '~> 2.8.1'
14   - end
15   -
16   - gem 'coveralls', :require => false
17   - gem 'rspec', '>= 2.11'
18   - gem 'simplecov', :require => false
19   -
20   - gem 'activerecord', "~> 3.2.0"
21   -end
22   -
23   -gemspec :path => "../../"
vendor/plugins/delayed_job_active_record/gemfiles/mysql/4-0.gemfile
... ... @@ -1,25 +0,0 @@
1   -source 'https://rubygems.org'
2   -
3   -gem 'rake'
4   -
5   -group :test do
6   - platforms :jruby do
7   - gem 'activerecord-jdbc-adapter'
8   - gem 'activerecord-jdbcmysql-adapter'
9   - gem 'jdbc-mysql'
10   - end
11   -
12   - platforms :ruby, :mswin, :mingw do
13   - gem 'mysql', '~> 2.9'
14   - end
15   -
16   - gem 'coveralls', :require => false
17   - gem 'rspec', '>= 2.11'
18   - gem 'simplecov', :require => false
19   -
20   - gem 'activerecord', "~> 4.0.0.beta"
21   -
22   - gem 'delayed_job', "~> 4.0.0.beta"
23   -end
24   -
25   -gemspec :path => "../../"
vendor/plugins/delayed_job_active_record/gemfiles/postgresql/3-0.gemfile
... ... @@ -1,23 +0,0 @@
1   -source 'https://rubygems.org'
2   -
3   -gem 'rake'
4   -
5   -group :test do
6   - platforms :jruby do
7   - gem 'activerecord-jdbc-adapter'
8   - gem 'activerecord-jdbcpostgresql-adapter'
9   - gem 'jdbc-postgres'
10   - end
11   -
12   - platforms :ruby, :mswin, :mingw do
13   - gem 'pg'
14   - end
15   -
16   - gem 'coveralls', :require => false
17   - gem 'rspec', '>= 2.11'
18   - gem 'simplecov', :require => false
19   -
20   - gem 'activerecord', "~> 3.0.0"
21   -end
22   -
23   -gemspec :path => "../../"
vendor/plugins/delayed_job_active_record/gemfiles/postgresql/3-1.gemfile
... ... @@ -1,23 +0,0 @@
1   -source 'https://rubygems.org'
2   -
3   -gem 'rake'
4   -
5   -group :test do
6   - platforms :jruby do
7   - gem 'activerecord-jdbc-adapter'
8   - gem 'activerecord-jdbcpostgresql-adapter'
9   - gem 'jdbc-postgres'
10   - end
11   -
12   - platforms :ruby, :mswin, :mingw do
13   - gem 'pg'
14   - end
15   -
16   - gem 'coveralls', :require => false
17   - gem 'rspec', '>= 2.11'
18   - gem 'simplecov', :require => false
19   -
20   - gem 'activerecord', "~> 3.1.0"
21   -end
22   -
23   -gemspec :path => "../../"
vendor/plugins/delayed_job_active_record/gemfiles/postgresql/3-2.gemfile
... ... @@ -1,23 +0,0 @@
1   -source 'https://rubygems.org'
2   -
3   -gem 'rake'
4   -
5   -group :test do
6   - platforms :jruby do
7   - gem 'activerecord-jdbc-adapter'
8   - gem 'activerecord-jdbcpostgresql-adapter'
9   - gem 'jdbc-postgres'
10   - end
11   -
12   - platforms :ruby, :mswin, :mingw do
13   - gem 'pg'
14   - end
15   -
16   - gem 'coveralls', :require => false
17   - gem 'rspec', '>= 2.11'
18   - gem 'simplecov', :require => false
19   -
20   - gem 'activerecord', "~> 3.2.0"
21   -end
22   -
23   -gemspec :path => "../../"
vendor/plugins/delayed_job_active_record/gemfiles/postgresql/4-0.gemfile
... ... @@ -1,25 +0,0 @@
1   -source 'https://rubygems.org'
2   -
3   -gem 'rake'
4   -
5   -group :test do
6   - platforms :jruby do
7   - gem 'activerecord-jdbc-adapter'
8   - gem 'activerecord-jdbcpostgresql-adapter'
9   - gem 'jdbc-postgres'
10   - end
11   -
12   - platforms :ruby, :mswin, :mingw do
13   - gem 'pg'
14   - end
15   -
16   - gem 'coveralls', :require => false
17   - gem 'rspec', '>= 2.11'
18   - gem 'simplecov', :require => false
19   -
20   - gem 'activerecord', "~> 4.0.0.beta"
21   -
22   - gem 'delayed_job', "~> 4.0.0.beta"
23   -end
24   -
25   -gemspec :path => "../../"
vendor/plugins/delayed_job_active_record/gemfiles/sqlite3/3-0.gemfile
... ... @@ -1,23 +0,0 @@
1   -source 'https://rubygems.org'
2   -
3   -gem 'rake'
4   -
5   -group :test do
6   - platforms :jruby do
7   - gem 'jruby-openssl'
8   - gem 'activerecord-jdbc-adapter'
9   - gem 'activerecord-jdbcsqlite3-adapter'
10   - end
11   -
12   - platforms :ruby, :mswin, :mingw do
13   - gem 'sqlite3'
14   - end
15   -
16   - gem 'coveralls', :require => false
17   - gem 'rspec', '>= 2.11'
18   - gem 'simplecov', :require => false
19   -
20   - gem 'activerecord', "~> 3.0.0"
21   -end
22   -
23   -gemspec :path => "../../"
vendor/plugins/delayed_job_active_record/gemfiles/sqlite3/3-1.gemfile
... ... @@ -1,23 +0,0 @@
1   -source 'https://rubygems.org'
2   -
3   -gem 'rake'
4   -
5   -group :test do
6   - platforms :jruby do
7   - gem 'jruby-openssl'
8   - gem 'activerecord-jdbc-adapter'
9   - gem 'activerecord-jdbcsqlite3-adapter'
10   - end
11   -
12   - platforms :ruby, :mswin, :mingw do
13   - gem 'sqlite3'
14   - end
15   -
16   - gem 'coveralls', :require => false
17   - gem 'rspec', '>= 2.11'
18   - gem 'simplecov', :require => false
19   -
20   - gem 'activerecord', "~> 3.1.0"
21   -end
22   -
23   -gemspec :path => "../../"
vendor/plugins/delayed_job_active_record/gemfiles/sqlite3/3-2.gemfile
... ... @@ -1,23 +0,0 @@
1   -source 'https://rubygems.org'
2   -
3   -gem 'rake'
4   -
5   -group :test do
6   - platforms :jruby do
7   - gem 'jruby-openssl'
8   - gem 'activerecord-jdbc-adapter'
9   - gem 'activerecord-jdbcsqlite3-adapter'
10   - end
11   -
12   - platforms :ruby, :mswin, :mingw do
13   - gem 'sqlite3'
14   - end
15   -
16   - gem 'coveralls', :require => false
17   - gem 'rspec', '>= 2.11'
18   - gem 'simplecov', :require => false
19   -
20   - gem 'activerecord', "~> 3.2.0"
21   -end
22   -
23   -gemspec :path => "../../"
vendor/plugins/delayed_job_active_record/gemfiles/sqlite3/4-0-protected_attributes.gemfile
... ... @@ -1,26 +0,0 @@
1   -source 'https://rubygems.org'
2   -
3   -gem 'rake'
4   -
5   -group :test do
6   - platforms :jruby do
7   - gem 'jruby-openssl'
8   - gem 'activerecord-jdbc-adapter'
9   - gem 'activerecord-jdbcsqlite3-adapter'
10   - end
11   -
12   - platforms :ruby, :mswin, :mingw do
13   - gem 'sqlite3'
14   - end
15   -
16   - gem 'coveralls', :require => false
17   - gem 'rspec', '>= 2.11', :require => false
18   - gem 'simplecov', :require => false
19   -
20   - gem 'activerecord', "~> 4.0.0.beta"
21   - gem 'protected_attributes'
22   -
23   - gem 'delayed_job', "~> 4.0.0.beta", :require => false
24   -end
25   -
26   -gemspec :path => "../../"
vendor/plugins/delayed_job_active_record/gemfiles/sqlite3/4-0.gemfile
... ... @@ -1,25 +0,0 @@
1   -source 'https://rubygems.org'
2   -
3   -gem 'rake'
4   -
5   -group :test do
6   - platforms :jruby do
7   - gem 'jruby-openssl'
8   - gem 'activerecord-jdbc-adapter'
9   - gem 'activerecord-jdbcsqlite3-adapter'
10   - end
11   -
12   - platforms :ruby, :mswin, :mingw do
13   - gem 'sqlite3'
14   - end
15   -
16   - gem 'coveralls', :require => false
17   - gem 'rspec', '>= 2.11'
18   - gem 'simplecov', :require => false
19   -
20   - gem 'activerecord', "~> 4.0.0.beta"
21   -
22   - gem 'delayed_job', "~> 4.0.0.beta"
23   -end
24   -
25   -gemspec :path => "../../"
vendor/plugins/delayed_job_active_record/lib/delayed/backend/active_record.rb
... ... @@ -1,111 +0,0 @@
1   -require 'active_record/version'
2   -module Delayed
3   - module Backend
4   - module ActiveRecord
5   - # A job object that is persisted to the database.
6   - # Contains the work object as a YAML field.
7   - class Job < ::ActiveRecord::Base
8   - include Delayed::Backend::Base
9   -
10   - if ::ActiveRecord::VERSION::MAJOR < 4 || defined?(::ActiveRecord::MassAssignmentSecurity)
11   - attr_accessible :priority, :run_at, :queue, :payload_object,
12   - :failed_at, :locked_at, :locked_by, :handler
13   - end
14   -
15   - scope :by_priority, lambda { order('priority ASC, run_at ASC') }
16   -
17   - before_save :set_default_run_at
18   -
19   - def self.set_delayed_job_table_name
20   - delayed_job_table_name = "#{::ActiveRecord::Base.table_name_prefix}delayed_jobs"
21   - self.table_name = delayed_job_table_name
22   - end
23   -
24   - self.set_delayed_job_table_name
25   -
26   - def self.ready_to_run(worker_name, max_run_time)
27   - where('(run_at <= ? AND (locked_at IS NULL OR locked_at < ?) OR locked_by = ?) AND failed_at IS NULL', db_time_now, db_time_now - max_run_time, worker_name)
28   - end
29   -
30   - def self.before_fork
31   - ::ActiveRecord::Base.clear_all_connections!
32   - end
33   -
34   - def self.after_fork
35   - ::ActiveRecord::Base.establish_connection
36   - end
37   -
38   - # When a worker is exiting, make sure we don't have any locked jobs.
39   - def self.clear_locks!(worker_name)
40   - where(:locked_by => worker_name).update_all(:locked_by => nil, :locked_at => nil)
41   - end
42   -
43   - def self.reserve(worker, max_run_time = Worker.max_run_time)
44   - # scope to filter to records that are "ready to run"
45   - ready_scope = self.ready_to_run(worker.name, max_run_time)
46   -
47   - # scope to filter to the single next eligible job
48   - ready_scope = ready_scope.where('priority >= ?', Worker.min_priority) if Worker.min_priority
49   - ready_scope = ready_scope.where('priority <= ?', Worker.max_priority) if Worker.max_priority
50   - ready_scope = ready_scope.where(:queue => Worker.queues) if Worker.queues.any?
51   - ready_scope = ready_scope.by_priority
52   -
53   - now = self.db_time_now
54   -
55   - # Optimizations for faster lookups on some common databases
56   - case self.connection.adapter_name
57   - when "PostgreSQL"
58   - # Custom SQL required for PostgreSQL because postgres does not support UPDATE...LIMIT
59   - # This locks the single record 'FOR UPDATE' in the subquery (http://www.postgresql.org/docs/9.0/static/sql-select.html#SQL-FOR-UPDATE-SHARE)
60   - # Note: active_record would attempt to generate UPDATE...LIMIT like sql for postgres if we use a .limit() filter, but it would not use
61   - # 'FOR UPDATE' and we would have many locking conflicts
62   - quoted_table_name = self.connection.quote_table_name(self.table_name)
63   - subquery_sql = ready_scope.limit(1).lock(true).select('id').to_sql
64   - reserved = self.find_by_sql(["UPDATE #{quoted_table_name} SET locked_at = ?, locked_by = ? WHERE id IN (#{subquery_sql}) RETURNING *", now, worker.name])
65   - reserved[0]
66   - when "MySQL", "Mysql2"
67   - # This works on MySQL and possibly some other DBs that support UPDATE...LIMIT. It uses separate queries to lock and return the job
68   - count = ready_scope.limit(1).update_all(:locked_at => now, :locked_by => worker.name)
69   - return nil if count == 0
70   - self.where(:locked_at => now, :locked_by => worker.name, :failed_at => nil).first
71   - when "MSSQL", "Teradata"
72   - # The MSSQL driver doesn't generate a limit clause when update_all is called directly
73   - subsubquery_sql = ready_scope.limit(1).to_sql
74   - # select("id") doesn't generate a subquery, so force a subquery
75   - subquery_sql = "SELECT id FROM (#{subsubquery_sql}) AS x"
76   - quoted_table_name = self.connection.quote_table_name(self.table_name)
77   - sql = ["UPDATE #{quoted_table_name} SET locked_at = ?, locked_by = ? WHERE id IN (#{subquery_sql})", now, worker.name]
78   - count = self.connection.execute(sanitize_sql(sql))
79   - return nil if count == 0
80   - # MSSQL JDBC doesn't support OUTPUT INSERTED.* for returning a result set, so query locked row
81   - self.where(:locked_at => now, :locked_by => worker.name, :failed_at => nil).first
82   - else
83   - # This is our old fashion, tried and true, but slower lookup
84   - ready_scope.limit(worker.read_ahead).detect do |job|
85   - count = ready_scope.where(:id => job.id).update_all(:locked_at => now, :locked_by => worker.name)
86   - count == 1 && job.reload
87   - end
88   - end
89   - end
90   -
91   - # Get the current time (GMT or local depending on DB)
92   - # Note: This does not ping the DB to get the time, so all your clients
93   - # must have syncronized clocks.
94   - def self.db_time_now
95   - if Time.zone
96   - Time.zone.now
97   - elsif ::ActiveRecord::Base.default_timezone == :utc
98   - Time.now.utc
99   - else
100   - Time.now
101   - end
102   - end
103   -
104   - def reload(*args)
105   - reset
106   - super
107   - end
108   - end
109   - end
110   - end
111   -end
vendor/plugins/delayed_job_active_record/lib/delayed_job_active_record.rb
... ... @@ -1,5 +0,0 @@
1   -require 'active_record'
2   -require 'delayed_job'
3   -require 'delayed/backend/active_record'
4   -
5   -Delayed::Worker.backend = :active_record
vendor/plugins/delayed_job_active_record/lib/generators/delayed_job/active_record_generator.rb
... ... @@ -1,22 +0,0 @@
1   -require 'generators/delayed_job/delayed_job_generator'
2   -require 'generators/delayed_job/next_migration_version'
3   -require 'rails/generators/migration'
4   -require 'rails/generators/active_record'
5   -
6   -# Extend the DelayedJobGenerator so that it creates an AR migration
7   -module DelayedJob
8   - class ActiveRecordGenerator < ::DelayedJobGenerator
9   - include Rails::Generators::Migration
10   - extend NextMigrationVersion
11   -
12   - self.source_paths << File.join(File.dirname(__FILE__), 'templates')
13   -
14   - def create_migration_file
15   - migration_template 'migration.rb', 'db/migrate/create_delayed_jobs.rb'
16   - end
17   -
18   - def self.next_migration_number dirname
19   - ActiveRecord::Generators::Base.next_migration_number dirname
20   - end
21   - end
22   -end
vendor/plugins/delayed_job_active_record/lib/generators/delayed_job/next_migration_version.rb
... ... @@ -1,14 +0,0 @@
1   -module DelayedJob
2   - module NextMigrationVersion
3   - # while methods have moved around this has been the implementation
4   - # since ActiveRecord 3.0
5   - def next_migration_number(dirname)
6   - next_migration_number = current_migration_number(dirname) + 1
7   - if ActiveRecord::Base.timestamped_migrations
8   - [Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % next_migration_number].max
9   - else
10   - "%.3d" % next_migration_number
11   - end
12   - end
13   - end
14   -end
vendor/plugins/delayed_job_active_record/lib/generators/delayed_job/templates/migration.rb
... ... @@ -1,22 +0,0 @@
1   -class CreateDelayedJobs < ActiveRecord::Migration
2   - def self.up
3   - create_table :delayed_jobs, :force => true do |table|
4   - table.integer :priority, :default => 0, :null => false # Allows some jobs to jump to the front of the queue
5   - table.integer :attempts, :default => 0, :null => false # Provides for retries, but still fail eventually.
6   - table.text :handler, :null => false # YAML-encoded string of the object that will do work
7   - table.text :last_error # reason for last failure (See Note below)
8   - table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future.
9   - table.datetime :locked_at # Set when a client is working on this object
10   - table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
11   - table.string :locked_by # Who is working on this object (if locked)
12   - table.string :queue # The name of the queue this job is in
13   - table.timestamps
14   - end
15   -
16   - add_index :delayed_jobs, [:priority, :run_at], :name => 'delayed_jobs_priority'
17   - end
18   -
19   - def self.down
20   - drop_table :delayed_jobs
21   - end
22   -end
vendor/plugins/delayed_job_active_record/lib/generators/delayed_job/templates/upgrade_migration.rb
... ... @@ -1,9 +0,0 @@
1   -class AddQueueToDelayedJobs < ActiveRecord::Migration
2   - def self.up
3   - add_column :delayed_jobs, :queue, :string
4   - end
5   -
6   - def self.down
7   - remove_column :delayed_jobs, :queue
8   - end
9   -end
vendor/plugins/delayed_job_active_record/lib/generators/delayed_job/upgrade_generator.rb
... ... @@ -1,22 +0,0 @@
1   -require 'generators/delayed_job/delayed_job_generator'
2   -require 'generators/delayed_job/next_migration_version'
3   -require 'rails/generators/migration'
4   -require 'rails/generators/active_record'
5   -
6   -# Extend the DelayedJobGenerator so that it creates an AR migration
7   -module DelayedJob
8   - class UpgradeGenerator < ::DelayedJobGenerator
9   - include Rails::Generators::Migration
10   - extend NextMigrationVersion
11   -
12   - self.source_paths << File.join(File.dirname(__FILE__), 'templates')
13   -
14   - def create_migration_file
15   - migration_template 'upgrade_migration.rb', 'db/migrate/add_queue_to_delayed_jobs.rb'
16   - end
17   -
18   - def self.next_migration_number dirname
19   - ActiveRecord::Generators::Base.next_migration_number dirname
20   - end
21   - end
22   -end
vendor/plugins/delayed_job_active_record/spec/database.yml
... ... @@ -1,14 +0,0 @@
1   -mysql:
2   - adapter: mysql
3   - database: delayed_job_test
4   - username: root
5   - encoding: utf8
6   -
7   -postgresql:
8   - adapter: postgresql
9   - database: delayed_job_test
10   - username: postgres
11   -
12   -sqlite3:
13   - adapter: sqlite3
14   - database: ":memory:"
vendor/plugins/delayed_job_active_record/spec/delayed/backend/active_record_spec.rb
... ... @@ -1,81 +0,0 @@
1   -require 'helper'
2   -require 'delayed/backend/active_record'
3   -
4   -describe Delayed::Backend::ActiveRecord::Job do
5   - it_behaves_like 'a delayed_job backend'
6   -
7   - context "db_time_now" do
8   - after do
9   - Time.zone = nil
10   - ActiveRecord::Base.default_timezone = :local
11   - end
12   -
13   - it "returns time in current time zone if set" do
14   - Time.zone = 'Eastern Time (US & Canada)'
15   - expect(%(EST EDT)).to include(Delayed::Job.db_time_now.zone)
16   - end
17   -
18   - it "returns UTC time if that is the AR default" do
19   - Time.zone = nil
20   - ActiveRecord::Base.default_timezone = :utc
21   - expect(Delayed::Backend::ActiveRecord::Job.db_time_now.zone).to eq 'UTC'
22   - end
23   -
24   - it "returns local time if that is the AR default" do
25   - Time.zone = 'Central Time (US & Canada)'
26   - ActiveRecord::Base.default_timezone = :local
27   - expect(%w(CST CDT)).to include(Delayed::Backend::ActiveRecord::Job.db_time_now.zone)
28   - end
29   - end
30   -
31   - describe "after_fork" do
32   - it "calls reconnect on the connection" do
33   - ActiveRecord::Base.should_receive(:establish_connection)
34   - Delayed::Backend::ActiveRecord::Job.after_fork
35   - end
36   - end
37   -
38   - describe "enqueue" do
39   - it "allows enqueue hook to modify job at DB level" do
40   - later = described_class.db_time_now + 20.minutes
41   - job = Delayed::Backend::ActiveRecord::Job.enqueue :payload_object => EnqueueJobMod.new
42   - expect(Delayed::Backend::ActiveRecord::Job.find(job.id).run_at).to be_within(1).of(later)
43   - end
44   - end
45   -
46   - if ::ActiveRecord::VERSION::MAJOR < 4 || defined?(::ActiveRecord::MassAssignmentSecurity)
47   - context "ActiveRecord::Base.send(:attr_accessible, nil)" do
48   - before do
49   - Delayed::Backend::ActiveRecord::Job.send(:attr_accessible, nil)
50   - end
51   -
52   - after do
53   - Delayed::Backend::ActiveRecord::Job.send(:attr_accessible, *Delayed::Backend::ActiveRecord::Job.new.attributes.keys)
54   - end
55   -
56   - it "is still accessible" do
57   - job = Delayed::Backend::ActiveRecord::Job.enqueue :payload_object => EnqueueJobMod.new
58   - expect(Delayed::Backend::ActiveRecord::Job.find(job.id).handler).to_not be_blank
59   - end
60   - end
61   - end
62   -
63   - context "ActiveRecord::Base.table_name_prefix" do
64   - it "when prefix is not set, use 'delayed_jobs' as table name" do
65   - ::ActiveRecord::Base.table_name_prefix = nil
66   - Delayed::Backend::ActiveRecord::Job.set_delayed_job_table_name
67   -
68   - expect(Delayed::Backend::ActiveRecord::Job.table_name).to eq 'delayed_jobs'
69   - end
70   -
71   - it "when prefix is set, prepend it before default table name" do
72   - ::ActiveRecord::Base.table_name_prefix = 'custom_'
73   - Delayed::Backend::ActiveRecord::Job.set_delayed_job_table_name
74   -
75   - expect(Delayed::Backend::ActiveRecord::Job.table_name).to eq 'custom_delayed_jobs'
76   -
77   - ::ActiveRecord::Base.table_name_prefix = nil
78   - Delayed::Backend::ActiveRecord::Job.set_delayed_job_table_name
79   - end
80   - end
81   -end
vendor/plugins/delayed_job_active_record/spec/delayed/serialization/active_record_spec.rb
... ... @@ -1,15 +0,0 @@
1   -require 'helper'
2   -
3   -describe ActiveRecord do
4   - it "loads classes with non-default primary key" do
5   - expect {
6   - YAML.load(Story.create.to_yaml)
7   - }.not_to raise_error
8   - end
9   -
10   - it "loads classes even if not in default scope" do
11   - expect {
12   - YAML.load(Story.create(:scoped => false).to_yaml)
13   - }.not_to raise_error
14   - end
15   -end
vendor/plugins/delayed_job_active_record/spec/helper.rb
... ... @@ -1,69 +0,0 @@
1   -require 'simplecov'
2   -require 'coveralls'
3   -
4   -SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
5   - SimpleCov::Formatter::HTMLFormatter,
6   - Coveralls::SimpleCov::Formatter
7   -]
8   -SimpleCov.start
9   -
10   -require 'logger'
11   -require 'rspec'
12   -
13   -begin
14   - require 'protected_attributes'
15   -rescue LoadError
16   -end
17   -require 'delayed_job_active_record'
18   -require 'delayed/backend/shared_spec'
19   -
20   -Delayed::Worker.logger = Logger.new('/tmp/dj.log')
21   -ENV['RAILS_ENV'] = 'test'
22   -
23   -db_adapter, gemfile = ENV["ADAPTER"], ENV["BUNDLE_GEMFILE"]
24   -db_adapter ||= gemfile && gemfile[%r(gemfiles/(.*?)/)] && $1
25   -db_adapter ||= 'sqlite3'
26   -
27   -config = YAML.load(File.read('spec/database.yml'))
28   -ActiveRecord::Base.establish_connection config[db_adapter]
29   -ActiveRecord::Base.logger = Delayed::Worker.logger
30   -ActiveRecord::Migration.verbose = false
31   -
32   -ActiveRecord::Schema.define do
33   - create_table :delayed_jobs, :force => true do |table|
34   - table.integer :priority, :default => 0
35   - table.integer :attempts, :default => 0
36   - table.text :handler
37   - table.text :last_error
38   - table.datetime :run_at
39   - table.datetime :locked_at
40   - table.datetime :failed_at
41   - table.string :locked_by
42   - table.string :queue
43   - table.timestamps
44   - end
45   -
46   - add_index :delayed_jobs, [:priority, :run_at], :name => 'delayed_jobs_priority'
47   -
48   - create_table :stories, :primary_key => :story_id, :force => true do |table|
49   - table.string :text
50   - table.boolean :scoped, :default => true
51   - end
52   -end
53   -
54   -# Purely useful for test cases...
55   -class Story < ActiveRecord::Base
56   - if ::ActiveRecord::VERSION::MAJOR < 4 && ActiveRecord::VERSION::MINOR < 2
57   - set_primary_key :story_id
58   - else
59   - self.primary_key = :story_id
60   - end
61   - def tell; text; end
62   - def whatever(n, _); tell*n; end
63   - default_scope { where(:scoped => true) }
64   -
65   - handle_asynchronously :whatever
66   -end
67   -
68   -# Add this directory so the ActiveSupport autoloading works
69   -ActiveSupport::Dependencies.autoload_paths << File.dirname(__FILE__)
vendor/plugins/monkey_patches/will_paginate_check_finder_sql/init.rb
... ... @@ -1,18 +0,0 @@
1   -# monkey patch to fix WillPaginate bug
2   -# this was solved in will_paginate 3.x.pre, then remove this patch when upgrade to it
3   -#
4   -# http://sod.lighthouseapp.com/projects/17958/tickets/120-paginate-association-with-finder_sql-raises-typeerror
5   -require 'will_paginate'
6   -
7   -WillPaginate::Finder::ClassMethods.module_eval do
8   - def paginate_with_finder_sql(*args)
9   - if respond_to?(:proxy_reflection) && !proxy_reflection.options[:finder_sql].nil?
10   - # note: paginate_by_sql ignores the blocks. So don't pass the block
11   - paginate_by_sql(@finder_sql, args.extract_options!)
12   - else
13   - paginate_without_finder_sql(*args)
14   - end
15   - end
16   - # patch to deal with the custom_sql scenario
17   - alias_method_chain :paginate, :finder_sql
18   -end
vendor/plugins/pothoven-attachment_fu/CHANGELOG
... ... @@ -1,84 +0,0 @@
1   -* Aug 22, 2013 *
2   -* Added cache-control header option and Ruby 1.9 fix for S3 from tricycle
3   -
4   -* Aug 21, 2013 *
5   -* Added S3 :encrypted_storage option support from cschulte22
6   -
7   -* Jul 5, 2013
8   -* Pull in changes from lchimonji10 to reformat README to RDoc format
9   -
10   -* Apr 10, 2013 *
11   -* Ruby 2 compatibility fix
12   -* Removed some lingering occurrences of RAILS_ROOT and RAILS_ENV
13   -* clean up of gemspec file
14   -* no longer package unnecessary files like the test files
15   -
16   -* Mar 12, 2013 *
17   -* Pull in changes from https://github.com/aalong/attachment_fu to use Ruby 1.9.2 Tempfile naming strategy to fix conflicts with Sprockets (see https://github.com/aalong/attachment_fu/commit/938ec3b8597fbf82b1de8c98de12c4688463450a)
18   -
19   -* Feb 19, 2013 *
20   -* Pull in changes from https://github.com/itkin/attachment_fu fork to fix mini magick
21   -
22   -* Nov 15, 2012 *
23   -* Removed 'crop:' option as already included when prefixing geometry with a 'c'. Add note to docs.
24   -* Added option to sharpen resized images ':sharpen_on_resize'
25   -
26   -* Oct 26, 2012 *
27   -* Merged with https://github.com/tdd/attachment_fu fork to include GEM support for use in Rails 3.2, and bumped version to 3.2.x to indicate Rails 3.2 support.
28   -
29   -* Oct 25, 2012 *
30   -* Fix to support Ruby 1.9.3
31   -* Image cropping support (append 'crop:' to desired file size when resizing)
32   -
33   -* Mar 15, 2010 *
34   -* Added a symbol syntax for parent-type-based size spec: calls the corresponding method on the current asset instance to
35   - get a Hash of required thumbnails. Lets us dynamically specify what would otherwise be hard-coded, which is useful
36   - when the set of thumbnails for a given parent type varies depending on the usage context.
37   -
38   -* Aug 6, 2009 *
39   -* JPEG quality control finalized across processors (although CoreImage applies it in a rather fuzzy-logic way), with tests.
40   -
41   -* Aug 4, 2009 *
42   -* Supports the :aspect/'!' geometry flag in all processors
43   - (thanks to http://www.deepcalm.com/writing/cropped-thumbnails-in-attachment_fu-using-imagescience)
44   -* JPEG quality control on thumbnailing/resizing (still buggy on Rmagick/MiniMagick though).
45   -* Moves from GIF to PNG regardless of the source file extension's case (used to require lowercase)
46   -* Auto-orients image (if EXIF suggests it) prior to processing with RMagickProcessor
47   -* Fixes non-image upload tests (both regular files and Merb files)
48   -* Fixes obsolete failures on RMagick tests (aspect_ratio tested but not initialized anymore due to new callback architecture
49   -
50   -* Apr 17 2008 *
51   -* amazon_s3.yml is now passed through ERB before being passed to AWS::S3 [François Beausoleil]
52   -
53   -* Mar 22 2008 *
54   -* Some tweaks to support Rails 2.0 and Rails 2.1 due to ActiveSupport::Callback changes.
55   - Thanks to http://blog.methodmissing.com/2008/1/19/edge-callback-refactorings-attachment_fu/
56   -
57   -* Feb. 26, 2008 *
58   -* remove breakpoint from test_helper, makes test suite crazy (at least Rails 2+) [Rob Sanheim]
59   -* make S3 test really optional [Rob Sanheim]
60   -
61   -* Nov 27, 2007 *
62   -* Handle properly ImageScience thumbnails resized from a gif file [Matt Aimonetti]
63   -* Save thumbnails file size properly when using ImageScience [Matt Aimonetti]
64   -* fixed s3 config file loading with latest versions of Rails [Matt Aimonetti]
65   -
66   -* April 2, 2007 *
67   -
68   -* don't copy the #full_filename to the default #temp_paths array if it doesn't exist
69   -* add default ID partitioning for attachments
70   -* add #binmode call to Tempfile (note: ruby should be doing this!) [Eric Beland]
71   -* Check for current type of :thumbnails option.
72   -* allow customization of the S3 configuration file path with the :s3_config_path option.
73   -* Don't try to remove thumbnails if there aren't any. Closes #3 [ben stiglitz]
74   -
75   -* BC * (before changelog)
76   -
77   -* add default #temp_paths entry [mattly]
78   -* add MiniMagick support to attachment_fu [Isacc]
79   -* update #destroy_file to clear out any empty directories too [carlivar]
80   -* fix references to S3Backend module [Hunter Hillegas]
81   -* make #current_data public with db_file and s3 backends [ebryn]
82   -* oops, actually svn add the files for s3 backend. [Jeffrey Hardy]
83   -* experimental s3 support, egad, no tests.... [Jeffrey Hardy]
84   -* doh, fix a few bad references to ActsAsAttachment [sixty4bit]
vendor/plugins/pothoven-attachment_fu/Gemfile
... ... @@ -1,13 +0,0 @@
1   -source 'http://rubygems.org'
2   -
3   -
4   -group :test, :development do
5   - gem 'rails', '~> 3.2'
6   - gem 'sqlite3'
7   - gem 'pothoven-attachment_fu', :path => '.'
8   - gem 'rmagick'
9   - gem 'core_image'
10   - gem 'mini_magick'
11   - gem 'aws-s3', :require => 'aws/s3'
12   - gem 'test-unit'
13   -end
vendor/plugins/pothoven-attachment_fu/Gemfile.lock
... ... @@ -1,109 +0,0 @@
1   -PATH
2   - remote: .
3   - specs:
4   - pothoven-attachment_fu (3.2.10)
5   -
6   -GEM
7   - remote: http://rubygems.org/
8   - specs:
9   - actionmailer (3.2.14)
10   - actionpack (= 3.2.14)
11   - mail (~> 2.5.4)
12   - actionpack (3.2.14)
13   - activemodel (= 3.2.14)
14   - activesupport (= 3.2.14)
15   - builder (~> 3.0.0)
16   - erubis (~> 2.7.0)
17   - journey (~> 1.0.4)
18   - rack (~> 1.4.5)
19   - rack-cache (~> 1.2)
20   - rack-test (~> 0.6.1)
21   - sprockets (~> 2.2.1)
22   - activemodel (3.2.14)
23   - activesupport (= 3.2.14)
24   - builder (~> 3.0.0)
25   - activerecord (3.2.14)
26   - activemodel (= 3.2.14)
27   - activesupport (= 3.2.14)
28   - arel (~> 3.0.2)
29   - tzinfo (~> 0.3.29)
30   - activeresource (3.2.14)
31   - activemodel (= 3.2.14)
32   - activesupport (= 3.2.14)
33   - activesupport (3.2.14)
34   - i18n (~> 0.6, >= 0.6.4)
35   - multi_json (~> 1.0)
36   - arel (3.0.2)
37   - aws-s3 (0.6.3)
38   - builder
39   - mime-types
40   - xml-simple
41   - builder (3.0.4)
42   - core_image (0.0.3.5)
43   - erubis (2.7.0)
44   - hike (1.2.3)
45   - i18n (0.6.5)
46   - journey (1.0.4)
47   - json (1.8.0)
48   - mail (2.5.4)
49   - mime-types (~> 1.16)
50   - treetop (~> 1.4.8)
51   - mime-types (1.24)
52   - mini_magick (3.6.0)
53   - subexec (~> 0.2.1)
54   - multi_json (1.7.9)
55   - polyglot (0.3.3)
56   - rack (1.4.5)
57   - rack-cache (1.2)
58   - rack (>= 0.4)
59   - rack-ssl (1.3.3)
60   - rack
61   - rack-test (0.6.2)
62   - rack (>= 1.0)
63   - rails (3.2.14)
64   - actionmailer (= 3.2.14)
65   - actionpack (= 3.2.14)
66   - activerecord (= 3.2.14)
67   - activeresource (= 3.2.14)
68   - activesupport (= 3.2.14)
69   - bundler (~> 1.0)
70   - railties (= 3.2.14)
71   - railties (3.2.14)
72   - actionpack (= 3.2.14)
73   - activesupport (= 3.2.14)
74   - rack-ssl (~> 1.3.2)
75   - rake (>= 0.8.7)
76   - rdoc (~> 3.4)
77   - thor (>= 0.14.6, < 2.0)
78   - rake (10.1.0)
79   - rdoc (3.12.2)
80   - json (~> 1.4)
81   - rmagick (2.13.2)
82   - sprockets (2.2.2)
83   - hike (~> 1.2)
84   - multi_json (~> 1.0)
85   - rack (~> 1.0)
86   - tilt (~> 1.1, != 1.3.0)
87   - sqlite3 (1.3.8)
88   - subexec (0.2.3)
89   - test-unit (2.5.5)
90   - thor (0.18.1)
91   - tilt (1.4.1)
92   - treetop (1.4.15)
93   - polyglot
94   - polyglot (>= 0.3.1)
95   - tzinfo (0.3.37)
96   - xml-simple (1.1.2)
97   -
98   -PLATFORMS
99   - ruby
100   -
101   -DEPENDENCIES
102   - aws-s3
103   - core_image
104   - mini_magick
105   - pothoven-attachment_fu!
106   - rails (~> 3.2)
107   - rmagick
108   - sqlite3
109   - test-unit
vendor/plugins/pothoven-attachment_fu/LICENSE
... ... @@ -1,20 +0,0 @@
1   -Copyright (c) 2009 rick olson
2   -
3   -Permission is hereby granted, free of charge, to any person obtaining
4   -a copy of this software and associated documentation files (the
5   -"Software"), to deal in the Software without restriction, including
6   -without limitation the rights to use, copy, modify, merge, publish,
7   -distribute, sublicense, and/or sell copies of the Software, and to
8   -permit persons to whom the Software is furnished to do so, subject to
9   -the following conditions:
10   -
11   -The above copyright notice and this permission notice shall be
12   -included in all copies or substantial portions of the Software.
13   -
14   -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15   -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16   -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17   -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18   -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19   -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20   -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
vendor/plugins/pothoven-attachment_fu/README
... ... @@ -1,193 +0,0 @@
1   -attachment-fu
2   -=============
3   -
4   -attachment_fu is a plugin by Rick Olson (aka technoweenie <http://techno-weenie.net>) and is the successor to acts_as_attachment. To get a basic run-through of its capabilities, check out Mike Clark's tutorial <http://clarkware.com/cgi/blosxom/2007/02/24#FileUploadFu>.
5   -
6   -
7   -attachment_fu functionality
8   -===========================
9   -
10   -attachment_fu facilitates file uploads in Ruby on Rails. There are a few storage options for the actual file data, but the plugin always at a minimum stores metadata for each file in the database.
11   -
12   -There are four storage options for files uploaded through attachment_fu:
13   - File system
14   - Database file
15   - Amazon S3
16   - Rackspace (Mosso) Cloud Files
17   -
18   -Each method of storage many options associated with it that will be covered in the following section. Something to note, however, is that the Amazon S3 storage requires you to modify config/amazon_s3.yml, the Rackspace Cloud Files storage requires you to modify config/rackspace_cloudfiles.yml, and the Database file storage requires an extra table.
19   -
20   -
21   -attachment_fu models
22   -====================
23   -
24   -For all three of these storage options a table of metadata is required. This table will contain information about the file (hence the 'meta') and its location. This table has no restrictions on naming, unlike the extra table required for database storage, which must have a table name of db_files (and by convention a model of DbFile).
25   -
26   -In the model there are two methods made available by this plugins: has_attachment and validates_as_attachment.
27   -
28   -has_attachment(options = {})
29   - This method accepts the options in a hash:
30   - :content_type # Allowed content types.
31   - # Allows all by default. Use :image to allow all standard image types.
32   - :min_size # Minimum size allowed.
33   - # 1 byte is the default.
34   - :max_size # Maximum size allowed.
35   - # 1.megabyte is the default.
36   - :size # Range of sizes allowed.
37   - # (1..1.megabyte) is the default. This overrides the :min_size and :max_size options.
38   - :resize_to # Used by RMagick to resize images.
39   - # Pass either an array of width/height, or a geometry string.
40   - :thumbnails # Specifies a set of thumbnails to generate.
41   - # This accepts a hash of filename suffixes and RMagick resizing options.
42   - # This option need only be included if you want thumbnailing.
43   - :thumbnail_class # Set which model class to use for thumbnails.
44   - # This current attachment class is used by default.
45   - :path_prefix # Path to store the uploaded files in.
46   - # Uses public/#{table_name} by default for the filesystem, and just #{table_name} for the S3 and Cloud Files backend.
47   - # Setting this sets the :storage to :file_system.
48   - :partition # Whether to partiton files in directories like /0000/0001/image.jpg. Default is true. Only applicable to the :file_system backend.
49   - :storage # Specifies the storage system to use..
50   - # Defaults to :db_file. Options are :file_system, :db_file, :s3, and :cloud_files.
51   - :cloudfront # If using S3 for storage, this option allows for serving the files via Amazon CloudFront.
52   - # Defaults to false.
53   - :processor # Sets the image processor to use for resizing of the attached image.
54   - # Options include ImageScience, Rmagick, and MiniMagick. Default is whatever is installed.
55   - :uuid_primary_key # If your model's primary key is a 128-bit UUID in hexadecimal format, then set this to true.
56   - :association_options # attachment_fu automatically defines associations with thumbnails with has_many and belongs_to. If there are any additional options that you want to pass to these methods, then specify them here.
57   -
58   -
59   - Examples:
60   - has_attachment :max_size => 1.kilobyte
61   - has_attachment :size => 1.megabyte..2.megabytes
62   - has_attachment :content_type => 'application/pdf'
63   - has_attachment :content_type => ['application/pdf', 'application/msword', 'text/plain']
64   - has_attachment :content_type => :image, :resize_to => [50,50]
65   - has_attachment :content_type => ['application/pdf', :image], :resize_to => 'x50'
66   - has_attachment :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }
67   - has_attachment :storage => :file_system, :path_prefix => 'public/files'
68   - has_attachment :storage => :file_system, :path_prefix => 'public/files',
69   - :content_type => :image, :resize_to => [50,50], :partition => false
70   - has_attachment :storage => :file_system, :path_prefix => 'public/files',
71   - :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }
72   - has_attachment :storage => :s3
73   - has_attachment :store => :s3, :cloudfront => true
74   - has_attachment :storage => :cloud_files
75   -
76   -validates_as_attachment
77   - This method prevents files outside of the valid range (:min_size to :max_size, or the :size range) from being saved. It does not however, halt the upload of such files. They will be uploaded into memory regardless of size before validation.
78   -
79   - Example:
80   - validates_as_attachment
81   -
82   -
83   -attachment_fu migrations
84   -========================
85   -
86   -Fields for attachment_fu metadata tables...
87   - in general:
88   - size, :integer # file size in bytes
89   - content_type, :string # mime type, ex: application/mp3
90   - filename, :string # sanitized filename
91   - that reference images:
92   - height, :integer # in pixels
93   - width, :integer # in pixels
94   - that reference images that will be thumbnailed:
95   - parent_id, :integer # id of parent image (on the same table, a self-referencing foreign-key).
96   - # Only populated if the current object is a thumbnail.
97   - thumbnail, :string # the 'type' of thumbnail this attachment record describes.
98   - # Only populated if the current object is a thumbnail.
99   - # Usage:
100   - # [ In Model 'Avatar' ]
101   - # has_attachment :content_type => :image,
102   - # :storage => :file_system,
103   - # :max_size => 500.kilobytes,
104   - # :resize_to => '320x200>',
105   - # :thumbnails => { :small => '10x10>',
106   - # :thumb => '100x100>' }
107   - # [ Elsewhere ]
108   - # @user.avatar.thumbnails.first.thumbnail #=> 'small'
109   - that reference files stored in the database (:db_file):
110   - db_file_id, :integer # id of the file in the database (foreign key)
111   -
112   -Field for attachment_fu db_files table:
113   - data, :binary # binary file data, for use in database file storage
114   -
115   -
116   -attachment_fu views
117   -===================
118   -
119   -There are two main views tasks that will be directly affected by attachment_fu: upload forms and displaying uploaded images.
120   -
121   -There are two parts of the upload form that differ from typical usage.
122   - 1. Include ':multipart => true' in the html options of the form_for tag.
123   - Example:
124   - <% form_for(:attachment_metadata, :url => { :action => "create" }, :html => { :multipart => true }) do |form| %>
125   -
126   - 2. Use the file_field helper with :uploaded_data as the field name.
127   - Example:
128   - <%= form.file_field :uploaded_data %>
129   -
130   -Displaying uploaded images is made easy by the public_filename method of the ActiveRecord attachment objects using file system, s3, and Cloud Files storage.
131   -
132   -public_filename(thumbnail = nil)
133   - Returns the public path to the file. If a thumbnail prefix is specified it will return the public file path to the corresponding thumbnail.
134   - Examples:
135   - attachment_obj.public_filename #=> /attachments/2/file.jpg
136   - attachment_obj.public_filename(:thumb) #=> /attachments/2/file_thumb.jpg
137   - attachment_obj.public_filename(:small) #=> /attachments/2/file_small.jpg
138   -
139   -When serving files from database storage, doing more than simply downloading the file is beyond the scope of this document.
140   -
141   -
142   -attachment_fu controllers
143   -=========================
144   -
145   -There are two considerations to take into account when using attachment_fu in controllers.
146   -
147   -The first is when the files have no publicly accessible path and need to be downloaded through an action.
148   -
149   -Example:
150   - def readme
151   - send_file '/path/to/readme.txt', :type => 'plain/text', :disposition => 'inline'
152   - end
153   -
154   -See the possible values for send_file for reference.
155   -
156   -
157   -The second is when saving the file when submitted from a form.
158   -Example in view:
159   - <%= form.file_field :attachable, :uploaded_data %>
160   -
161   -Example in controller:
162   - def create
163   - @attachable_file = AttachmentMetadataModel.new(params[:attachable])
164   - if @attachable_file.save
165   - flash[:notice] = 'Attachment was successfully created.'
166   - redirect_to attachable_url(@attachable_file)
167   - else
168   - render :action => :new
169   - end
170   - end
171   -
172   -attachement_fu scripting
173   -====================================
174   -
175   -You may wish to import a large number of images or attachments.
176   -The following example shows how to upload a file from a script.
177   -
178   -#!/usr/bin/env ./script/runner
179   -
180   -# required to use ActionController::TestUploadedFile
181   -require 'action_controller'
182   -require 'action_controller/test_process.rb'
183   -
184   -path = "./public/images/x.jpg"
185   -
186   -# mimetype is a string like "image/jpeg". One way to get the mimetype for a given file on a UNIX system
187   -# mimetype = `file -ib #{path}`.gsub(/\n/,"")
188   -
189   -mimetype = "image/jpeg"
190   -
191   -# This will "upload" the file at path and create the new model.
192   -@attachable = AttachmentMetadataModel.new(:uploaded_data => ActionController::TestUploadedFile.new(path, mimetype))
193   -@attachable.save
vendor/plugins/pothoven-attachment_fu/README.rdoc
... ... @@ -1,352 +0,0 @@
1   -= attachment-fu
2   -
3   -attachment_fu is a plugin by Rick Olson (aka technoweenie
4   -http://techno-weenie.net) and is the successor to acts_as_attachment. To get a
5   -basic run-through of its capabilities, check out {Mike Clark's
6   -tutorial}[http://clarkware.com/cgi/blosxom/2007/02/24#FileUploadFu].
7   -
8   -= attachment_fu functionality
9   -
10   -attachment_fu facilitates file uploads in Ruby on Rails. There are a few
11   -storage options for the actual file data, but the plugin always at a minimum
12   -stores metadata for each file in the database.
13   -
14   -There are four storage options for files uploaded through attachment_fu:
15   -
16   -* File system
17   -* Database file
18   -* Amazon S3
19   -* Rackspace (Mosso) Cloud Files
20   -
21   -Each method of storage many options associated with it that will be covered in
22   -the following section. Something to note, however, is that the Amazon S3 storage
23   -requires you to modify +config/amazon_s3.yml+, the Rackspace Cloud Files storage
24   -requires you to modify +config/rackspace_cloudfiles.yml+, and the Database file
25   -storage requires an extra table.
26   -
27   -= attachment_fu models
28   -
29   -For all three of these storage options a table of metadata is required. This
30   -table will contain information about the file (hence the 'meta') and its
31   -location. This table has no restrictions on naming, unlike the extra table
32   -required for database storage, which must have a table name of +db_files+ (and
33   -by convention a model of +DbFile+).
34   -
35   -Two methods are available to models: +has_attachment+ and
36   -+validates_as_attachment+.
37   -
38   -== has_attachment(options = {})
39   -
40   -This method accepts the options in a hash:
41   -
42   -[:content_type]
43   - Allowed content types.
44   -
45   - By default, all content types are allowed. Use +:image+ to allow all
46   - standard image types.
47   -
48   -[:min_size]
49   - Minimum file size.
50   -
51   - By default, set to +1.byte+.
52   -
53   -[:max_size]
54   - Maximum file size.
55   -
56   - By default, set to +1.megabyte+.
57   -
58   -[:size]
59   - Minimum and maximum file size.
60   -
61   - By default, set to +1..1.megabyte+. Overrides +:min_size+ and
62   - +:max_size+.
63   -
64   -[:resize_to]
65   - Used by RMagick.
66   -
67   - Tells RMagick how to resize images. Pass either an array specifying
68   - width and height or a geometry string. Prefixing the geometry string
69   - with a 'c' will crop the image to the specified size.
70   -
71   -[:sharpen_on_resize]
72   - Used by RMagick.
73   -
74   - If set to true, images are sharpened after being resized.
75   -
76   -[:thumbnails]
77   - A set of thumbnails to generate.
78   -
79   - This accepts a hash of filename suffixes and RMagick resizing options. This
80   - option need only be included if you want thumbnailing.
81   -
82   - If you have a polymorphic parent relationship, you can provide
83   - parent-type-specific thumbnail settings by using a pair with the type string
84   - as key and a Hash of thumbnail definitions, or a method symbol, as value.
85   - The method symbol will call the named method in order to get a
86   - dynamically-built Hash of thumbnail definitions, which gives you full
87   - flexibility. AttachmentFu automatically detects your first polymorphic
88   - +belongs_to+ relationship.
89   -
90   -[:thumbnail_class]
91   - Which model class to use for thumbnails.
92   -
93   - By default, the current attachment class is used.
94   -
95   -[:jpeg_quality]
96   - JPEG quality settings for thumbnail resizes.
97   -
98   - Arguments can be in multiple formats:
99   -
100   - * Integer from 0 (basically crap) to 100 (basically lossless, fat files).
101   -
102   - * When relying on tdd-image_science, you can also use one of its +JPEG_xxx+
103   - constants for predefined ratios/settings.
104   -
105   - * You can also use a Hash, with keys being either thumbnail symbols (I
106   - repeat: _symbols_) or surface boundaries. A surface boundary is a string
107   - starting with either '<' or '>=', followed by a number of pixels. This
108   - lets you specify per-thumbnail or per-general-thumbnail-"size" JPEG
109   - qualities. (which can be useful when you have a _lot_ of thumbnail
110   - options). Surface example: <code>{'<2000' => 90, '>=2000' => 75}</code>.
111   -
112   - Defaults vary depending on the processor (ImageScience: 100%,
113   - Rmagick/MiniMagick/Gd2: 75%, CoreImage: auto-adjust). Note that only
114   - tdd-image_science (available from GitHub) currently supports explicit JPEG
115   - quality; the default image_science currently forces 100%.
116   -
117   -[:path_prefix]
118   - Path to store the uploaded files in. Uses <code>public/#{table_name}</code>
119   - by default for the filesystem, and just <code>#{table_name}</code> for the
120   - S3 and Cloud Files backend. Setting this sets the +:storage+ to
121   - +:file_system+.
122   -
123   -[:partition]
124   - Whether to partiton files in directories like +/0000/0001/image.jpg+.
125   - Default is true. Only applicable to the +:file_system+ backend.
126   -
127   -[:storage]
128   - Specifies the storage system to use. Defaults to +:db_file+. Options are
129   - +:file_system+, +:db_file+, +:s3+, and +:cloud_files+.
130   -
131   -[:cloudfront]
132   - If using S3 for storage, this option allows for serving the files via Amazon
133   - CloudFront. Defaults to false.
134   -
135   -[:processor]
136   - Sets the image processor to use for resizing of the attached image. Options
137   - include ImageScience, Rmagick, MiniMagick, Gd2 and CoreImage. Default is
138   - whatever is installed.
139   -
140   -[:uuid_primary_key]
141   - If your model's primary key is a 128-bit UUID in hexadecimal format, then
142   - set this to true.
143   -
144   -[:association_options]
145   - attachment_fu automatically defines associations with thumbnails with
146   - +has_many+ and +belongs_to+. If there are any additional options that you
147   - want to pass to these methods, then specify them here.
148   -
149   -Examples:
150   -
151   - has_attachment(content_type: 'application/pdf')
152   - has_attachment(
153   - content_type: ['application/pdf', 'application/msword', 'text/plain']
154   - )
155   - has_attachment(content_type: ['application/pdf', :image], resize_to: 'x50')
156   - has_attachment(content_type: :image, resize_to: [50,50])
157   - has_attachment(max_size: 1.kilobyte)
158   - has_attachment(size: 1.megabyte..2.megabytes)
159   - has_attachment(storage: :cloud_files)
160   - has_attachment(storage: :file_system, path_prefix: 'public/files')
161   - has_attachment(
162   - storage: :file_system,
163   - path_prefix: 'public/files',
164   - content_type: :image,
165   - resize_to: [50, 50],
166   - partition: false
167   - )
168   - has_attachment(
169   - storage: :file_system,
170   - path_prefix: 'public/files',
171   - thumbnails: {thumb: [50, 50], geometry: 'x50'}
172   - )
173   - has_attachment(storage: :s3)
174   - has_attachment(store: :s3, cloudfront: true)
175   - has_attachment(thumbnails: {thumb: [50, 50], geometry: 'x50'})
176   -
177   - # Let's say we have a polymorphic belongs_to, e.g. called 'imageable', where
178   - # imageable_type (or whatever the :foreign_type option was set to) can be,
179   - # among other things, 'Product', 'User' or 'Editorial', each of which should
180   - # have extra thumbnails:
181   -
182   - has_attachment(thumbnails: {
183   - editorials: {fullsize: '150x100>'},
184   - geometry: 'x50',
185   - products: {large_thumb: '169x169!', zoomed: '500x500>'},
186   - thumb: [50, 50],
187   - users: {avatar: '64x64!'}
188   - })
189   -
190   - # JPEG qualities…
191   -
192   - has_attachment(jpeg_quality: 75)
193   - has_attachment(jpeg_quality: 80 | ImageScience::JPEG_PROGRESSIVE)
194   - has_attachment(
195   - thumbnails: {thumb: [50, 50], geometry: 'x50'},
196   - jpeg_quality: {'<2000' => 90, '>=2000' => 75}
197   - )
198   - has_attachment(
199   - thumbnails: {thumb: [50, 50], geometry: 'x50'},
200   - jpeg_quality: {nil => 75, thumb: 90, geometry: 90}
201   - )
202   -
203   -== validates_as_attachment
204   -
205   -This method prevents files outside of the valid range (+:min_size+ to
206   -+:max_size+, or the +:size+ range) from being saved. It does not however, halt
207   -the upload of such files. They will be uploaded into memory regardless of size
208   -before validation.
209   -
210   -To perform this validation, simply add +validates_as_attachment+ to your model.
211   -
212   -= attachment_fu migrations
213   -
214   -Fields for attachment_fu metadata tables…
215   -
216   -In general:
217   -
218   - size, :integer # file size in bytes
219   - content_type, :string # mime type, ex: application/mp3
220   - filename, :string # sanitized filename
221   -
222   -That reference images:
223   -
224   - height, :integer # in pixels
225   - width, :integer # in pixels
226   -
227   -That reference images that will be thumbnailed:
228   -
229   - parent_id, :integer # id of parent image (on the same table, a
230   - # self-referencing foreign-key). Only populated if
231   - # the current object is a thumbnail.
232   - thumbnail, :string # The type of thumbnail this attachment record
233   - # describes. Only populated if the current object is
234   - # a thumbnail. Example:
235   - #
236   - # (In Model 'Avatar')
237   - # has_attachment(
238   - # :content_type => :image,
239   - # :storage => :file_system,
240   - # :max_size => 500.kilobytes,
241   - # :resize_to => '320x200>',
242   - # :thumbnails => {
243   - # :small => '10x10>',
244   - # :thumb => '100x100>'
245   - # }
246   - # )
247   - #
248   - # (Elsewhere)
249   - # @user.avatar.thumbnails.first.thumbnail # => 'small'
250   - #
251   - db_file_id, :integer # ID of the file in the database (foreign key) that
252   - # reference files stored in the database (:db_file).
253   -
254   -Field for attachment_fu +db_files+ table:
255   -
256   - data, :binary # binary file data, for use in database file storage
257   -
258   -= attachment_fu views
259   -
260   -There are two main views tasks that will be directly affected by attachment_fu:
261   -upload forms and displaying uploaded images.
262   -
263   -There are two parts of the upload form that differ from typical usage.
264   -
265   -1. Include <code>multipart: true</code> in the html options of the +form_for+
266   - tag. Example:
267   -
268   - <%=
269   - form_for(
270   - :attachment_metadata,
271   - url: {action: "create"},
272   - html: {multipart: true}
273   - ) do |form|
274   - %>
275   -
276   -2. Use the +file_field+ helper with +:uploaded_data+ as the field name. Example:
277   -
278   - <%= form.file_field(:uploaded_data) %>
279   -
280   -Displaying uploaded images is made easy by the +public_filename+ method of the
281   -ActiveRecord attachment objects using file system, s3, and Cloud Files storage.
282   -
283   -== public_filename(thumbnail = nil)
284   -
285   -Returns the public path to the file. If a thumbnail prefix is specified it will
286   -return the public file path to the corresponding thumbnail. Examples:
287   -
288   - attachment_obj.public_filename #=> /attachments/2/file.jpg
289   - attachment_obj.public_filename(:thumb) #=> /attachments/2/file_thumb.jpg
290   - attachment_obj.public_filename(:small) #=> /attachments/2/file_small.jpg
291   -
292   -When serving files from database storage, doing more than simply downloading the
293   -file is beyond the scope of this document.
294   -
295   -= attachment_fu controllers
296   -
297   -There are two considerations to take into account when using attachment_fu in
298   -controllers.
299   -
300   -The first is when the files have no publicly accessible path and need to be
301   -downloaded through an action. Example:
302   -
303   - def readme
304   - send_file(
305   - '/path/to/readme.txt',
306   - type: 'plain/text',
307   - disposition: 'inline'
308   - )
309   - end
310   -
311   -See the possible values for +send_file+ for reference.
312   -
313   -The second is when saving the file when submitted from a form. Example:
314   -
315   -In a view:
316   -
317   - <%= form.file_field(:attachable, :uploaded_data) %>
318   -
319   -In a controller:
320   -
321   - def create
322   - @attachable_file = AttachmentMetadataModel.new(params[:attachable])
323   - if @attachable_file.save
324   - flash[:notice] = 'Attachment was successfully created.'
325   - redirect_to(attachable_url(@attachable_file))
326   - else
327   - redirect_to(action: 'new')
328   - end
329   - end
330   -
331   -= attachment_fu scripting
332   -
333   -You may wish to import a large number of images or attachments. The following
334   -example shows how to upload a file from a script.
335   -
336   - #!/usr/bin/env ./script/runner
337   -
338   - # required to use ActionController::TestUploadedFile
339   - require 'action_controller'
340   - require 'action_controller/test_process.rb'
341   -
342   - path = "./public/images/x.jpg"
343   -
344   - # `mimetype` is a string like "image/jpeg". One way to get the mimetype for
345   - # a given file on a UNIX system: mimetype = `file -ib #{path}`.gsub(/\n/,"")
346   - mimetype = "image/jpeg"
347   -
348   - # This will "upload" the file at path and create the new model.
349   - @attachable = AttachmentMetadataModel.new(
350   - uploaded_data: ActionController::TestUploadedFile.new(path, mimetype)
351   - )
352   - @attachable.save
vendor/plugins/pothoven-attachment_fu/Rakefile
... ... @@ -1,22 +0,0 @@
1   -require 'rake'
2   -require 'rake/testtask'
3   -require 'rdoc/task'
4   -
5   -desc 'Default: run unit tests.'
6   -task :default => :test
7   -
8   -desc 'Test the attachment_fu plugin.'
9   -Rake::TestTask.new(:test) do |t|
10   - t.libs << 'lib'
11   - t.pattern = 'test/**/*_test.rb'
12   - t.verbose = true
13   -end
14   -
15   -desc 'Generate documentation for the attachment_fu plugin.'
16   -Rake::RDocTask.new(:rdoc) do |rdoc|
17   - rdoc.rdoc_dir = 'rdoc'
18   - rdoc.title = 'ActsAsAttachment'
19   - rdoc.options << '--line-numbers --inline-source'
20   - rdoc.rdoc_files.include('README.rdoc')
21   - rdoc.rdoc_files.include('lib/**/*.rb')
22   -end
vendor/plugins/pothoven-attachment_fu/amazon_s3.yml.tpl
... ... @@ -1,17 +0,0 @@
1   -development:
2   - bucket_name: appname_development
3   - access_key_id:
4   - secret_access_key:
5   - distribution_domain: XXXX.cloudfront.net
6   -
7   -test:
8   - bucket_name: appname_test
9   - access_key_id:
10   - secret_access_key:
11   - distribution_domain: XXXX.cloudfront.net
12   -
13   -production:
14   - bucket_name: appname
15   - access_key_id:
16   - secret_access_key:
17   - distribution_domain: XXXX.cloudfront.net
vendor/plugins/pothoven-attachment_fu/attachment_fu.gemspec
... ... @@ -1,23 +0,0 @@
1   -# -*- encoding: utf-8 -*-
2   -
3   -Gem::Specification.new do |s|
4   - s.name = %q{pothoven-attachment_fu}
5   - s.authors = ["Rick Olson", "Steven Pothoven"]
6   - s.summary = %q{attachment_fu as a gem}
7   - s.description = %q{This is a fork of Rick Olson's attachment_fu adding Ruby 1.9 and Rails 3.2 support as well as some other enhancements.}
8   - s.email = %q{steven@pothoven.net}
9   - s.homepage = %q{http://github.com/pothoven/attachment_fu}
10   - s.version = "3.2.10"
11   - s.date = %q{2013-08-22}
12   -
13   - s.files = Dir.glob("{lib,vendor}/**/*") + %w( CHANGELOG LICENSE README.rdoc amazon_s3.yml.tpl rackspace_cloudfiles.yml.tpl )
14   - s.extra_rdoc_files = ["README.rdoc"]
15   - s.rdoc_options = ["--inline-source", "--charset=UTF-8"]
16   - s.require_paths = ["lib"]
17   - s.rubyforge_project = "nowarning"
18   - s.rubygems_version = %q{1.3.5}
19   -
20   - if s.respond_to? :specification_version then
21   - s.specification_version = 2
22   - end
23   -end
vendor/plugins/pothoven-attachment_fu/config/database.yml
... ... @@ -1,3 +0,0 @@
1   -test:
2   - adapter: sqlite3
3   - database: ":memory:"
vendor/plugins/pothoven-attachment_fu/config/environment.rb
vendor/plugins/pothoven-attachment_fu/init.rb
... ... @@ -1,6 +0,0 @@
1   -require 'geometry'
2   -ActiveRecord::Base.send(:extend, Technoweenie::AttachmentFu::ActMethods)
3   -Technoweenie::AttachmentFu.tempfile_path = ATTACHMENT_FU_TEMPFILE_PATH if Object.const_defined?(:ATTACHMENT_FU_TEMPFILE_PATH)
4   -FileUtils.mkdir_p Technoweenie::AttachmentFu.tempfile_path
5   -
6   -$:.unshift(File.dirname(__FILE__) + '/vendor')
vendor/plugins/pothoven-attachment_fu/install.rb
... ... @@ -1,7 +0,0 @@
1   -require 'fileutils'
2   -
3   -s3_config = File.dirname(__FILE__) + '/../../../config/amazon_s3.yml'
4   -FileUtils.cp File.dirname(__FILE__) + '/amazon_s3.yml.tpl', s3_config unless File.exist?(s3_config)
5   -cloudfiles_config = File.dirname(__FILE__) + '/../../../config/rackspace_cloudfiles.yml'
6   -FileUtils.cp File.dirname(__FILE__) + '/rackspace_cloudfiles.yml.tpl', cloudfiles_config unless File.exist?(cloudfiles_config)
7   -puts IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
vendor/plugins/pothoven-attachment_fu/lib/geometry.rb
... ... @@ -1,96 +0,0 @@
1   -# This Geometry class was yanked from RMagick. However, it lets ImageMagick handle the actual change_geometry.
2   -# Use #new_dimensions_for to get new dimensions
3   -# Used so I can use spiffy RMagick geometry strings with ImageScience
4   -class Geometry
5   - # @ is removed until support for them is added
6   - FLAGS = ['', '%', '<', '>', '!']#, '@']
7   - RFLAGS = { '%' => :percent,
8   - '!' => :aspect,
9   - '<' => :>,
10   - '>' => :<,
11   - '@' => :area }
12   -
13   - attr_accessor :width, :height, :x, :y, :flag
14   -
15   - def initialize(width=nil, height=nil, x=nil, y=nil, flag=nil)
16   - # Support floating-point width and height arguments so Geometry
17   - # objects can be used to specify Image#density= arguments.
18   - raise ArgumentError, "width must be >= 0: #{width}" if width < 0
19   - raise ArgumentError, "height must be >= 0: #{height}" if height < 0
20   - @width = width.to_f
21   - @height = height.to_f
22   - @x = x.to_i
23   - @y = y.to_i
24   - @flag = flag
25   - end
26   -
27   - # Construct an object from a geometry string
28   - RE = /\A(\d*)(?:x(\d+)?)?([-+]\d+)?([-+]\d+)?([%!<>@]?)\Z/
29   -
30   - def self.from_s(str)
31   - raise(ArgumentError, "no geometry string specified") unless str
32   -
33   - if m = RE.match(str)
34   - new(m[1].to_i, m[2].to_i, m[3].to_i, m[4].to_i, RFLAGS[m[5]])
35   - else
36   - raise ArgumentError, "invalid geometry format"
37   - end
38   - end
39   -
40   - # Convert object to a geometry string
41   - def to_s
42   - str = ''
43   - str << "%g" % @width if @width > 0
44   - str << 'x' if (@width > 0 || @height > 0)
45   - str << "%g" % @height if @height > 0
46   - str << "%+d%+d" % [@x, @y] if (@x != 0 || @y != 0)
47   - str << FLAGS[@flag.to_i]
48   - end
49   -
50   - # attempts to get new dimensions for the current geometry string given these old dimensions.
51   - # This doesn't implement the aspect flag (!) or the area flag (@). PDI
52   - def new_dimensions_for(orig_width, orig_height)
53   - new_width = orig_width
54   - new_height = orig_height
55   -
56   - case @flag
57   - when :percent
58   - scale_x = @width.zero? ? 100 : @width
59   - scale_y = @height.zero? ? @width : @height
60   - new_width = scale_x.to_f * (orig_width.to_f / 100.0)
61   - new_height = scale_y.to_f * (orig_height.to_f / 100.0)
62   - when :aspect
63   - new_width = @width unless @width.nil?
64   - new_height = @height unless @height.nil?
65   - when :<, :>, nil
66   - scale_factor =
67   - if new_width.zero? || new_height.zero?
68   - 1.0
69   - else
70   - if @width.nonzero? && @height.nonzero?
71   - [@width.to_f / new_width.to_f, @height.to_f / new_height.to_f].min
72   - else
73   - @width.nonzero? ? (@width.to_f / new_width.to_f) : (@height.to_f / new_height.to_f)
74   - end
75   - end
76   - new_width = scale_factor * new_width.to_f
77   - new_height = scale_factor * new_height.to_f
78   - new_width = orig_width if @flag && orig_width.send(@flag, new_width)
79   - new_height = orig_height if @flag && orig_height.send(@flag, new_height)
80   - end
81   -
82   - [new_width, new_height].collect! { |v| [v.round, 1].max }
83   - end
84   -end
85   -
86   -class Array
87   - # allows you to get new dimensions for the current array of dimensions with a given geometry string
88   - #
89   - # [50, 64] / '40>' # => [40, 51]
90   - def /(geometry)
91   - raise ArgumentError, "Only works with a [width, height] pair" if size != 2
92   - raise ArgumentError, "Must pass a valid geometry string or object" unless geometry.is_a?(String) || geometry.is_a?(Geometry)
93   - geometry = Geometry.from_s(geometry) if geometry.is_a?(String)
94   - geometry.new_dimensions_for first, last
95   - end
96   -end
vendor/plugins/pothoven-attachment_fu/lib/pothoven-attachment_fu.rb
... ... @@ -1,12 +0,0 @@
1   -class Engine < Rails::Engine
2   - # Mimic old vendored plugin behavior, attachment_fu/lib is autoloaded.
3   - config.autoload_paths << File.expand_path("..", __FILE__)
4   -
5   - initializer "attachment_fu" do
6   - require 'geometry'
7   -
8   - ActiveRecord::Base.send(:extend, Technoweenie::AttachmentFu::ActMethods)
9   - Technoweenie::AttachmentFu.tempfile_path = ATTACHMENT_FU_TEMPFILE_PATH if Object.const_defined?(:ATTACHMENT_FU_TEMPFILE_PATH)
10   - FileUtils.mkdir_p Technoweenie::AttachmentFu.tempfile_path
11   - end
12   -end
vendor/plugins/pothoven-attachment_fu/lib/technoweenie/attachment_fu.rb
... ... @@ -1,588 +0,0 @@
1   -module Technoweenie # :nodoc:
2   - module AttachmentFu # :nodoc:
3   - @@default_processors = %w(ImageScience Rmagick MiniMagick Gd2 CoreImage)
4   - @@tempfile_path = File.join(Rails.root, 'tmp', 'attachment_fu')
5   - @@content_types = [
6   - 'image/jpeg',
7   - 'image/pjpeg',
8   - 'image/jpg',
9   - 'image/gif',
10   - 'image/png',
11   - 'image/x-png',
12   - 'image/jpg',
13   - 'image/x-ms-bmp',
14   - 'image/bmp',
15   - 'image/x-bmp',
16   - 'image/x-bitmap',
17   - 'image/x-xbitmap',
18   - 'image/x-win-bitmap',
19   - 'image/x-windows-bmp',
20   - 'image/ms-bmp',
21   - 'application/bmp',
22   - 'application/x-bmp',
23   - 'application/x-win-bitmap',
24   - 'application/preview',
25   - 'image/jp_',
26   - 'application/jpg',
27   - 'application/x-jpg',
28   - 'image/pipeg',
29   - 'image/vnd.swiftview-jpeg',
30   - 'image/x-xbitmap',
31   - 'application/png',
32   - 'application/x-png',
33   - 'image/gi_',
34   - 'image/x-citrix-pjpeg'
35   - ]
36   - mattr_reader :content_types, :tempfile_path, :default_processors
37   - mattr_writer :tempfile_path
38   -
39   - class ThumbnailError < StandardError; end
40   - class AttachmentError < StandardError; end
41   -
42   - module ActMethods
43   - # Options:
44   - # * <tt>:content_type</tt> - Allowed content types. Allows all by default. Use :image to allow all standard image types.
45   - # * <tt>:min_size</tt> - Minimum size allowed. 1 byte is the default.
46   - # * <tt>:max_size</tt> - Maximum size allowed. 1.megabyte is the default.
47   - # * <tt>:size</tt> - Range of sizes allowed. (1..1.megabyte) is the default. This overrides the :min_size and :max_size options.
48   - # * <tt>:resize_to</tt> - Used by RMagick to resize images. Pass either an array of width/height, or a geometry string. Prefix geometry string with 'c' to crop image, ex. 'c100x100'
49   - # * <tt>:sharpen_on_resize</tt> - When using RMagick, setting to true will sharpen images after resizing.
50   - # * <tt>:jpeg_quality</tt> - Used to provide explicit JPEG quality for thumbnail/resize saves. Can have multiple formats:
51   - # * Integer from 0 (basically crap) to 100 (basically lossless, fat files).
52   - # * When relying on ImageScience, you can also use one of its +JPEG_xxx+ constants for predefined ratios/settings.
53   - # * You can also use a Hash, with keys being either thumbnail symbols (I repeat: _symbols_) or surface boundaries.
54   - # A surface boundary is a string starting with either '<' or '>=', followed by a number of pixels. This lets you
55   - # specify per-thumbnail or per-general-thumbnail-"size" JPEG qualities. (which can be useful when you have a
56   - # _lot_ of thumbnail options). Surface example: +{ '<2000' => 90, '>=2000' => 75 }+.
57   - # Defaults vary depending on the processor (ImageScience: 100%, Rmagick/MiniMagick/Gd2: 75%,
58   - # CoreImage: auto-adjust). Note that only tdd-image_science (available from GitHub) currently supports explicit JPEG quality;
59   - # the default image_science currently forces 100%.
60   - # * <tt>:thumbnails</tt> - Specifies a set of thumbnails to generate. This accepts a hash of filename suffixes and
61   - # RMagick resizing options. If you have a polymorphic parent relationship, you can provide parent-type-specific
62   - # thumbnail settings by using a pair with the type string as key and a Hash of thumbnail definitions as value.
63   - # AttachmentFu automatically detects your first polymorphic +belongs_to+ relationship.
64   - # * <tt>:thumbnail_class</tt> - Set what class to use for thumbnails. This attachment class is used by default.
65   - # * <tt>:path_prefix</tt> - path to store the uploaded files. Uses public/#{table_name} by default for the filesystem, and just #{table_name}
66   - # for the S3 backend. Setting this sets the :storage to :file_system.
67   -
68   - # * <tt>:storage</tt> - Use :file_system to specify the attachment data is stored with the file system. Defaults to :db_system.
69   - # * <tt>:cloundfront</tt> - Set to true if you are using S3 storage and want to serve the files through CloudFront. You will need to
70   - # set a distribution domain in the amazon_s3.yml config file. Defaults to false
71   - # * <tt>:bucket_key</tt> - Use this to specify a different bucket key other than :bucket_name in the amazon_s3.yml file. This allows you to use
72   - # different buckets for different models. An example setting would be :image_bucket and the you would need to define the name of the corresponding
73   - # bucket in the amazon_s3.yml file.
74   -
75   - # * <tt>:keep_profile</tt> By default image EXIF data will be stripped to minimize image size. For small thumbnails this proivides important savings. Picture quality is not affected. Set to false if you want to keep the image profile as is. ImageScience will allways keep EXIF data.
76   - #
77   - # Examples:
78   - # has_attachment :max_size => 1.kilobyte
79   - # has_attachment :size => 1.megabyte..2.megabytes
80   - # has_attachment :content_type => 'application/pdf'
81   - # has_attachment :content_type => ['application/pdf', 'application/msword', 'text/plain']
82   - # has_attachment :content_type => :image, :resize_to => [50,50]
83   - # has_attachment :content_type => ['application/pdf', :image], :resize_to => 'x50'
84   - # has_attachment :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }
85   - # has_attachment :storage => :file_system, :path_prefix => 'public/files'
86   - # has_attachment :storage => :file_system, :path_prefix => 'public/files',
87   - # :content_type => :image, :resize_to => [50,50]
88   - # has_attachment :storage => :file_system, :path_prefix => 'public/files',
89   - # :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }
90   - # has_attachment :storage => :s3
91   - def has_attachment(options = {})
92   - # this allows you to redefine the acts' options for each subclass, however
93   - options[:min_size] ||= 1
94   - options[:max_size] ||= 1.megabyte
95   - options[:size] ||= (options[:min_size]..options[:max_size])
96   - options[:thumbnails] ||= {}
97   - options[:thumbnail_class] ||= self
98   - options[:s3_access] ||= :public_read
99   - options[:cloudfront] ||= false
100   - options[:content_type] = [options[:content_type]].flatten.collect! { |t| t == :image ? ::Technoweenie::AttachmentFu.content_types : t }.flatten unless options[:content_type].nil?
101   - options[:cache_control] ||= "max-age=315360000" # 10 years
102   -
103   - unless options[:thumbnails].is_a?(Hash)
104   - raise ArgumentError, ":thumbnails option should be a hash: e.g. :thumbnails => { :foo => '50x50' }"
105   - end
106   -
107   - extend ClassMethods unless (class << self; included_modules; end).include?(ClassMethods)
108   - include InstanceMethods unless included_modules.include?(InstanceMethods)
109   -
110   - parent_options = attachment_options || {}
111   - # doing these shenanigans so that #attachment_options is available to processors and backends
112   - self.attachment_options = options
113   -
114   - attr_accessor :thumbnail_resize_options
115   -
116   - attachment_options[:storage] ||= (attachment_options[:file_system_path] || attachment_options[:path_prefix]) ? :file_system : :db_file
117   - attachment_options[:storage] ||= parent_options[:storage]
118   - attachment_options[:path_prefix] ||= attachment_options[:file_system_path]
119   - if attachment_options[:path_prefix].nil?
120   - attachment_options[:path_prefix] = case attachment_options[:storage]
121   - when :s3 then table_name
122   - when :cloud_files then table_name
123   - else File.join("public", table_name)
124   - end
125   - end
126   - attachment_options[:path_prefix] = attachment_options[:path_prefix][1..-1] if options[:path_prefix].first == '/'
127   -
128   - association_options = { :foreign_key => 'parent_id' }
129   - if attachment_options[:association_options]
130   - association_options.merge!(attachment_options[:association_options])
131   - end
132   - with_options(association_options) do |m|
133   - m.has_many :thumbnails, :class_name => "::#{attachment_options[:thumbnail_class]}"
134   - m.belongs_to :parent, :class_name => "::#{base_class}" unless options[:thumbnails].empty?
135   - end
136   -
137   - storage_mod = ::Technoweenie::AttachmentFu::Backends.const_get("#{options[:storage].to_s.classify}Backend")
138   - include storage_mod unless included_modules.include?(storage_mod)
139   -
140   - case attachment_options[:processor]
141   - when :none, nil
142   - processors = ::Technoweenie::AttachmentFu.default_processors.dup
143   - begin
144   - if processors.any?
145   - attachment_options[:processor] = processors.first
146   - processor_mod = ::Technoweenie::AttachmentFu::Processors.const_get("#{attachment_options[:processor].to_s.classify}Processor")
147   - include processor_mod unless included_modules.include?(processor_mod)
148   - end
149   - rescue Object, Exception
150   - raise unless load_related_exception?($!)
151   -
152   - processors.shift
153   - retry
154   - end
155   - else
156   - begin
157   - processor_mod = ::Technoweenie::AttachmentFu::Processors.const_get("#{attachment_options[:processor].to_s.classify}Processor")
158   - include processor_mod unless included_modules.include?(processor_mod)
159   - rescue Object, Exception
160   - raise unless load_related_exception?($!)
161   -
162   - puts "Problems loading #{options[:processor]}Processor: #{$!}"
163   - end
164   - end unless parent_options[:processor] # Don't let child override processor
165   - end
166   -
167   - def load_related_exception?(e) #:nodoc: implementation specific
168   - case
169   - when e.kind_of?(LoadError), e.kind_of?(MissingSourceFile), $!.class.name == "CompilationError"
170   - # We can't rescue CompilationError directly, as it is part of the RubyInline library.
171   - # We must instead rescue RuntimeError, and check the class' name.
172   - true
173   - else
174   - false
175   - end
176   - end
177   - private :load_related_exception?
178   - end
179   -
180   - module ClassMethods
181   - delegate :content_types, :to => ::Technoweenie::AttachmentFu
182   -
183   - # Performs common validations for attachment models.
184   - def validates_as_attachment
185   - validates_presence_of :size, :content_type, :filename
186   - validate :attachment_attributes_valid?
187   - end
188   -
189   - # Returns true or false if the given content type is recognized as an image.
190   - def image?(content_type)
191   - content_types.include?(content_type)
192   - end
193   -
194   - def self.extended(base)
195   - base.class_attribute :attachment_options
196   - base.before_destroy :destroy_thumbnails
197   - base.before_validation :set_size_from_temp_path
198   - base.after_destroy :destroy_file
199   - base.after_validation :process_attachment
200   - base.after_save :after_process_attachment
201   - #if defined?(::ActiveSupport::Callbacks)
202   - # base.define_callbacks :after_resize, :after_attachment_saved, :before_thumbnail_saved
203   - #end
204   - end
205   -
206   - unless defined?(::ActiveSupport::Callbacks)
207   - # Callback after an image has been resized.
208   - #
209   - # class Foo < ActiveRecord::Base
210   - # acts_as_attachment
211   - # after_resize do |record, img|
212   - # record.aspect_ratio = img.columns.to_f / img.rows.to_f
213   - # end
214   - # end
215   - def after_resize(&block)
216   - write_inheritable_array(:after_resize, [block])
217   - end
218   -
219   - # Callback after an attachment has been saved either to the file system or the DB.
220   - # Only called if the file has been changed, not necessarily if the record is updated.
221   - #
222   - # class Foo < ActiveRecord::Base
223   - # acts_as_attachment
224   - # after_attachment_saved do |record|
225   - # ...
226   - # end
227   - # end
228   - def after_attachment_saved(&block)
229   - write_inheritable_array(:after_attachment_saved, [block])
230   - end
231   -
232   - # Callback before a thumbnail is saved. Use this to pass any necessary extra attributes that may be required.
233   - #
234   - # class Foo < ActiveRecord::Base
235   - # acts_as_attachment
236   - # before_thumbnail_saved do |thumbnail|
237   - # record = thumbnail.parent
238   - # ...
239   - # end
240   - # end
241   - def before_thumbnail_saved(&block)
242   - write_inheritable_array(:before_thumbnail_saved, [block])
243   - end
244   - end
245   -
246   - # Get the thumbnail class, which is the current attachment class by default.
247   - # Configure this with the :thumbnail_class option.
248   - def thumbnail_class
249   - attachment_options[:thumbnail_class] = attachment_options[:thumbnail_class].constantize unless attachment_options[:thumbnail_class].is_a?(Class)
250   - attachment_options[:thumbnail_class]
251   - end
252   -
253   - # Copies the given file path to a new tempfile, returning the closed tempfile.
254   - def copy_to_temp_file(file, temp_base_name)
255   - Tempfile.new(temp_base_name, ::Technoweenie::AttachmentFu.tempfile_path).tap do |tmp|
256   - tmp.close
257   - FileUtils.cp file, tmp.path
258   - end
259   - end
260   -
261   - # Writes the given data to a new tempfile, returning the closed tempfile.
262   - def write_to_temp_file(data, temp_base_name)
263   - Tempfile.new(temp_base_name, ::Technoweenie::AttachmentFu.tempfile_path).tap do |tmp|
264   - tmp.binmode
265   - tmp.write data
266   - tmp.close
267   - end
268   - end
269   -
270   - def polymorphic_relation_type_column
271   - return @@_polymorphic_relation_type_column if defined?(@@_polymorphic_relation_type_column)
272   - # Checked against ActiveRecord 1.15.6 through Edge @ 2009-08-05.
273   - ref = reflections.values.detect { |r| r.macro == :belongs_to && r.options[:polymorphic] }
274   - @@_polymorphic_relation_type_column = ref && ref.options[:foreign_type]
275   - end
276   - end
277   -
278   - module InstanceMethods
279   - def self.included(base)
280   - base.define_callbacks *[:after_resize, :after_attachment_saved, :before_thumbnail_saved] if base.respond_to?(:define_callbacks)
281   - end
282   -
283   - # Checks whether the attachment's content type is an image content type
284   - def image?
285   - self.class.image?(content_type)
286   - end
287   -
288   - # Returns true/false if an attachment is thumbnailable. A thumbnailable attachment has an image content type and the parent_id attribute.
289   - def thumbnailable?
290   - image? && respond_to?(:parent_id) && parent_id.nil?
291   - end
292   -
293   - # Returns the class used to create new thumbnails for this attachment.
294   - def thumbnail_class
295   - self.class.thumbnail_class
296   - end
297   -
298   - # Gets the thumbnail name for a filename. 'foo.jpg' becomes 'foo_thumbnail.jpg'
299   - def thumbnail_name_for(thumbnail = nil)
300   - if thumbnail.blank?
301   - if filename.nil?
302   - return ''
303   - else
304   - return filename
305   - end
306   - end
307   -
308   - ext = nil
309   - basename = filename.gsub /\.\w+$/ do |s|
310   - ext = s; ''
311   - end
312   - # ImageScience doesn't create gif thumbnails, only pngs
313   - ext.sub!(/gif$/i, 'png') if attachment_options[:processor] == "ImageScience"
314   - "#{basename}_#{thumbnail}#{ext}"
315   - end
316   -
317   - # Creates or updates the thumbnail for the current attachment.
318   - def create_or_update_thumbnail(temp_file, file_name_suffix, *size)
319   - thumbnailable? || raise(ThumbnailError.new("Can't create a thumbnail if the content type is not an image or there is no parent_id column"))
320   - find_or_initialize_thumbnail(file_name_suffix).tap do |thumb|
321   - thumb.temp_paths.unshift temp_file
322   - thumb.send(:assign_attributes, {
323   - :content_type => content_type,
324   - :filename => thumbnail_name_for(file_name_suffix),
325   - :thumbnail_resize_options => size
326   - }, :without_protection => true)
327   - callback_with_args :before_thumbnail_saved, thumb
328   - thumb.save!
329   - end
330   - end
331   -
332   - # Sets the content type.
333   - def content_type=(new_type)
334   - write_attribute :content_type, new_type.to_s.strip
335   - end
336   -
337   - # Sanitizes a filename.
338   - def filename=(new_name)
339   - write_attribute :filename, sanitize_filename(new_name)
340   - end
341   -
342   - # Returns the width/height in a suitable format for the image_tag helper: (100x100)
343   - def image_size
344   - [width.to_s, height.to_s] * 'x'
345   - end
346   -
347   - # Returns true if the attachment data will be written to the storage system on the next save
348   - def save_attachment?
349   - File.file?(temp_path.class == String ? temp_path : temp_path.to_filename)
350   - end
351   -
352   - # nil placeholder in case this field is used in a form.
353   - def uploaded_data() nil; end
354   -
355   - # This method handles the uploaded file object. If you set the field name to uploaded_data, you don't need
356   - # any special code in your controller.
357   - #
358   - # <% form_for :attachment, :html => { :multipart => true } do |f| -%>
359   - # <p><%= f.file_field :uploaded_data %></p>
360   - # <p><%= submit_tag :Save %>
361   - # <% end -%>
362   - #
363   - # @attachment = Attachment.create! params[:attachment]
364   - #
365   - # TODO: Allow it to work with Merb tempfiles too.
366   - def uploaded_data=(file_data)
367   - if file_data.respond_to?(:content_type)
368   - return nil if file_data.size == 0
369   - self.content_type = file_data.content_type
370   - self.filename = file_data.original_filename if respond_to?(:filename)
371   - else
372   - return nil if file_data.blank? || file_data['size'] == 0
373   - self.content_type = file_data['content_type']
374   - self.filename = file_data['filename']
375   - file_data = file_data['tempfile']
376   - end
377   - if file_data.is_a?(StringIO)
378   - file_data.rewind
379   - set_temp_data file_data.read
380   - else
381   - file_data.respond_to?(:tempfile) ? self.temp_paths.unshift( file_data.tempfile.path ) : self.temp_paths.unshift( file_data.path )
382   - end
383   - end
384   -
385   - # Gets the latest temp path from the collection of temp paths. While working with an attachment,
386   - # multiple Tempfile objects may be created for various processing purposes (resizing, for example).
387   - # An array of all the tempfile objects is stored so that the Tempfile instance is held on to until
388   - # it's not needed anymore. The collection is cleared after saving the attachment.
389   - def temp_path
390   - p = temp_paths.first
391   - p.respond_to?(:path) ? p.path : p.to_s
392   - end
393   -
394   - # Gets an array of the currently used temp paths. Defaults to a copy of #full_filename.
395   - def temp_paths
396   - @temp_paths ||= (new_record? || !respond_to?(:full_filename) || !File.exist?(full_filename) ?
397   - [] : [copy_to_temp_file(full_filename)])
398   - end
399   -
400   - # Gets the data from the latest temp file. This will read the file into memory.
401   - def temp_data
402   - save_attachment? ? File.read(temp_path) : nil
403   - end
404   -
405   - # Writes the given data to a Tempfile and adds it to the collection of temp files.
406   - def set_temp_data(data)
407   - temp_paths.unshift write_to_temp_file data unless data.nil?
408   - end
409   -
410   - # Copies the given file to a randomly named Tempfile.
411   - def copy_to_temp_file(file)
412   - self.class.copy_to_temp_file file, random_tempfile_filename
413   - end
414   -
415   - # Writes the given file to a randomly named Tempfile.
416   - def write_to_temp_file(data)
417   - self.class.write_to_temp_file data, random_tempfile_filename
418   - end
419   -
420   - # Stub for creating a temp file from the attachment data. This should be defined in the backend module.
421   - def create_temp_file() end
422   -
423   - # Allows you to work with a processed representation (RMagick, ImageScience, etc) of the attachment in a block.
424   - #
425   - # @attachment.with_image do |img|
426   - # self.data = img.thumbnail(100, 100).to_blob
427   - # end
428   - #
429   - def with_image(&block)
430   - self.class.with_image(temp_path, &block)
431   - end
432   -
433   - protected
434   - # Generates a unique filename for a Tempfile.
435   - def random_tempfile_filename
436   - base_filename = filename ? filename.gsub(/\.\w+$/, '') : 'attachment'
437   - ext = filename.slice(/\.\w+$/)
438   - ["#{rand Time.now.to_i}#{base_filename}", ext || '']
439   - end
440   -
441   - def sanitize_filename(filename)
442   - return unless filename
443   - filename.strip.tap do |name|
444   - # NOTE: File.basename doesn't work right with Windows paths on Unix
445   - # get only the filename, not the whole path
446   - name.gsub! /^.*(\\|\/)/, ''
447   -
448   - # Finally, replace all non alphanumeric, underscore or periods with underscore
449   - name.gsub! /[^A-Za-z0-9\.\-]/, '_'
450   - end
451   - end
452   -
453   - # before_validation callback.
454   - def set_size_from_temp_path
455   - self.size = File.size(temp_path) if save_attachment?
456   - end
457   -
458   - # validates the size and content_type attributes according to the current model's options
459   - def attachment_attributes_valid?
460   - [:size, :content_type].each do |attr_name|
461   - enum = attachment_options[attr_name]
462   - if Object.const_defined?(:I18n) # Rails >= 2.2
463   - errors.add attr_name, I18n.translate("activerecord.errors.messages.inclusion", attr_name => enum) unless enum.nil? || enum.include?(send(attr_name))
464   - else
465   - errors.add attr_name, ActiveRecord::Errors.default_error_messages[:inclusion] unless enum.nil? || enum.include?(send(attr_name))
466   - end
467   - end
468   - end
469   -
470   - # Initializes a new thumbnail with the given suffix.
471   - def find_or_initialize_thumbnail(file_name_suffix)
472   - respond_to?(:parent_id) ?
473   - thumbnail_class.find_or_initialize_by_thumbnail_and_parent_id(file_name_suffix.to_s, id) :
474   - thumbnail_class.find_or_initialize_by_thumbnail(file_name_suffix.to_s)
475   - end
476   -
477   - # Stub for a #process_attachment method in a processor
478   - def process_attachment
479   - @saved_attachment = save_attachment?
480   - end
481   -
482   - # Cleans up after processing. Thumbnails are created, the attachment is stored to the backend, and the temp_paths are cleared.
483   - def after_process_attachment
484   - if @saved_attachment
485   - if respond_to?(:process_attachment_with_processing, true) && thumbnailable? && !attachment_options[:thumbnails].blank? && parent_id.nil?
486   - temp_file = temp_path || create_temp_file
487   - attachment_options[:thumbnails].each { |suffix, size|
488   - if size.is_a?(Symbol)
489   - parent_type = polymorphic_parent_type
490   - next unless parent_type && [parent_type, parent_type.tableize].include?(suffix.to_s) && respond_to?(size)
491   - size = send(size)
492   - end
493   - if size.is_a?(Hash)
494   - parent_type = polymorphic_parent_type
495   - next unless parent_type && [parent_type, parent_type.tableize].include?(suffix.to_s)
496   - size.each { |ppt_suffix, ppt_size|
497   - create_or_update_thumbnail(temp_file, ppt_suffix, *ppt_size)
498   - }
499   - else
500   - create_or_update_thumbnail(temp_file, suffix, *size)
501   - end
502   - }
503   - end
504   - save_to_storage
505   - @temp_paths.clear
506   - @saved_attachment = nil
507   - #callback :after_attachment_saved
508   - callback_with_args :after_attachment_saved, nil
509   - end
510   - end
511   -
512   - # Resizes the given processed img object with either the attachment resize options or the thumbnail resize options.
513   - def resize_image_or_thumbnail!(img)
514   - if (!respond_to?(:parent_id) || parent_id.nil?) && attachment_options[:resize_to] # parent image
515   - resize_image(img, attachment_options[:resize_to])
516   - elsif thumbnail_resize_options # thumbnail
517   - resize_image(img, thumbnail_resize_options)
518   - end
519   - end
520   -
521   - if defined?(Rails) && Rails::VERSION::MAJOR >= 3
522   - def callback_with_args(method, arg = self)
523   - if respond_to?(method)
524   - send(method, arg)
525   - end
526   - end
527   - # Yanked from ActiveRecord::Callbacks, modified so I can pass args to the callbacks besides self.
528   - # Only accept blocks, however
529   - elsif ActiveSupport.const_defined?(:Callbacks)
530   - # Rails 2.1 and beyond!
531   - def callback_with_args(method, arg = self)
532   - notify(method)
533   -
534   - result = run_callbacks(method, { :object => arg }) { |result, object| result == false }
535   -
536   - if result != false && respond_to_without_attributes?(method)
537   - result = send(method)
538   - end
539   -
540   - result
541   - end
542   -
543   - def run_callbacks(kind, options = {}, &block)
544   - options.reverse_merge!( :object => self )
545   - self.class.send("#{kind}_callback_chain").run(options[:object], options, &block)
546   - end
547   - else
548   - # Rails 2.0
549   - def callback_with_args(method, arg = self)
550   - notify(method)
551   -
552   - result = nil
553   - callbacks_for(method).each do |callback|
554   - result = callback.call(self, arg)
555   - return false if result == false
556   - end
557   - result
558   - end
559   - end
560   -
561   - # Removes the thumbnails for the attachment, if it has any
562   - def destroy_thumbnails
563   - self.thumbnails.each { |thumbnail| thumbnail.destroy } if thumbnailable?
564   - end
565   -
566   - def polymorphic_parent_type
567   - rel_name = self.class.polymorphic_relation_type_column
568   - rel_name && send(rel_name)
569   - end
570   -
571   - def get_jpeg_quality(require_0_to_100 = true)
572   - quality = attachment_options[:jpeg_quality]
573   - if quality.is_a?(Hash)
574   - sbl_quality = thumbnail && quality[thumbnail.to_sym]
575   - sbl_quality = nil if sbl_quality && require_0_to_100 && !sbl_quality.to_i.between?(0, 100)
576   - surface = (width || 1) * (height || 1)
577   - size_quality = quality.detect { |k, v|
578   - next unless k.is_a?(String) && k =~ /^(<|>=)(\d+)$/
579   - op, threshold = $1, $2.to_i
580   - surface.send(op, threshold)
581   - }
582   - quality = sbl_quality || size_quality && size_quality[1]
583   - end
584   - return quality && (!require_0_to_100 || quality.to_i.between?(0, 100)) ? quality : nil
585   - end
586   - end
587   - end
588   -end
vendor/plugins/pothoven-attachment_fu/lib/technoweenie/attachment_fu/backends/cloud_file_backend.rb
... ... @@ -1,211 +0,0 @@
1   -module Technoweenie # :nodoc:
2   - module AttachmentFu # :nodoc:
3   - module Backends
4   - # = CloudFiles Storage Backend
5   - #
6   - # Enables use of {Rackspace Cloud Files}[http://www.mosso.com/cloudfiles.jsp] as a storage mechanism
7   - #
8   - # Based heavily on the Amazon S3 backend.
9   - #
10   - # == Requirements
11   - #
12   - # Requires the {Cloud Files Gem}[http://www.mosso.com/cloudfiles.jsp] by Rackspace
13   - #
14   - # == Configuration
15   - #
16   - # Configuration is done via <tt>Rails.root.to_s/config/rackspace_cloudfiles.yml</tt> and is loaded according to the <tt>#{Rails.env}</tt>.
17   - # The minimum connection options that you must specify are a container name, your Mosso login name and your Mosso API key.
18   - # You can sign up for Cloud Files and get access keys by visiting https://www.mosso.com/buy.htm
19   - #
20   - # Example configuration (Rails.root.to_s/config/rackspace_cloudfiles.yml)
21   - #
22   - # development:
23   - # container_name: appname_development
24   - # username: <your key>
25   - # api_key: <your key>
26   - #
27   - # test:
28   - # container_name: appname_test
29   - # username: <your key>
30   - # api_key: <your key>
31   - #
32   - # production:
33   - # container_name: appname
34   - # username: <your key>
35   - # apik_key: <your key>
36   - #
37   - # You can change the location of the config path by passing a full path to the :cloudfiles_config_path option.
38   - #
39   - # has_attachment :storage => :cloud_files, :cloudfiles_config_path => (Rails.root.to_s + '/config/mosso.yml')
40   - #
41   - # === Required configuration parameters
42   - #
43   - # * <tt>:username</tt> - The username for your Rackspace Cloud (Mosso) account. Provided by Rackspace.
44   - # * <tt>:secret_access_key</tt> - The api key for your Rackspace Cloud account. Provided by Rackspace.
45   - # * <tt>:container_name</tt> - The name of a container in your Cloud Files account.
46   - #
47   - # If any of these required arguments is missing, a AuthenticationException will be raised from CloudFiles::Connection.
48   - #
49   - # == Usage
50   - #
51   - # To specify Cloud Files as the storage mechanism for a model, set the acts_as_attachment <tt>:storage</tt> option to <tt>:cloud_files/tt>.
52   - #
53   - # class Photo < ActiveRecord::Base
54   - # has_attachment :storage => :cloud_files
55   - # end
56   - #
57   - # === Customizing the path
58   - #
59   - # By default, files are prefixed using a pseudo hierarchy in the form of <tt>:table_name/:id</tt>, which results
60   - # in Cloud Files object names (and urls) that look like: http://:server/:container_name/:table_name/:id/:filename with :table_name
61   - # representing the customizable portion of the path. You can customize this prefix using the <tt>:path_prefix</tt>
62   - # option:
63   - #
64   - # class Photo < ActiveRecord::Base
65   - # has_attachment :storage => :cloud_files, :path_prefix => 'my/custom/path'
66   - # end
67   - #
68   - # Which would result in public URLs like <tt>http(s)://:server/:container_name/my/custom/path/:id/:filename.</tt>
69   - #
70   - # === Permissions
71   - #
72   - # File permisisons are determined by the permissions of the container. At present, the options are public (and distributed
73   - # by the Limelight CDN), and private (only available to your login)
74   - #
75   - # === Other options
76   - #
77   - # Of course, all the usual configuration options apply, such as content_type and thumbnails:
78   - #
79   - # class Photo < ActiveRecord::Base
80   - # has_attachment :storage => :cloud_files, :content_type => ['application/pdf', :image], :resize_to => 'x50'
81   - # has_attachment :storage => :cloud_files, :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }
82   - # end
83   - #
84   - # === Accessing Cloud Files URLs
85   - #
86   - # You can get an object's public URL using the cloudfiles_url accessor. For example, assuming that for your postcard app
87   - # you had a container name like 'postcard_world_development', and an attachment model called Photo:
88   - #
89   - # @postcard.cloudfiles_url # => http://cdn.cloudfiles.mosso.com/c45182/uploaded_files/20/london.jpg
90   - #
91   - # The resulting url is in the form: http://:server/:container_name/:table_name/:id/:file.
92   - # The optional thumbnail argument will output the thumbnail's filename (if any).
93   - #
94   - # Additionally, you can get an object's base path relative to the container root using
95   - # <tt>base_path</tt>:
96   - #
97   - # @photo.file_base_path # => uploaded_files/20
98   - #
99   - # And the full path (including the filename) using <tt>full_filename</tt>:
100   - #
101   - # @photo.full_filename # => uploaded_files/20/london.jpg
102   - #
103   - # Niether <tt>base_path</tt> or <tt>full_filename</tt> include the container name as part of the path.
104   - # You can retrieve the container name using the <tt>container_name</tt> method.
105   - module CloudFileBackend
106   - class RequiredLibraryNotFoundError < StandardError; end
107   - class ConfigFileNotFoundError < StandardError; end
108   -
109   - def self.included(base) #:nodoc:
110   - mattr_reader :container_name, :cloudfiles_config
111   -
112   - begin
113   - require 'cloudfiles'
114   - rescue LoadError
115   - raise RequiredLibraryNotFoundError.new('CloudFiles could not be loaded')
116   - end
117   -
118   - begin
119   - @@cloudfiles_config_path = base.attachment_options[:cloudfiles_config_path] || (Rails.root.to_s + '/config/rackspace_cloudfiles.yml')
120   - @@cloudfiles_config = @@cloudfiles_config = YAML.load(ERB.new(File.read(@@cloudfiles_config_path)).result)[Rails.env].symbolize_keys
121   - rescue
122   - #raise ConfigFileNotFoundError.new('File %s not found' % @@cloudfiles_config_path)
123   - end
124   -
125   - @@container_name = @@cloudfiles_config[:container_name]
126   - @@cf = CloudFiles::Connection.new(@@cloudfiles_config[:username], @@cloudfiles_config[:api_key])
127   - @@container = @@cf.container(@@container_name)
128   -
129   - base.before_update :rename_file
130   - end
131   -
132   - # Overwrites the base filename writer in order to store the old filename
133   - def filename=(value)
134   - @old_filename = filename unless filename.nil? || @old_filename
135   - write_attribute :filename, sanitize_filename(value)
136   - end
137   -
138   - # The attachment ID used in the full path of a file
139   - def attachment_path_id
140   - ((respond_to?(:parent_id) && parent_id) || id).to_s
141   - end
142   -
143   - # The pseudo hierarchy containing the file relative to the container name
144   - # Example: <tt>:table_name/:id</tt>
145   - def base_path
146   - File.join(attachment_options[:path_prefix], attachment_path_id)
147   - end
148   -
149   - # The full path to the file relative to the container name
150   - # Example: <tt>:table_name/:id/:filename</tt>
151   - def full_filename(thumbnail = nil)
152   - File.join(base_path, thumbnail_name_for(thumbnail))
153   - end
154   -
155   - # All public objects are accessible via a GET request to the Cloud Files servers. You can generate a
156   - # url for an object using the cloudfiles_url method.
157   - #
158   - # @photo.cloudfiles_url
159   - #
160   - # The resulting url is in the CDN URL for the object
161   - #
162   - # The optional thumbnail argument will output the thumbnail's filename (if any).
163   - #
164   - # If you are trying to get the URL for a nonpublic container, nil will be returned.
165   - def cloudfiles_url(thumbnail = nil)
166   - if @@container.public?
167   - File.join(@@container.cdn_url, full_filename(thumbnail))
168   - else
169   - nil
170   - end
171   - end
172   - alias :public_filename :cloudfiles_url
173   -
174   - def create_temp_file
175   - write_to_temp_file current_data
176   - end
177   -
178   - def current_data
179   - @@container.get_object(full_filename).data
180   - end
181   -
182   - protected
183   - # Called in the after_destroy callback
184   - def destroy_file
185   - @@container.delete_object(full_filename)
186   - end
187   -
188   - def rename_file
189   - # Cloud Files doesn't rename right now, so we'll just nuke.
190   - return unless @old_filename && @old_filename != filename
191   -
192   - old_full_filename = File.join(base_path, @old_filename)
193   - @@container.delete_object(old_full_filename)
194   -
195   - @old_filename = nil
196   - true
197   - end
198   -
199   - def save_to_storage
200   - if save_attachment?
201   - @object = @@container.create_object(full_filename)
202   - @object.write((temp_path ? File.open(temp_path) : temp_data))
203   - end
204   -
205   - @old_filename = nil
206   - true
207   - end
208   - end
209   - end
210   - end
211   -end
vendor/plugins/pothoven-attachment_fu/lib/technoweenie/attachment_fu/backends/db_file_backend.rb
... ... @@ -1,39 +0,0 @@
1   -module Technoweenie # :nodoc:
2   - module AttachmentFu # :nodoc:
3   - module Backends
4   - # Methods for DB backed attachments
5   - module DbFileBackend
6   - def self.included(base) #:nodoc:
7   - Object.const_set(:DbFile, Class.new(ActiveRecord::Base)) unless Object.const_defined?(:DbFile)
8   - base.belongs_to :db_file, :class_name => '::DbFile', :foreign_key => 'db_file_id'
9   - end
10   -
11   - # Creates a temp file with the current db data.
12   - def create_temp_file
13   - write_to_temp_file current_data
14   - end
15   -
16   - # Gets the current data from the database
17   - def current_data
18   - db_file.data
19   - end
20   -
21   - protected
22   - # Destroys the file. Called in the after_destroy callback
23   - def destroy_file
24   - db_file.destroy if db_file
25   - end
26   -
27   - # Saves the data to the DbFile model
28   - def save_to_storage
29   - if save_attachment?
30   - (db_file || build_db_file).data = temp_data
31   - db_file.save!
32   - self.class.update_all ['db_file_id = ?', self.db_file_id = db_file.id], ['id = ?', id]
33   - end
34   - true
35   - end
36   - end
37   - end
38   - end
39   -end
40 0 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/lib/technoweenie/attachment_fu/backends/file_system_backend.rb
... ... @@ -1,126 +0,0 @@
1   -require 'fileutils'
2   -require 'digest/sha2'
3   -
4   -module Technoweenie # :nodoc:
5   - module AttachmentFu # :nodoc:
6   - module Backends
7   - # Methods for file system backed attachments
8   - module FileSystemBackend
9   - def self.included(base) #:nodoc:
10   - base.before_update :rename_file
11   - end
12   -
13   - # Gets the full path to the filename in this format:
14   - #
15   - # # This assumes a model name like MyModel
16   - # # public/#{table_name} is the default filesystem path
17   - # #{Rails.root}/public/my_models/5/blah.jpg
18   - #
19   - # Overwrite this method in your model to customize the filename.
20   - # The optional thumbnail argument will output the thumbnail's filename.
21   - def full_filename(thumbnail = nil)
22   - file_system_path = (thumbnail ? thumbnail_class : self).attachment_options[:path_prefix].to_s
23   - File.join(Rails.root, file_system_path, *partitioned_path(thumbnail_name_for(thumbnail)))
24   - end
25   -
26   - # Used as the base path that #public_filename strips off full_filename to create the public path
27   - def base_path
28   - @base_path ||= File.join(Rails.root, 'public')
29   - end
30   -
31   - # The attachment ID used in the full path of a file
32   - def attachment_path_id
33   - ((respond_to?(:parent_id) && parent_id) || id) || 0
34   - end
35   -
36   - # Partitions the given path into an array of path components.
37   - #
38   - # For example, given an <tt>*args</tt> of ["foo", "bar"], it will return
39   - # <tt>["0000", "0001", "foo", "bar"]</tt> (assuming that that id returns 1).
40   - #
41   - # If the id is not an integer, then path partitioning will be performed by
42   - # hashing the string value of the id with SHA-512, and splitting the result
43   - # into 4 components. If the id a 128-bit UUID (as set by :uuid_primary_key => true)
44   - # then it will be split into 2 components.
45   - #
46   - # To turn this off entirely, set :partition => false.
47   - def partitioned_path(*args)
48   - if respond_to?(:attachment_options) && attachment_options[:partition] == false
49   - args
50   - elsif attachment_options[:uuid_primary_key]
51   - # Primary key is a 128-bit UUID in hex format. Split it into 2 components.
52   - path_id = attachment_path_id.to_s
53   - component1 = path_id[0..15] || "-"
54   - component2 = path_id[16..-1] || "-"
55   - [component1, component2] + args
56   - else
57   - path_id = attachment_path_id
58   - if path_id.is_a?(Integer)
59   - # Primary key is an integer. Split it after padding it with 0.
60   - ("%08d" % path_id).scan(/..../) + args
61   - else
62   - # Primary key is a String. Hash it, then split it into 4 components.
63   - hash = Digest::SHA512.hexdigest(path_id.to_s)
64   - [hash[0..31], hash[32..63], hash[64..95], hash[96..127]] + args
65   - end
66   - end
67   - end
68   -
69   - # Gets the public path to the file
70   - # The optional thumbnail argument will output the thumbnail's filename.
71   - def public_filename(thumbnail = nil)
72   - full_filename(thumbnail).gsub %r(^#{Regexp.escape(base_path)}), ''
73   - end
74   -
75   - def filename=(value)
76   - @old_filename = full_filename unless filename.nil? || @old_filename
77   - write_attribute :filename, sanitize_filename(value)
78   - end
79   -
80   - # Creates a temp file from the currently saved file.
81   - def create_temp_file
82   - copy_to_temp_file full_filename
83   - end
84   -
85   - protected
86   - # Destroys the file. Called in the after_destroy callback
87   - def destroy_file
88   - FileUtils.rm full_filename
89   - # remove directory also if it is now empty
90   - Dir.rmdir(File.dirname(full_filename)) if (Dir.entries(File.dirname(full_filename))-['.','..']).empty?
91   - rescue
92   - logger.info "Exception destroying #{full_filename.inspect}: [#{$!.class.name}] #{$1.to_s}"
93   - logger.warn $!.backtrace.collect { |b| " > #{b}" }.join("\n")
94   - end
95   -
96   - # Renames the given file before saving
97   - def rename_file
98   - return unless @old_filename && @old_filename != full_filename
99   - if save_attachment? && File.exists?(@old_filename)
100   - FileUtils.rm @old_filename
101   - elsif File.exists?(@old_filename)
102   - FileUtils.mv @old_filename, full_filename
103   - end
104   - @old_filename = nil
105   - true
106   - end
107   -
108   - # Saves the file to the file system
109   - def save_to_storage
110   - if save_attachment?
111   - # TODO: This overwrites the file if it exists, maybe have an allow_overwrite option?
112   - FileUtils.mkdir_p(File.dirname(full_filename))
113   - FileUtils.cp(temp_path, full_filename)
114   - FileUtils.chmod(attachment_options[:chmod] || 0644, full_filename)
115   - end
116   - @old_filename = nil
117   - true
118   - end
119   -
120   - def current_data
121   - File.file?(full_filename) ? File.read(full_filename) : nil
122   - end
123   - end
124   - end
125   - end
126   -end
vendor/plugins/pothoven-attachment_fu/lib/technoweenie/attachment_fu/backends/s3_backend.rb
... ... @@ -1,412 +0,0 @@
1   -module Technoweenie # :nodoc:
2   - module AttachmentFu # :nodoc:
3   - module Backends
4   - # = AWS::S3 Storage Backend
5   - #
6   - # Enables use of {Amazon's Simple Storage Service}[http://aws.amazon.com/s3] as a storage mechanism
7   - #
8   - # == Requirements
9   - #
10   - # Requires the {AWS::S3 Library}[http://amazon.rubyforge.org] for S3 by Marcel Molina Jr. installed either
11   - # as a gem or a as a Rails plugin.
12   - #
13   - # == Configuration
14   - #
15   - # Configuration is done via <tt>#{Rails.root}/config/amazon_s3.yml</tt> and is loaded according to the <tt>#{Rails.env}</tt>.
16   - # The minimum connection options that you must specify are a bucket name, your access key id and your secret access key.
17   - # If you don't already have your access keys, all you need to sign up for the S3 service is an account at Amazon.
18   - # You can sign up for S3 and get access keys by visiting http://aws.amazon.com/s3.
19   - #
20   - # If you wish to use Amazon CloudFront to serve the files, you can also specify a distibution domain for the bucket.
21   - # To read more about CloudFront, visit http://aws.amazon.com/cloudfront
22   - #
23   - # Example configuration (#{Rails.root}/config/amazon_s3.yml)
24   - #
25   - # development:
26   - # bucket_name: appname_development
27   - # access_key_id: <your key>
28   - # secret_access_key: <your key>
29   - # distribution_domain: XXXX.cloudfront.net
30   - #
31   - # test:
32   - # bucket_name: appname_test
33   - # access_key_id: <your key>
34   - # secret_access_key: <your key>
35   - # distribution_domain: XXXX.cloudfront.net
36   - #
37   - # production:
38   - # bucket_name: appname
39   - # access_key_id: <your key>
40   - # secret_access_key: <your key>
41   - # distribution_domain: XXXX.cloudfront.net
42   - #
43   - # You can change the location of the config path by passing a full path to the :s3_config_path option.
44   - #
45   - # has_attachment :storage => :s3, :s3_config_path => (#{Rails.root} + '/config/s3.yml')
46   - #
47   - # === Required configuration parameters
48   - #
49   - # * <tt>:access_key_id</tt> - The access key id for your S3 account. Provided by Amazon.
50   - # * <tt>:secret_access_key</tt> - The secret access key for your S3 account. Provided by Amazon.
51   - # * <tt>:bucket_name</tt> - A unique bucket name (think of the bucket_name as being like a database name).
52   - #
53   - # If any of these required arguments is missing, a MissingAccessKey exception will be raised from AWS::S3.
54   - #
55   - # == About bucket names
56   - #
57   - # Bucket names have to be globaly unique across the S3 system. And you can only have up to 100 of them,
58   - # so it's a good idea to think of a bucket as being like a database, hence the correspondance in this
59   - # implementation to the development, test, and production environments.
60   - #
61   - # The number of objects you can store in a bucket is, for all intents and purposes, unlimited.
62   - #
63   - # === Optional configuration parameters
64   - #
65   - # * <tt>:server</tt> - The server to make requests to. Defaults to <tt>s3.amazonaws.com</tt>.
66   - # * <tt>:port</tt> - The port to the requests should be made on. Defaults to 80 or 443 if <tt>:use_ssl</tt> is set.
67   - # * <tt>:use_ssl</tt> - If set to true, <tt>:port</tt> will be implicitly set to 443, unless specified otherwise. Defaults to false.
68   - # * <tt>:distribution_domain</tt> - The CloudFront distribution domain for the bucket. This can either be the assigned
69   - # distribution domain (ie. XXX.cloudfront.net) or a chosen domain using a CNAME. See CloudFront for more details.
70   - #
71   - # == Usage
72   - #
73   - # To specify S3 as the storage mechanism for a model, set the acts_as_attachment <tt>:storage</tt> option to <tt>:s3</tt>.
74   - #
75   - # class Photo < ActiveRecord::Base
76   - # has_attachment :storage => :s3
77   - # end
78   - #
79   - # === Customizing the path
80   - #
81   - # By default, files are prefixed using a pseudo hierarchy in the form of <tt>:table_name/:id</tt>, which results
82   - # in S3 urls that look like: http(s)://:server/:bucket_name/:table_name/:id/:filename with :table_name
83   - # representing the customizable portion of the path. You can customize this prefix using the <tt>:path_prefix</tt>
84   - # option:
85   - #
86   - # class Photo < ActiveRecord::Base
87   - # has_attachment :storage => :s3, :path_prefix => 'my/custom/path'
88   - # end
89   - #
90   - # Which would result in URLs like <tt>http(s)://:server/:bucket_name/my/custom/path/:id/:filename.</tt>
91   - #
92   - # === Using different bucket names on different models
93   - #
94   - # By default the bucket name that the file will be stored to is the one specified by the
95   - # <tt>:bucket_name</tt> key in the amazon_s3.yml file. You can use the <tt>:bucket_key</tt> option
96   - # to overide this behavior on a per model basis. For instance if you want a bucket that will hold
97   - # only Photos you can do this:
98   - #
99   - # class Photo < ActiveRecord::Base
100   - # has_attachment :storage => :s3, :bucket_key => :photo_bucket_name
101   - # end
102   - #
103   - # And then your amazon_s3.yml file needs to look like this.
104   - #
105   - # development:
106   - # bucket_name: appname_development
107   - # access_key_id: <your key>
108   - # secret_access_key: <your key>
109   - #
110   - # test:
111   - # bucket_name: appname_test
112   - # access_key_id: <your key>
113   - # secret_access_key: <your key>
114   - #
115   - # production:
116   - # bucket_name: appname
117   - # photo_bucket_name: appname_photos
118   - # access_key_id: <your key>
119   - # secret_access_key: <your key>
120   - #
121   - # If the bucket_key you specify is not there in a certain environment then attachment_fu will
122   - # default to the <tt>bucket_name</tt> key. This way you only have to create special buckets
123   - # this can be helpful if you only need special buckets in certain environments.
124   - #
125   - # === Permissions
126   - #
127   - # By default, files are stored on S3 with public access permissions. You can customize this using
128   - # the <tt>:s3_access</tt> option to <tt>has_attachment</tt>. Available values are
129   - # <tt>:private</tt>, <tt>:public_read_write</tt>, and <tt>:authenticated_read</tt>.
130   - #
131   - # === Other options
132   - #
133   - # Of course, all the usual configuration options apply, such as content_type and thumbnails:
134   - #
135   - # class Photo < ActiveRecord::Base
136   - # has_attachment :storage => :s3, :content_type => ['application/pdf', :image], :resize_to => 'x50'
137   - # has_attachment :storage => :s3, :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }
138   - # end
139   - #
140   - # === Accessing S3 URLs
141   - #
142   - # You can get an object's URL using the s3_url accessor. For example, assuming that for your postcard app
143   - # you had a bucket name like 'postcard_world_development', and an attachment model called Photo:
144   - #
145   - # @postcard.s3_url # => http(s)://s3.amazonaws.com/postcard_world_development/photos/1/mexico.jpg
146   - #
147   - # The resulting url is in the form: http(s)://:server/:bucket_name/:table_name/:id/:file.
148   - # The optional thumbnail argument will output the thumbnail's filename (if any).
149   - #
150   - # Additionally, you can get an object's base path relative to the bucket root using
151   - # <tt>base_path</tt>:
152   - #
153   - # @photo.file_base_path # => photos/1
154   - #
155   - # And the full path (including the filename) using <tt>full_filename</tt>:
156   - #
157   - # @photo.full_filename # => photos/
158   - #
159   - # Niether <tt>base_path</tt> or <tt>full_filename</tt> include the bucket name as part of the path.
160   - # You can retrieve the bucket name using the <tt>bucket_name</tt> method.
161   - #
162   - # === Accessing CloudFront URLs
163   - #
164   - # You can get an object's CloudFront URL using the cloudfront_url accessor. Using the example from above:
165   - # @postcard.cloudfront_url # => http://XXXX.cloudfront.net/photos/1/mexico.jpg
166   - #
167   - # The resulting url is in the form: http://:distribution_domain/:table_name/:id/:file
168   - #
169   - # If you set :cloudfront to true in your model, the public_filename will be the CloudFront
170   - # URL, not the S3 URL.
171   - module S3Backend
172   - class RequiredLibraryNotFoundError < StandardError; end
173   - class ConfigFileNotFoundError < StandardError; end
174   -
175   - def self.included(base) #:nodoc:
176   - mattr_reader :bucket_name, :s3_config
177   -
178   - begin
179   - require 'aws/s3'
180   - include AWS::S3
181   - rescue LoadError
182   - raise RequiredLibraryNotFoundError.new('AWS::S3 could not be loaded')
183   - end
184   -
185   - begin
186   - @@s3_config_path = base.attachment_options[:s3_config_path] || File.join(Rails.root, 'config', 'amazon_s3.yml')
187   - @@s3_config = @@s3_config = YAML.load(ERB.new(File.read(@@s3_config_path)).result)[Rails.env].symbolize_keys
188   - #rescue
189   - # raise ConfigFileNotFoundError.new('File %s not found' % @@s3_config_path)
190   - end
191   -
192   - bucket_key = base.attachment_options[:bucket_key]
193   -
194   - if bucket_key and s3_config[bucket_key.to_sym]
195   - eval_string = "def bucket_name()\n \"#{s3_config[bucket_key.to_sym]}\"\nend"
196   - else
197   - eval_string = "def bucket_name()\n \"#{s3_config[:bucket_name]}\"\nend"
198   - end
199   - base.class_eval(eval_string, __FILE__, __LINE__)
200   -
201   - Base.establish_connection!(s3_config.slice(:access_key_id, :secret_access_key, :server, :port, :use_ssl, :persistent, :proxy))
202   -
203   - # Bucket.create(@@bucket_name)
204   -
205   - base.before_update :rename_file
206   - end
207   -
208   - def self.protocol
209   - @protocol ||= s3_config[:use_ssl] ? 'https://' : 'http://'
210   - end
211   -
212   - def self.hostname
213   - @hostname ||= s3_config[:server] || AWS::S3::DEFAULT_HOST
214   - end
215   -
216   - def self.port_string
217   - @port_string ||= (s3_config[:port].nil? || s3_config[:port] == (s3_config[:use_ssl] ? 443 : 80)) ? '' : ":#{s3_config[:port]}"
218   - end
219   -
220   - def self.distribution_domain
221   - @distribution_domain = s3_config[:distribution_domain]
222   - end
223   -
224   - module ClassMethods
225   - def s3_protocol
226   - Technoweenie::AttachmentFu::Backends::S3Backend.protocol
227   - end
228   -
229   - def s3_hostname
230   - Technoweenie::AttachmentFu::Backends::S3Backend.hostname
231   - end
232   -
233   - def s3_port_string
234   - Technoweenie::AttachmentFu::Backends::S3Backend.port_string
235   - end
236   -
237   - def cloudfront_distribution_domain
238   - Technoweenie::AttachmentFu::Backends::S3Backend.distribution_domain
239   - end
240   - end
241   -
242   - # Overwrites the base filename writer in order to store the old filename
243   - def filename=(value)
244   - @old_filename = filename unless filename.nil? || @old_filename
245   - write_attribute :filename, sanitize_filename(value)
246   - end
247   -
248   - # The attachment ID used in the full path of a file
249   - def attachment_path_id
250   - ((respond_to?(:parent_id) && parent_id) || id).to_s
251   - end
252   -
253   - # The pseudo hierarchy containing the file relative to the bucket name
254   - # Example: <tt>:table_name/:id</tt>
255   - def base_path
256   - File.join(attachment_options[:path_prefix], attachment_path_id)
257   - end
258   -
259   - # The full path to the file relative to the bucket name
260   - # Example: <tt>:table_name/:id/:filename</tt>
261   - def full_filename(thumbnail = nil)
262   - File.join(base_path, thumbnail_name_for(thumbnail))
263   - end
264   -
265   - # All public objects are accessible via a GET request to the S3 servers. You can generate a
266   - # url for an object using the s3_url method.
267   - #
268   - # @photo.s3_url
269   - #
270   - # The resulting url is in the form: <tt>http(s)://:server/:bucket_name/:table_name/:id/:file</tt> where
271   - # the <tt>:server</tt> variable defaults to <tt>AWS::S3 URL::DEFAULT_HOST</tt> (s3.amazonaws.com) and can be
272   - # set using the configuration parameters in <tt>#{Rails.root}/config/amazon_s3.yml</tt>.
273   - #
274   - # The optional thumbnail argument will output the thumbnail's filename (if any).
275   - def s3_url(thumbnail = nil)
276   - File.join(s3_protocol + s3_hostname + s3_port_string, bucket_name, full_filename(thumbnail))
277   - end
278   -
279   - # All public objects are accessible via a GET request to CloudFront. You can generate a
280   - # url for an object using the cloudfront_url method.
281   - #
282   - # @photo.cloudfront_url
283   - #
284   - # The resulting url is in the form: <tt>http://:distribution_domain/:table_name/:id/:file</tt> using
285   - # the <tt>:distribution_domain</tt> variable set in the configuration parameters in <tt>#{Rails.root}/config/amazon_s3.yml</tt>.
286   - #
287   - # The optional thumbnail argument will output the thumbnail's filename (if any).
288   - def cloudfront_url(thumbnail = nil)
289   - s3_protocol + cloudfront_distribution_domain + "/" + full_filename(thumbnail)
290   - end
291   -
292   - def public_filename(*args)
293   - if attachment_options[:cloudfront]
294   - cloudfront_url(*args)
295   - else
296   - s3_url(*args)
297   - end
298   - end
299   -
300   - # All private objects are accessible via an authenticated GET request to the S3 servers. You can generate an
301   - # authenticated url for an object like this:
302   - #
303   - # @photo.authenticated_s3_url
304   - #
305   - # By default authenticated urls expire 5 minutes after they were generated.
306   - #
307   - # Expiration options can be specified either with an absolute time using the <tt>:expires</tt> option,
308   - # or with a number of seconds relative to now with the <tt>:expires_in</tt> option:
309   - #
310   - # # Absolute expiration date (October 13th, 2025)
311   - # @photo.authenticated_s3_url(:expires => Time.mktime(2025,10,13).to_i)
312   - #
313   - # # Expiration in five hours from now
314   - # @photo.authenticated_s3_url(:expires_in => 5.hours)
315   - #
316   - # You can specify whether the url should go over SSL with the <tt>:use_ssl</tt> option.
317   - # By default, the ssl settings for the current connection will be used:
318   - #
319   - # @photo.authenticated_s3_url(:use_ssl => true)
320   - #
321   - # Finally, the optional thumbnail argument will output the thumbnail's filename (if any):
322   - #
323   - # @photo.authenticated_s3_url('thumbnail', :expires_in => 5.hours, :use_ssl => true)
324   - def authenticated_s3_url(*args)
325   - options = args.extract_options!
326   - options[:expires_in] = options[:expires_in].to_i if options[:expires_in]
327   - thumbnail = args.shift
328   - S3Object.url_for(full_filename(thumbnail), bucket_name, options)
329   - end
330   -
331   - def create_temp_file
332   - write_to_temp_file current_data
333   - end
334   -
335   - def current_data
336   - if attachment_options[:encrypted_storage] && self.respond_to?(:encryption_key) && self.encryption_key != nil
337   - EncryptedData.decrypt_data(S3Object.value(full_filename, bucket_name), self.encryption_key)
338   - else
339   - S3Object.value full_filename, bucket_name
340   - end
341   - end
342   -
343   - def s3_protocol
344   - Technoweenie::AttachmentFu::Backends::S3Backend.protocol
345   - end
346   -
347   - def s3_hostname
348   - Technoweenie::AttachmentFu::Backends::S3Backend.hostname
349   - end
350   -
351   - def s3_port_string
352   - Technoweenie::AttachmentFu::Backends::S3Backend.port_string
353   - end
354   -
355   - def cloudfront_distribution_domain
356   - Technoweenie::AttachmentFu::Backends::S3Backend.distribution_domain
357   - end
358   -
359   - protected
360   - # Called in the after_destroy callback
361   - def destroy_file
362   - S3Object.delete full_filename, bucket_name
363   - end
364   -
365   - def rename_file
366   - return unless @old_filename && @old_filename != filename
367   -
368   - old_full_filename = File.join(base_path, @old_filename)
369   -
370   - S3Object.rename(
371   - old_full_filename,
372   - full_filename,
373   - bucket_name,
374   - :access => attachment_options[:s3_access]
375   - )
376   -
377   - @old_filename = nil
378   - true
379   - end
380   -
381   - def save_to_storage
382   - if save_attachment?
383   - if attachment_options[:encrypted_storage]
384   - S3Object.store(
385   - full_filename,
386   - (temp_path ? File.open(temp_path) : temp_data),
387   - bucket_name,
388   - :content_type => content_type,
389   - :cache_control => attachment_options[:cache_control],
390   - :access => attachment_options[:s3_access],
391   - 'x-amz-server-side-encryption' => 'AES256',
392   - 'Content-Disposition' => "attachment; filename=\"#{filename}\""
393   - )
394   - else
395   - S3Object.store(
396   - full_filename,
397   - (temp_path ? File.open(temp_path) : temp_data),
398   - bucket_name,
399   - :content_type => content_type,
400   - :cache_control => attachment_options[:cache_control],
401   - :access => attachment_options[:s3_access]
402   - )
403   - end
404   - end
405   -
406   - @old_filename = nil
407   - true
408   - end
409   - end
410   - end
411   - end
412   -end
vendor/plugins/pothoven-attachment_fu/lib/technoweenie/attachment_fu/processors/core_image_processor.rb
... ... @@ -1,66 +0,0 @@
1   -require 'red_artisan/core_image/processor'
2   -
3   -module Technoweenie # :nodoc:
4   - module AttachmentFu # :nodoc:
5   - module Processors
6   - module CoreImageProcessor
7   - def self.included(base)
8   - base.send :extend, ClassMethods
9   - base.alias_method_chain :process_attachment, :processing
10   - end
11   -
12   - module ClassMethods
13   - def with_image(file, &block)
14   - block.call OSX::CIImage.from(file)
15   - end
16   - end
17   -
18   - protected
19   - def process_attachment_with_processing
20   - return unless process_attachment_without_processing
21   - with_image do |img|
22   - self.width = img.extent.size.width if respond_to?(:width)
23   - self.height = img.extent.size.height if respond_to?(:height)
24   - resize_image_or_thumbnail! img
25   - callback_with_args :after_resize, img
26   - end if image?
27   - end
28   -
29   - # Performs the actual resizing operation for a thumbnail
30   - def resize_image(img, size)
31   - processor = ::RedArtisan::CoreImage::Processor.new(img)
32   - size = size.first if size.is_a?(Array) && size.length == 1
33   - if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
34   - if size.is_a?(Fixnum)
35   - processor.fit(size)
36   - else
37   - processor.resize(size[0], size[1])
38   - end
39   - else
40   - new_size = [img.extent.size.width, img.extent.size.height] / size.to_s
41   - processor.resize(new_size[0], new_size[1])
42   - end
43   -
44   - processor.render do |result|
45   - self.width = result.extent.size.width if respond_to?(:width)
46   - self.height = result.extent.size.height if respond_to?(:height)
47   - out_file = random_tempfile_filename
48   - temp_paths.unshift Tempfile.new(out_file, Technoweenie::AttachmentFu.tempfile_path).path
49   - properties = nil
50   - # We don't check the source image since we're forcing the output to JPEG, apparently…
51   - # Beware: apparently CoreImage only takes the percentage as a HINT, using a different actual quality…
52   - quality = get_jpeg_quality
53   - properties = { OSX::NSImageCompressionFactor => quality / 100.0 } if quality
54   - result.save(self.temp_path, OSX::NSJPEGFileType, properties)
55   - #
56   - # puts "#{self.temp_path} @ #{quality.inspect} -> #{%x(identify -format '%Q' "#{self.temp_path}")}"
57   - #
58   - self.size = File.size(self.temp_path)
59   - end
60   - end
61   - end
62   - end
63   - end
64   -end
65   -
66   -
vendor/plugins/pothoven-attachment_fu/lib/technoweenie/attachment_fu/processors/gd2_processor.rb
... ... @@ -1,59 +0,0 @@
1   -require 'rubygems'
2   -require 'gd2'
3   -module Technoweenie # :nodoc:
4   - module AttachmentFu # :nodoc:
5   - module Processors
6   - module Gd2Processor
7   - def self.included(base)
8   - base.send :extend, ClassMethods
9   - base.alias_method_chain :process_attachment, :processing
10   - end
11   -
12   - module ClassMethods
13   - # Yields a block containing a GD2 Image for the given binary data.
14   - def with_image(file, &block)
15   - im = GD2::Image.import(file)
16   - block.call(im)
17   - end
18   - end
19   -
20   - protected
21   - def process_attachment_with_processing
22   - return unless process_attachment_without_processing && image?
23   - with_image do |img|
24   - resize_image_or_thumbnail! img
25   - self.width = img.width
26   - self.height = img.height
27   - callback_with_args :after_resize, img
28   - end
29   - end
30   -
31   - # Performs the actual resizing operation for a thumbnail
32   - def resize_image(img, size)
33   - size = size.first if size.is_a?(Array) && size.length == 1
34   - if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
35   - if size.is_a?(Fixnum)
36   - # Borrowed from image science's #thumbnail method and adapted
37   - # for this.
38   - scale = size.to_f / (img.width > img.height ? img.width.to_f : img.height.to_f)
39   - img.resize!((img.width * scale).round(1), (img.height * scale).round(1), false)
40   - else
41   - img.resize!(size.first, size.last, false)
42   - end
43   - else
44   - w, h = [img.width, img.height] / size.to_s
45   - img.resize!(w, h, false)
46   - end
47   - self.width = img.width if respond_to?(:width)
48   - self.height = img.height if respond_to?(:height)
49   - out_file = random_tempfile_filename
50   - temp_paths.unshift out_file
51   - jpeg = out_file =~ /\.jpe?g\z/i
52   - quality = jpeg && get_jpeg_quality
53   - self.size = img.export(self.temp_path, quality ? { :quality => quality } : {})
54   - end
55   -
56   - end
57   - end
58   - end
59   -end
60 0 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/lib/technoweenie/attachment_fu/processors/image_science_processor.rb
... ... @@ -1,80 +0,0 @@
1   -require 'image_science'
2   -module Technoweenie # :nodoc:
3   - module AttachmentFu # :nodoc:
4   - module Processors
5   - module ImageScienceProcessor
6   - def self.included(base)
7   - base.send :extend, ClassMethods
8   - base.alias_method_chain :process_attachment, :processing
9   - end
10   -
11   - module ClassMethods
12   - # Yields a block containing an Image Science image for the given binary data.
13   - def with_image(file, &block)
14   - ::ImageScience.with_image file, &block
15   - end
16   - end
17   -
18   - protected
19   - def process_attachment_with_processing
20   - return unless process_attachment_without_processing && image?
21   - with_image do |img|
22   - self.width = img.width if respond_to?(:width)
23   - self.height = img.height if respond_to?(:height)
24   - resize_image_or_thumbnail! img
25   - end
26   - end
27   -
28   - # Performs the actual resizing operation for a thumbnail
29   - def resize_image(img, size)
30   - # create a dummy temp file to write to
31   - # ImageScience doesn't handle all gifs properly, so it converts them to
32   - # pngs for thumbnails. It has something to do with trying to save gifs
33   - # with a larger palette than 256 colors, which is all the gif format
34   - # supports.
35   - filename.sub! /gif$/i, 'png'
36   - content_type.sub!(/gif$/, 'png')
37   - temp_paths.unshift write_to_temp_file(filename)
38   - grab_dimensions = lambda do |img|
39   - self.width = img.width if respond_to?(:width)
40   - self.height = img.height if respond_to?(:height)
41   -
42   - # We don't check for quality being a 0-100 value as we also allow FreeImage JPEG_xxx constants.
43   - quality = content_type[/jpe?g/i] && get_jpeg_quality(false)
44   - # Traditional ImageScience has a 1-arg save method, tdd-image_science has 1 mandatory + 1 optional
45   - if quality && img.method(:save).arity == -2
46   - img.save self.temp_path, quality
47   - else
48   - img.save self.temp_path
49   - end
50   - self.size = File.size(self.temp_path)
51   - callback_with_args :after_resize, img
52   - end
53   -
54   - size = size.first if size.is_a?(Array) && size.length == 1
55   - if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
56   - if size.is_a?(Fixnum)
57   - img.thumbnail(size, &grab_dimensions)
58   - else
59   - img.resize(size[0], size[1], &grab_dimensions)
60   - end
61   - else
62   - new_size = [img.width, img.height] / size.to_s
63   - if size.ends_with?('!')
64   - aspect = new_size[0].to_f / new_size[1].to_f
65   - ih, iw = img.height, img.width
66   - w, h = (ih * aspect), (iw / aspect)
67   - w = [iw, w].min.to_i
68   - h = [ih, h].min.to_i
69   - img.with_crop((iw-w)/2, (ih-h)/2, (iw+w)/2, (ih+h)/2) { |crop|
70   - crop.resize(new_size[0], new_size[1], &grab_dimensions)
71   - }
72   - else
73   - img.resize(new_size[0], new_size[1], &grab_dimensions)
74   - end
75   - end
76   - end
77   - end
78   - end
79   - end
80   -end
81 0 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/lib/technoweenie/attachment_fu/processors/mini_magick_processor.rb
... ... @@ -1,142 +0,0 @@
1   -require 'mini_magick'
2   -module Technoweenie # :nodoc:
3   - module AttachmentFu # :nodoc:
4   - module Processors
5   - module MiniMagickProcessor
6   - def self.included(base)
7   - base.send :extend, ClassMethods
8   - base.alias_method_chain :process_attachment, :processing
9   - end
10   -
11   - module ClassMethods
12   - # Yields a block containing an MiniMagick Image for the given binary data.
13   - def with_image(file, &block)
14   - begin
15   - binary_data = file.is_a?(MiniMagick::Image) ? file : MiniMagick::Image.open(file) unless !Object.const_defined?(:MiniMagick)
16   - rescue
17   - # Log the failure to load the image.
18   - logger.debug("Exception working with image: #{$!}")
19   - binary_data = nil
20   - end
21   - block.call binary_data if block && binary_data
22   - ensure
23   - !binary_data.nil?
24   - end
25   - end
26   -
27   - protected
28   - def process_attachment_with_processing
29   - return unless process_attachment_without_processing
30   - with_image do |img|
31   - resize_image_or_thumbnail! img
32   - self.width = img[:width] if respond_to?(:width)
33   - self.height = img[:height] if respond_to?(:height)
34   - callback_with_args :after_resize, img
35   - end if image?
36   - end
37   -
38   - # Performs the actual resizing operation for a thumbnail
39   - def resize_image(img, size)
40   - size = size.first if size.is_a?(Array) && size.length == 1
41   - format = img[:format]
42   - img.combine_options do |commands|
43   - commands.strip unless attachment_options[:keep_profile]
44   -
45   - # GIF is not handled correctly, so we move to PNG, as in other processors…
46   - if format == 'GIF'
47   - img.format('PNG')
48   - end
49   -
50   - if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
51   - if size.is_a?(Fixnum)
52   - size = [size, size]
53   - commands.resize(size.join('x'))
54   - else
55   - commands.resize(size.join('x') + '!')
56   - end
57   - # extend to thumbnail size
58   - elsif size.is_a?(String) and size =~ /e$/
59   - size = size.gsub(/e/, '')
60   - commands.resize(size.to_s + '>')
61   - commands.background('#ffffff')
62   - commands.gravity('center')
63   - commands.extent(size)
64   - # crop thumbnail, the smart way
65   - elsif size.is_a?(String) and size =~ /c$/
66   - size = size.gsub(/c/, '')
67   -
68   - # calculate sizes and aspect ratio
69   - thumb_width, thumb_height = size.split("x")
70   - thumb_width = thumb_width.to_f
71   - thumb_height = thumb_height.to_f
72   -
73   - thumb_aspect = thumb_width.to_f / thumb_height.to_f
74   - image_width, image_height = img[:width].to_f, img[:height].to_f
75   - image_aspect = image_width / image_height
76   -
77   - # only crop if image is not smaller in both dimensions
78   - unless image_width < thumb_width and image_height < thumb_height
79   - command = calculate_offset(image_width,image_height,image_aspect,thumb_width,thumb_height,thumb_aspect)
80   -
81   - # crop image
82   - commands.extract(command)
83   - end
84   -
85   - # don not resize if image is not as height or width then thumbnail
86   - if image_width < thumb_width or image_height < thumb_height
87   - commands.background('#ffffff')
88   - commands.gravity('center')
89   - commands.extent(size)
90   - # resize image
91   - else
92   - commands.resize("#{size.to_s}")
93   - end
94   - # crop end
95   - else
96   - commands.resize(size.to_s)
97   - end
98   - end
99   - dims = img[:dimensions]
100   - self.width = dims[0] if respond_to?(:width)
101   - self.height = dims[1] if respond_to?(:height)
102   - # Has to be done this far so we get proper dimensions
103   - if format == 'JPEG'
104   - quality = get_jpeg_quality
105   - img.quality(quality) if quality
106   - end
107   - temp_paths.unshift img
108   - self.size = File.size(self.temp_path)
109   - end
110   -
111   - def calculate_offset(image_width,image_height,image_aspect,thumb_width,thumb_height,thumb_aspect)
112   - # only crop if image is not smaller in both dimensions
113   -
114   - # special cases, image smaller in one dimension then thumbsize
115   - if image_width < thumb_width
116   - offset = (image_height / 2) - (thumb_height / 2)
117   - command = "#{image_width}x#{thumb_height}+0+#{offset}"
118   - elsif image_height < thumb_height
119   - offset = (image_width / 2) - (thumb_width / 2)
120   - command = "#{thumb_width}x#{image_height}+#{offset}+0"
121   -
122   - # normal thumbnail generation
123   - # calculate height and offset y, width is fixed
124   - elsif (image_aspect <= thumb_aspect or image_width < thumb_width) and image_height > thumb_height
125   - height = image_width / thumb_aspect
126   - offset = (image_height / 2) - (height / 2)
127   - command = "#{image_width}x#{height}+0+#{offset}"
128   - # calculate width and offset x, height is fixed
129   - else
130   - width = image_height * thumb_aspect
131   - offset = (image_width / 2) - (width / 2)
132   - command = "#{width}x#{image_height}+#{offset}+0"
133   - end
134   - # crop image
135   - command
136   - end
137   -
138   -
139   - end
140   - end
141   - end
142   -end
143 0 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/lib/technoweenie/attachment_fu/processors/rmagick_processor.rb
... ... @@ -1,66 +0,0 @@
1   -require 'RMagick'
2   -module Technoweenie # :nodoc:
3   - module AttachmentFu # :nodoc:
4   - module Processors
5   - module RmagickProcessor
6   - def self.included(base)
7   - base.send :extend, ClassMethods
8   - base.alias_method_chain :process_attachment, :processing
9   - end
10   -
11   - module ClassMethods
12   - # Yields a block containing an RMagick Image for the given binary data.
13   - def with_image(file, &block)
14   - begin
15   - binary_data = file.is_a?(Magick::Image) ? file : Magick::Image.read(file).first unless !Object.const_defined?(:Magick)
16   - binary_data && binary_data.auto_orient!
17   - rescue
18   - # Log the failure to load the image. This should match ::Magick::ImageMagickError
19   - # but that would cause acts_as_attachment to require rmagick.
20   - logger.debug("Exception working with image: #{$!}")
21   - binary_data = nil
22   - end
23   - block.call binary_data if block && binary_data
24   - ensure
25   - !binary_data.nil?
26   - end
27   - end
28   -
29   - protected
30   - def process_attachment_with_processing
31   - return unless process_attachment_without_processing
32   - with_image do |img|
33   - resize_image_or_thumbnail! img
34   - self.width = img.columns if respond_to?(:width)
35   - self.height = img.rows if respond_to?(:height)
36   - callback_with_args :after_resize, img
37   - end if image?
38   - end
39   -
40   - # Performs the actual resizing operation for a thumbnail
41   - def resize_image(img, size)
42   - size = size.first if size.is_a?(Array) && size.length == 1 && !size.first.is_a?(Fixnum)
43   - if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
44   - size = [size, size] if size.is_a?(Fixnum)
45   - img.thumbnail!(*size)
46   - elsif size.is_a?(String) && size =~ /^c.*$/ # Image cropping - example geometry string: c75x75
47   - dimensions = size[1..size.size].split("x")
48   - img.crop_resized!(dimensions[0].to_i, dimensions[1].to_i)
49   - else
50   - img.change_geometry(size.to_s) { |cols, rows, image|
51   - image.resize!(cols<1 ? 1 : cols, rows<1 ? 1 : rows)
52   - }
53   - end
54   - self.width = img.columns if respond_to?(:width)
55   - self.height = img.rows if respond_to?(:height)
56   - img = img.sharpen if attachment_options[:sharpen_on_resize] && img.changed?
57   - img.strip! unless attachment_options[:keep_profile]
58   - quality = img.format.to_s[/JPEG/] && get_jpeg_quality
59   - out_file = write_to_temp_file(img.to_blob { self.quality = quality if quality })
60   - temp_paths.unshift out_file
61   - self.size = File.size(self.temp_path)
62   - end
63   - end
64   - end
65   - end
66   -end
vendor/plugins/pothoven-attachment_fu/rackspace_cloudfiles.yml.tpl
... ... @@ -1,14 +0,0 @@
1   -development:
2   - container_name: appname_development
3   - username:
4   - api_key:
5   -
6   -test:
7   - container_name: appname_test
8   - username:
9   - api_key:
10   -
11   -production:
12   - container_name: appname_production
13   - username:
14   - api_key:
vendor/plugins/pothoven-attachment_fu/test/backends/db_file_test.rb
... ... @@ -1,16 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
2   -
3   -class DbFileTest < Test::Unit::TestCase
4   - include BaseAttachmentTests
5   - attachment_model Attachment
6   -
7   - def test_should_call_after_attachment_saved(klass = Attachment)
8   - attachment_model.saves = 0
9   - assert_created do
10   - upload_file :filename => '/files/rails.png'
11   - end
12   - assert_equal 1, attachment_model.saves
13   - end
14   -
15   - test_against_subclass :test_should_call_after_attachment_saved, Attachment
16   -end
17 0 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/test/backends/file_system_test.rb
... ... @@ -1,143 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
2   -require 'digest/sha2'
3   -
4   -class FileSystemTest < Test::Unit::TestCase
5   - include BaseAttachmentTests
6   - attachment_model FileAttachment
7   -
8   - def test_filesystem_size_for_file_attachment(klass = FileAttachment)
9   - attachment_model klass
10   - assert_created 1 do
11   - attachment = upload_file :filename => '/files/rails.png'
12   - assert_equal attachment.size, File.open(attachment.full_filename).stat.size
13   - end
14   - end
15   -
16   - test_against_subclass :test_filesystem_size_for_file_attachment, FileAttachment
17   -
18   - def test_should_not_overwrite_file_attachment(klass = FileAttachment)
19   - attachment_model klass
20   - assert_created 2 do
21   - real = upload_file :filename => '/files/rails.png'
22   - assert_valid real
23   - assert !real.new_record?, real.errors.full_messages.join("\n")
24   - assert !real.size.zero?
25   -
26   - fake = upload_file :filename => '/files/fake/rails.png'
27   - assert_valid fake
28   - assert !fake.size.zero?
29   -
30   - assert_not_equal File.open(real.full_filename).stat.size, File.open(fake.full_filename).stat.size
31   - end
32   - end
33   -
34   - test_against_subclass :test_should_not_overwrite_file_attachment, FileAttachment
35   -
36   - def test_should_store_file_attachment_in_filesystem(klass = FileAttachment)
37   - attachment_model klass
38   - attachment = nil
39   - assert_created do
40   - attachment = upload_file :filename => '/files/rails.png'
41   - assert_valid attachment
42   - assert File.exists?(attachment.full_filename), "#{attachment.full_filename} does not exist"
43   - end
44   - attachment
45   - end
46   -
47   - test_against_subclass :test_should_store_file_attachment_in_filesystem, FileAttachment
48   -
49   - def test_should_delete_old_file_when_updating(klass = FileAttachment)
50   - attachment_model klass
51   - attachment = upload_file :filename => '/files/rails.png'
52   - old_filename = attachment.full_filename
53   - assert_not_created do
54   - use_temp_file 'files/rails.png' do |file|
55   - attachment.filename = 'rails2.png'
56   - attachment.temp_paths.unshift File.join(FIXTURE_PATH, file)
57   - attachment.save!
58   - assert File.exists?(attachment.full_filename), "#{attachment.full_filename} does not exist"
59   - assert !File.exists?(old_filename), "#{old_filename} still exists"
60   - end
61   - end
62   - end
63   -
64   - test_against_subclass :test_should_delete_old_file_when_updating, FileAttachment
65   -
66   - def test_should_delete_old_file_when_renaming(klass = FileAttachment)
67   - attachment_model klass
68   - attachment = upload_file :filename => '/files/rails.png'
69   - old_filename = attachment.full_filename
70   - assert_not_created do
71   - attachment.filename = 'rails2.png'
72   - attachment.save
73   - assert File.exists?(attachment.full_filename), "#{attachment.full_filename} does not exist"
74   - assert !File.exists?(old_filename), "#{old_filename} still exists"
75   - assert !attachment.reload.size.zero?
76   - assert_equal 'rails2.png', attachment.filename
77   - end
78   - end
79   -
80   - test_against_subclass :test_should_delete_old_file_when_renaming, FileAttachment
81   -
82   - def test_path_partitioning_works_on_integer_id(klass = FileAttachment)
83   - attachment_model klass
84   -
85   - # Create a random attachment object, doesn't matter what.
86   - attachment = upload_file :filename => '/files/rails.png'
87   - old_id = attachment.id
88   - attachment.id = 1
89   -
90   - begin
91   - assert_equal ["0000", "0001", "bar.txt"], attachment.send(:partitioned_path, "bar.txt")
92   - ensure
93   - attachment.id = old_id
94   - end
95   - end
96   -
97   - test_against_subclass :test_path_partitioning_works_on_integer_id, FileAttachment
98   -
99   - def test_path_partitioning_with_string_id_works_by_generating_hash(klass = FileAttachmentWithStringId)
100   - attachment_model klass
101   -
102   - # Create a random attachment object, doesn't matter what.
103   - attachment = upload_file :filename => '/files/rails.png'
104   - old_id = attachment.id
105   - attachment.id = "hello world some long string"
106   - hash = Digest::SHA512.hexdigest("hello world some long string")
107   -
108   - begin
109   - assert_equal [
110   - hash[0..31],
111   - hash[32..63],
112   - hash[64..95],
113   - hash[96..127],
114   - "bar.txt"
115   - ], attachment.send(:partitioned_path, "bar.txt")
116   - ensure
117   - attachment.id = old_id
118   - end
119   - end
120   -
121   - test_against_subclass :test_path_partitioning_with_string_id_works_by_generating_hash, FileAttachmentWithStringId
122   -
123   - def test_path_partition_string_id_hashing_is_turned_off_if_id_is_uuid(klass = FileAttachmentWithUuid)
124   - attachment_model klass
125   -
126   - # Create a random attachment object, doesn't matter what.
127   - attachment = upload_file :filename => '/files/rails.png'
128   - old_id = attachment.id
129   - attachment.id = "0c0743b698483569dc65909a8cdb3bf9"
130   -
131   - begin
132   - assert_equal [
133   - "0c0743b698483569",
134   - "dc65909a8cdb3bf9",
135   - "bar.txt"
136   - ], attachment.send(:partitioned_path, "bar.txt")
137   - ensure
138   - attachment.id = old_id
139   - end
140   - end
141   -
142   - test_against_subclass :test_path_partition_string_id_hashing_is_turned_off_if_id_is_uuid, FileAttachmentWithUuid
143   -end
vendor/plugins/pothoven-attachment_fu/test/backends/remote/cloudfiles_test.rb
... ... @@ -1,102 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper'))
2   -require 'net/http'
3   -
4   -class CloudfilesTest < Test::Unit::TestCase
5   - def self.test_CloudFiles?
6   - true unless ENV["TEST_CLOUDFILES"] == "false"
7   - end
8   -
9   - if test_CloudFiles? && File.exist?(File.join(File.dirname(__FILE__), '../../rackspace_cloudfiles.yml'))
10   - include BaseAttachmentTests
11   - attachment_model CloudFilesAttachment
12   -
13   - def test_should_create_correct_container_name(klass = CloudFilesAttachment)
14   - attachment_model klass
15   - attachment = upload_file :filename => '/files/rails.png'
16   - assert_equal attachment.cloudfiles_config[:container_name], attachment.container_name
17   - end
18   -
19   - test_against_subclass :test_should_create_correct_container_name, CloudFilesAttachment
20   -
21   - def test_should_create_default_path_prefix(klass = CloudFilesAttachment)
22   - attachment_model klass
23   - attachment = upload_file :filename => '/files/rails.png'
24   - assert_equal File.join(attachment_model.table_name, attachment.attachment_path_id), attachment.base_path
25   - end
26   -
27   - test_against_subclass :test_should_create_default_path_prefix, CloudFilesAttachment
28   -
29   - def test_should_create_custom_path_prefix(klass = CloudFilesWithPathPrefixAttachment)
30   - attachment_model klass
31   - attachment = upload_file :filename => '/files/rails.png'
32   - assert_equal File.join('some/custom/path/prefix', attachment.attachment_path_id), attachment.base_path
33   - end
34   -
35   - test_against_subclass :test_should_create_custom_path_prefix, CloudFilesWithPathPrefixAttachment
36   -
37   -
38   - def test_should_create_valid_url(klass = CloudFilesAttachment)
39   - attachment_model klass
40   - attachment = upload_file :filename => '/files/rails.png'
41   - assert_match(%r!http://cdn.cloudfiles.mosso.com/(.*?)/cloud_files_attachments/1/rails.png!, attachment.cloudfiles_url)
42   - end
43   -
44   - test_against_subclass :test_should_create_valid_url, CloudFilesAttachment
45   -
46   - def test_should_save_attachment(klass = CloudFilesAttachment)
47   - attachment_model klass
48   - assert_created do
49   - attachment = upload_file :filename => '/files/rails.png'
50   - assert_valid attachment
51   - assert attachment.image?
52   - assert !attachment.size.zero?
53   - assert_kind_of Net::HTTPOK, http_response_for(attachment.cloudfiles_url)
54   - end
55   - end
56   -
57   - test_against_subclass :test_should_save_attachment, CloudFilesAttachment
58   -
59   - def test_should_delete_attachment_from_cloud_files_when_attachment_record_destroyed(klass = CloudFilesAttachment)
60   - attachment_model klass
61   - attachment = upload_file :filename => '/files/rails.png'
62   -
63   - urls = [attachment.cloudfiles_url] + attachment.thumbnails.collect(&:cloudfiles_url)
64   -
65   - urls.each {|url| assert_kind_of Net::HTTPOK, http_response_for(url) }
66   - attachment.destroy
67   - urls.each do |url|
68   - begin
69   - http_response_for(url)
70   - rescue Net::HTTPForbidden, Net::HTTPNotFound
71   - nil
72   - end
73   - end
74   - end
75   -
76   - test_against_subclass :test_should_delete_attachment_from_cloud_files_when_attachment_record_destroyed, CloudFilesAttachment
77   -
78   -
79   -
80   - protected
81   - def http_response_for(url)
82   - url = URI.parse(url)
83   - Net::HTTP.start(url.host, url.port) {|http| http.request_head(url.path) }
84   - end
85   -
86   - def s3_protocol
87   - Technoweenie::AttachmentFu::Backends::S3Backend.protocol
88   - end
89   -
90   - def s3_hostname
91   - Technoweenie::AttachmentFu::Backends::S3Backend.hostname
92   - end
93   -
94   - def s3_port_string
95   - Technoweenie::AttachmentFu::Backends::S3Backend.port_string
96   - end
97   - else
98   - def test_flunk_s3
99   - puts "s3 config file not loaded, tests not running"
100   - end
101   - end
102   -end
103 0 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/test/backends/remote/s3_test.rb
... ... @@ -1,119 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper'))
2   -require 'net/http'
3   -
4   -class S3Test < Test::Unit::TestCase
5   - def self.test_S3?
6   - true unless ENV["TEST_S3"] == "false"
7   - end
8   -
9   - if test_S3? && File.exist?(File.join(File.dirname(__FILE__), '../../amazon_s3.yml'))
10   - include BaseAttachmentTests
11   - attachment_model S3Attachment
12   -
13   - def test_should_create_correct_bucket_name(klass = S3Attachment)
14   - attachment_model klass
15   - attachment = upload_file :filename => '/files/rails.png'
16   - assert_equal attachment.s3_config[:bucket_name], attachment.bucket_name
17   - end
18   -
19   - test_against_subclass :test_should_create_correct_bucket_name, S3Attachment
20   -
21   - def test_should_create_default_path_prefix(klass = S3Attachment)
22   - attachment_model klass
23   - attachment = upload_file :filename => '/files/rails.png'
24   - assert_equal File.join(attachment_model.table_name, attachment.attachment_path_id), attachment.base_path
25   - end
26   -
27   - test_against_subclass :test_should_create_default_path_prefix, S3Attachment
28   -
29   - def test_should_create_custom_path_prefix(klass = S3WithPathPrefixAttachment)
30   - attachment_model klass
31   - attachment = upload_file :filename => '/files/rails.png'
32   - assert_equal File.join('some/custom/path/prefix', attachment.attachment_path_id), attachment.base_path
33   - end
34   -
35   - test_against_subclass :test_should_create_custom_path_prefix, S3WithPathPrefixAttachment
36   -
37   - def test_should_create_valid_url(klass = S3Attachment)
38   - attachment_model klass
39   - attachment = upload_file :filename => '/files/rails.png'
40   - assert_equal "#{s3_protocol}#{s3_hostname}#{s3_port_string}/#{attachment.bucket_name}/#{attachment.full_filename}", attachment.s3_url
41   - end
42   -
43   - test_against_subclass :test_should_create_valid_url, S3Attachment
44   -
45   - def test_should_create_authenticated_url(klass = S3Attachment)
46   - attachment_model klass
47   - attachment = upload_file :filename => '/files/rails.png'
48   - assert_match /^http.+AWSAccessKeyId.+Expires.+Signature.+/, attachment.authenticated_s3_url(:use_ssl => true)
49   - end
50   -
51   - test_against_subclass :test_should_create_authenticated_url, S3Attachment
52   -
53   - def test_should_create_authenticated_url_for_thumbnail(klass = S3Attachment)
54   - attachment_model klass
55   - attachment = upload_file :filename => '/files/rails.png'
56   - ['large', :large].each do |thumbnail|
57   - assert_match(
58   - /^http.+rails_large\.png.+AWSAccessKeyId.+Expires.+Signature/,
59   - attachment.authenticated_s3_url(thumbnail),
60   - "authenticated_s3_url failed with #{thumbnail.class} parameter"
61   - )
62   - end
63   - end
64   -
65   - def test_should_save_attachment(klass = S3Attachment)
66   - attachment_model klass
67   - assert_created do
68   - attachment = upload_file :filename => '/files/rails.png'
69   - assert_valid attachment
70   - assert attachment.image?
71   - assert !attachment.size.zero?
72   - assert_kind_of Net::HTTPOK, http_response_for(attachment.s3_url)
73   - end
74   - end
75   -
76   - test_against_subclass :test_should_save_attachment, S3Attachment
77   -
78   - def test_should_delete_attachment_from_s3_when_attachment_record_destroyed(klass = S3Attachment)
79   - attachment_model klass
80   - attachment = upload_file :filename => '/files/rails.png'
81   -
82   - urls = [attachment.s3_url] + attachment.thumbnails.collect(&:s3_url)
83   -
84   - urls.each {|url| assert_kind_of Net::HTTPOK, http_response_for(url) }
85   - attachment.destroy
86   - urls.each do |url|
87   - begin
88   - http_response_for(url)
89   - rescue Net::HTTPForbidden, Net::HTTPNotFound
90   - nil
91   - end
92   - end
93   - end
94   -
95   - test_against_subclass :test_should_delete_attachment_from_s3_when_attachment_record_destroyed, S3Attachment
96   -
97   - protected
98   - def http_response_for(url)
99   - url = URI.parse(url)
100   - Net::HTTP.start(url.host, url.port) {|http| http.request_head(url.path) }
101   - end
102   -
103   - def s3_protocol
104   - Technoweenie::AttachmentFu::Backends::S3Backend.protocol
105   - end
106   -
107   - def s3_hostname
108   - Technoweenie::AttachmentFu::Backends::S3Backend.hostname
109   - end
110   -
111   - def s3_port_string
112   - Technoweenie::AttachmentFu::Backends::S3Backend.port_string
113   - end
114   - else
115   - def test_flunk_s3
116   - puts "s3 config file not loaded, tests not running"
117   - end
118   - end
119   -end
120 0 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/test/base_attachment_tests.rb
... ... @@ -1,77 +0,0 @@
1   -module BaseAttachmentTests
2   - def test_should_create_file_from_uploaded_file
3   - assert_created do
4   - attachment = upload_file :filename => '/files/foo.txt', :content_type => 'text/plain'
5   - assert_valid attachment
6   - assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
7   - assert !attachment.image?
8   - assert !attachment.size.zero?
9   - #assert_equal 3, attachment.size
10   - assert_nil attachment.width
11   - assert_nil attachment.height
12   - end
13   - end
14   -
15   - def test_should_create_file_from_merb_temp_file
16   - assert_created do
17   - attachment = upload_merb_file :filename => '/files/foo.txt', :content_type => 'text/plain'
18   - assert_valid attachment
19   - assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
20   - assert !attachment.image?
21   - assert !attachment.size.zero?
22   - #assert_equal 3, attachment.size
23   - assert_nil attachment.width
24   - assert_nil attachment.height
25   - end
26   - end
27   -
28   - def test_reassign_attribute_data
29   - assert_created 1 do
30   - attachment = upload_file :filename => '/files/rails.png'
31   - assert_valid attachment
32   - assert attachment.size > 0, "no data was set"
33   -
34   - attachment.set_temp_data 'wtf'
35   - assert attachment.save_attachment?
36   - attachment.save!
37   -
38   - assert_equal 'wtf', attachment_model.find(attachment.id).send(:current_data)
39   - end
40   - end
41   -
42   - def test_no_reassign_attribute_data_on_nil
43   - assert_created 1 do
44   - attachment = upload_file :filename => '/files/rails.png'
45   - assert_valid attachment
46   - assert attachment.size > 0, "no data was set"
47   -
48   - attachment.set_temp_data nil
49   - assert !attachment.save_attachment?
50   - end
51   - end
52   -
53   - def test_should_overwrite_old_contents_when_updating
54   - attachment = upload_file :filename => '/files/rails.png'
55   - assert_not_created do # no new db_file records
56   - use_temp_file 'files/rails.png' do |file|
57   - attachment.filename = 'rails2.png'
58   - attachment.temp_paths.unshift File.join(FIXTURE_PATH, file)
59   - attachment.save!
60   - end
61   - end
62   - end
63   -
64   - def test_should_save_without_updating_file
65   - attachment = upload_file :filename => '/files/foo.txt'
66   - assert_valid attachment
67   - assert !attachment.save_attachment?
68   - assert_nothing_raised { attachment.save! }
69   - end
70   -
71   - def test_should_handle_nil_file_upload
72   - attachment = attachment_model.create :uploaded_data => ''
73   - assert_raise ActiveRecord::RecordInvalid do
74   - attachment.save!
75   - end
76   - end
77   -end
78 0 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/test/basic_test.rb
... ... @@ -1,121 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
3   -
4   -class BasicTest < Test::Unit::TestCase
5   - def test_should_set_default_min_size
6   - assert_equal 1, Attachment.attachment_options[:min_size]
7   - end
8   -
9   - def test_should_set_default_max_size
10   - assert_equal 1.megabyte, Attachment.attachment_options[:max_size]
11   - end
12   -
13   - def test_should_set_default_size
14   - assert_equal (1..1.megabyte), Attachment.attachment_options[:size]
15   - end
16   -
17   - def test_should_set_default_thumbnails_option
18   - assert_equal Hash.new, Attachment.attachment_options[:thumbnails]
19   - end
20   -
21   - def test_should_set_default_thumbnail_class
22   - assert_equal Attachment, Attachment.attachment_options[:thumbnail_class]
23   - end
24   -
25   - def test_should_normalize_content_types_to_array
26   - assert_equal %w(pdf), PdfAttachment.attachment_options[:content_type]
27   - assert_equal %w(pdf doc txt), DocAttachment.attachment_options[:content_type]
28   - assert_equal Technoweenie::AttachmentFu.content_types, ImageAttachment.attachment_options[:content_type]
29   - assert_equal ['pdf'] + Technoweenie::AttachmentFu.content_types, ImageOrPdfAttachment.attachment_options[:content_type]
30   - end
31   -
32   - def test_should_sanitize_content_type
33   - @attachment = Attachment.new :content_type => ' foo '
34   - assert_equal 'foo', @attachment.content_type
35   - end
36   -
37   - def test_should_sanitize_filenames
38   - @attachment = Attachment.new :filename => 'blah/foo.bar'
39   - assert_equal 'foo.bar', @attachment.filename
40   -
41   - @attachment.filename = 'blah\\foo.bar'
42   - assert_equal 'foo.bar', @attachment.filename
43   -
44   - @attachment.filename = 'f o!O-.bar'
45   - assert_equal 'f_o_O-.bar', @attachment.filename
46   -
47   -# @attachment.filename = 'sheeps_says_bææ'
48   -# assert_equal 'sheeps_says_b__', @attachment.filename
49   -
50   - @attachment.filename = nil
51   - assert_nil @attachment.filename
52   - end
53   -
54   - def test_should_convert_thumbnail_name
55   - @attachment = FileAttachment.new :filename => 'foo.bar'
56   - assert_equal 'foo.bar', @attachment.thumbnail_name_for(nil)
57   - assert_equal 'foo.bar', @attachment.thumbnail_name_for('')
58   - assert_equal 'foo_blah.bar', @attachment.thumbnail_name_for(:blah)
59   - assert_equal 'foo_blah.blah.bar', @attachment.thumbnail_name_for('blah.blah')
60   -
61   - @attachment.filename = 'foo.bar.baz'
62   - assert_equal 'foo.bar_blah.baz', @attachment.thumbnail_name_for(:blah)
63   - end
64   -
65   - def test_should_require_valid_thumbnails_option
66   - klass = Class.new(ActiveRecord::Base)
67   - assert_raise ArgumentError do
68   - klass.has_attachment :thumbnails => []
69   - end
70   - end
71   -
72   - class ::ImageWithPolymorphicThumbsAttachment
73   - cattr_accessor :thumbnail_creations
74   -
75   - def create_or_update_thumbnail(path, thumb, *size)
76   - @@thumbnail_creations[thumb] = size.size == 1 ? size.first : size
77   - end
78   -
79   - def self.reset_creations
80   - @@thumbnail_creations = {}
81   - end
82   - end
83   -
84   - def test_should_handle_polymorphic_thumbnails_option
85   - assert_polymorphic_thumb_creation nil,
86   - :thumb => [50, 50], :geometry => 'x50'
87   - assert_polymorphic_thumb_creation 'Product',
88   - :thumb => [50, 50], :geometry => 'x50', :large_thumb => '169x169!', :zoomed => '500x500>'
89   - assert_polymorphic_thumb_creation 'Editorial',
90   - :thumb => [50, 50], :geometry => 'x50', :fullsize => '150x100>'
91   - assert_polymorphic_thumb_creation 'User',
92   - :thumb => [50, 50], :geometry => 'x50', :avatar => '64x64!'
93   - end
94   -
95   - def test_should_compute_per_thumbnail_jpeg_quality
96   - assert_jpeg_quality :thumb, 90
97   - assert_jpeg_quality :avatar, 85
98   - assert_jpeg_quality :large, 75
99   - assert_jpeg_quality :large, 0x200 | 75, false
100   - assert_jpeg_quality nil, 75
101   - end
102   -
103   -private
104   - def assert_jpeg_quality(thumbnail, quality, require_0_to_100 = true)
105   - klass = ImageWithPerThumbJpegAttachment
106   - w, h = if thumbnail
107   - klass.attachment_options[:thumbnails][thumbnail].scan(/\d+/)
108   - else
109   - klass.attachment_options[:resize_to].scan(/\d+/)
110   - end
111   - attachment = klass.new(:thumbnail => thumbnail, :width => w, :height => h)
112   - assert_equal quality, attachment.send(:get_jpeg_quality, require_0_to_100)
113   - end
114   -
115   - def assert_polymorphic_thumb_creation(parent, defs)
116   - attachment_model ImageWithPolymorphicThumbsAttachment
117   - attachment_model.reset_creations
118   - attachment = upload_file :filename => '/files/rails.png', :imageable_type => parent.to_s.classify, :imageable_id => nil
119   - assert_equal defs, attachment_model.thumbnail_creations
120   - end
121   -end
vendor/plugins/pothoven-attachment_fu/test/database.yml
... ... @@ -1,18 +0,0 @@
1   -sqlite:
2   - :adapter: sqlite
3   - :database: attachment_fu_plugin.sqlite.db
4   -sqlite3:
5   - :adapter: sqlite3
6   - :database: attachment_fu_plugin.sqlite3.db
7   -postgresql:
8   - :adapter: postgresql
9   - :username: postgres
10   - :password: postgres
11   - :database: attachment_fu_plugin_test
12   - :min_messages: ERROR
13   -mysql:
14   - :adapter: mysql
15   - :host: localhost
16   - :username: rails
17   - :password:
18   - :database: attachment_fu_plugin_test
19 0 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/test/extra_attachment_test.rb
... ... @@ -1,67 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
2   -
3   -class OrphanAttachmentTest < Test::Unit::TestCase
4   - include BaseAttachmentTests
5   - attachment_model OrphanAttachment
6   -
7   - def test_should_create_image_from_uploaded_file
8   - assert_created do
9   - attachment = upload_file :filename => '/files/rails.png'
10   - assert_valid attachment
11   - assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
12   - assert attachment.image?
13   - assert !attachment.size.zero?
14   - end
15   - end
16   -
17   - def test_should_create_file_from_uploaded_file
18   - assert_created do
19   - attachment = upload_file :filename => '/files/foo.txt'
20   - assert_valid attachment
21   - assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
22   - assert attachment.image?
23   - assert !attachment.size.zero?
24   - end
25   - end
26   -
27   - def test_should_create_file_from_merb_temp_file
28   - assert_created do
29   - attachment = upload_merb_file :filename => '/files/foo.txt'
30   - assert_valid attachment
31   - assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
32   - assert attachment.image?
33   - assert !attachment.size.zero?
34   - end
35   - end
36   -
37   - def test_should_create_image_from_uploaded_file_with_custom_content_type
38   - assert_created do
39   - attachment = upload_file :content_type => 'foo/bar', :filename => '/files/rails.png'
40   - assert_valid attachment
41   - assert !attachment.image?
42   - assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
43   - assert !attachment.size.zero?
44   - #assert_equal 1784, attachment.size
45   - end
46   - end
47   -
48   - def test_should_create_thumbnail
49   - attachment = upload_file :filename => '/files/rails.png'
50   -
51   - assert_raise Technoweenie::AttachmentFu::ThumbnailError do
52   - attachment.create_or_update_thumbnail(attachment.create_temp_file, 'thumb', 50, 50)
53   - end
54   - end
55   -
56   - def test_should_create_thumbnail_with_geometry_string
57   - attachment = upload_file :filename => '/files/rails.png'
58   -
59   - assert_raise Technoweenie::AttachmentFu::ThumbnailError do
60   - attachment.create_or_update_thumbnail(attachment.create_temp_file, 'thumb', 'x50')
61   - end
62   - end
63   -end
64   -
65   -class MinimalAttachmentTest < OrphanAttachmentTest
66   - attachment_model MinimalAttachment
67   -end
68 0 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/test/fixtures/attachment.rb
... ... @@ -1,297 +0,0 @@
1   -class Attachment < ActiveRecord::Base
2   - @@saves = 0
3   - cattr_accessor :saves
4   - has_attachment :processor => :rmagick
5   - validates_as_attachment
6   - after_save do |record|
7   - self.saves += 1
8   - end
9   -end
10   -
11   -class LowerQualityAttachment < Attachment
12   - self.table_name = 'attachments'
13   - has_attachment :resize_to => [55,55], :jpeg_quality => 50
14   -end
15   -
16   -class SmallAttachment < Attachment
17   - has_attachment :max_size => 1.kilobyte
18   -end
19   -
20   -class BigAttachment < Attachment
21   - has_attachment :size => 1.megabyte..2.megabytes
22   -end
23   -
24   -class PdfAttachment < Attachment
25   - has_attachment :content_type => 'pdf'
26   -end
27   -
28   -class DocAttachment < Attachment
29   - has_attachment :content_type => %w(pdf doc txt)
30   -end
31   -
32   -class ImageAttachment < Attachment
33   - has_attachment :content_type => :image, :resize_to => [50,50]
34   -end
35   -
36   -class ImageOrPdfAttachment < Attachment
37   - has_attachment :content_type => ['pdf', :image], :resize_to => 'x50'
38   -end
39   -
40   -class ImageWithThumbsAttachment < Attachment
41   - has_attachment :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }, :resize_to => [55,55]
42   - # after_resize do |record, img|
43   - # record.aspect_ratio = img.columns.to_f / img.rows.to_f
44   - # end
45   -end
46   -
47   -class ImageWithPerThumbJpegAttachment < Attachment
48   - has_attachment :resize_to => '500x500!',
49   - :thumbnails => { :thumb => '50x50!', :large => '300x300!', :avatar => '64x64!' },
50   - :jpeg_quality => { :thumb => 90, '<5000' => 85, '>=5000' => 75, :large => 0x200 | 75 }
51   -end
52   -
53   -class ImageWithPolymorphicThumbsAttachment < Attachment
54   - belongs_to :imageable, :polymorphic => true
55   - has_attachment :thumbnails => {
56   - :thumb => [50, 50],
57   - :geometry => 'x50',
58   - :products => { :large_thumb => '169x169!', :zoomed => '500x500>' },
59   - :editorials => { :fullsize => '150x100>' },
60   - 'User' => { :avatar => '64x64!' }
61   - }
62   -end
63   -
64   -class FileAttachment < ActiveRecord::Base
65   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files', :processor => :rmagick
66   - validates_as_attachment
67   -end
68   -
69   -class FileAttachmentWithStringId < ActiveRecord::Base
70   - self.table_name = 'file_attachments_with_string_id'
71   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files', :processor => :rmagick
72   - validates_as_attachment
73   -
74   - before_validation :auto_generate_id
75   - before_save :auto_generate_id
76   - @@last_id = 0
77   -
78   - private
79   - def auto_generate_id
80   - @@last_id += 1
81   - self.id = "id_#{@@last_id}"
82   - end
83   -end
84   -
85   -class FileAttachmentWithUuid < ActiveRecord::Base
86   - self.table_name = 'file_attachments_with_string_id'
87   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files', :processor => :rmagick, :uuid_primary_key => true
88   - validates_as_attachment
89   -
90   - before_validation :auto_generate_id
91   - before_save :auto_generate_id
92   - @@last_id = 0
93   -
94   - private
95   - def auto_generate_id
96   - @@last_id += 1
97   - self.id = "%0127dx" % @@last_id
98   - end
99   -end
100   -
101   -class ImageFileAttachment < FileAttachment
102   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
103   - :content_type => :image, :resize_to => [50,50]
104   -end
105   -
106   -class ImageWithThumbsFileAttachment < FileAttachment
107   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
108   - :thumbnails => { :thumb => [50, 50], :geometry => 'x50' }, :resize_to => [55,55]
109   - # after_resize do |record, img|
110   - # record.aspect_ratio = img.columns.to_f / img.rows.to_f
111   - # end
112   -end
113   -
114   -class ImageWithThumbsClassFileAttachment < FileAttachment
115   - # use file_system_path to test backwards compatibility
116   - has_attachment :file_system_path => 'vendor/plugins/attachment_fu/test/files',
117   - :thumbnails => { :thumb => [50, 50] }, :resize_to => [55,55],
118   - :thumbnail_class => 'ImageThumbnail'
119   -end
120   -
121   -class ImageThumbnail < FileAttachment
122   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files/thumbnails'
123   -end
124   -
125   -# no parent
126   -class OrphanAttachment < ActiveRecord::Base
127   - has_attachment :processor => :rmagick
128   - validates_as_attachment
129   -end
130   -
131   -# no filename, no size, no content_type
132   -class MinimalAttachment < ActiveRecord::Base
133   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files', :processor => :rmagick
134   - validates_as_attachment
135   -
136   - def filename
137   - "#{id}.file"
138   - end
139   -end
140   -
141   -begin
142   - class ImageScienceAttachment < ActiveRecord::Base
143   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
144   - :processor => :image_science, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55
145   - end
146   -
147   - class ImageScienceLowerQualityAttachment < ActiveRecord::Base
148   - self.table_name = 'image_science_attachments'
149   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
150   - :processor => :image_science, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55,
151   - :jpeg_quality => 75
152   - end
153   -
154   - class ImageScienceWithPerThumbJpegAttachment < ImageScienceAttachment
155   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
156   - :processor => :image_science,
157   - :resize_to => '100x100',
158   - :thumbnails => { :thumb => [50, 50], :editorial => '300x120', :avatar => '64x64!' },
159   - :jpeg_quality => { :thumb => 90, '<5000' => 80, '>=5000' => 75 }
160   - end
161   -rescue MissingSourceFile
162   - puts $!.message
163   - puts "no ImageScience"
164   -end
165   -
166   -begin
167   - class CoreImageAttachment < ActiveRecord::Base
168   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
169   - :processor => :core_image, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55
170   - end
171   -
172   - class LowerQualityCoreImageAttachment < CoreImageAttachment
173   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
174   - :processor => :core_image, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55,
175   - :jpeg_quality => 50
176   - end
177   -
178   - class CoreImageWithPerThumbJpegAttachment < CoreImageAttachment
179   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
180   - :processor => :core_image,
181   - :resize_to => '100x100',
182   - :thumbnails => { :thumb => [50, 50], :editorial => '300x120', :avatar => '64x64!' },
183   - :jpeg_quality => { :thumb => 90, '<5000' => 80, '>=5000' => 75 }
184   - end
185   -rescue MissingSourceFile
186   - puts $!.message
187   - puts "no CoreImage"
188   -end
189   -
190   -begin
191   - class MiniMagickAttachment < ActiveRecord::Base
192   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
193   - :processor => :mini_magick, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55
194   - end
195   -
196   - class ImageThumbnailCrop < MiniMagickAttachment
197   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
198   - :thumbnails => { :square => "50x50c", :vertical => "30x60c", :horizontal => "60x30c"}
199   -
200   - # TODO this is a bad duplication, this method is in the MiniMagick Processor
201   - def self.calculate_offset(image_width,image_height,image_aspect,thumb_width,thumb_height,thumb_aspect)
202   - # only crop if image is not smaller in both dimensions
203   -
204   - # special cases, image smaller in one dimension then thumbsize
205   - if image_width < thumb_width
206   - offset = (image_height / 2) - (thumb_height / 2)
207   - command = "#{image_width}x#{thumb_height}+0+#{offset}"
208   - elsif image_height < thumb_height
209   - offset = (image_width / 2) - (thumb_width / 2)
210   - command = "#{thumb_width}x#{image_height}+#{offset}+0"
211   -
212   - # normal thumbnail generation
213   - # calculate height and offset y, width is fixed
214   - elsif (image_aspect <= thumb_aspect or image_width < thumb_width) and image_height > thumb_height
215   - height = image_width / thumb_aspect
216   - offset = (image_height / 2) - (height / 2)
217   - command = "#{image_width}x#{height}+0+#{offset}"
218   - # calculate width and offset x, height is fixed
219   - else
220   - width = image_height * thumb_aspect
221   - offset = (image_width / 2) - (width / 2)
222   - command = "#{width}x#{image_height}+#{offset}+0"
223   - end
224   - # crop image
225   - command
226   - end
227   - end
228   -
229   - class LowerQualityMiniMagickAttachment < ActiveRecord::Base
230   - self.table_name = 'mini_magick_attachments'
231   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
232   - :processor => :mini_magick, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55,
233   - :jpeg_quality => 50
234   - end
235   -
236   - class MiniMagickWithPerThumbJpegAttachment < MiniMagickAttachment
237   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
238   - :processor => :mini_magick,
239   - :resize_to => '100x100',
240   - :thumbnails => { :thumb => [50, 50], :editorial => '300x120', :avatar => '64x64!' },
241   - :jpeg_quality => { :thumb => 90, '<5000' => 80, '>=5000' => 75 }
242   - end
243   -
244   -rescue MissingSourceFile
245   - puts $!.message
246   - puts "no Mini Magick"
247   -end
248   -
249   -begin
250   - class GD2Attachment < ActiveRecord::Base
251   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
252   - :processor => :gd2, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55
253   - end
254   -
255   - class LowerQualityGD2Attachment < GD2Attachment
256   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
257   - :processor => :gd2, :thumbnails => { :thumb => [50, 51], :geometry => '31>', :aspect => '25x25!' }, :resize_to => 55,
258   - :jpeg_quality => 50
259   - end
260   -
261   - class GD2WithPerThumbJpegAttachment < GD2Attachment
262   - has_attachment :path_prefix => 'vendor/plugins/attachment_fu/test/files',
263   - :processor => :gd2,
264   - :resize_to => '100x100',
265   - :thumbnails => { :thumb => [50, 50], :editorial => '300x120', :avatar => '64x64!' },
266   - :jpeg_quality => { :thumb => 90, '<5000' => 80, '>=5000' => 75 }
267   - end
268   -rescue MissingSourceFile
269   - puts $!.message
270   - puts "no GD2"
271   -end
272   -
273   -
274   -begin
275   - class S3Attachment < ActiveRecord::Base
276   - has_attachment :storage => :s3, :processor => :rmagick, :s3_config_path => File.join(File.dirname(__FILE__), '../amazon_s3.yml')
277   - validates_as_attachment
278   - end
279   -
280   - class CloudFilesAttachment < ActiveRecord::Base
281   - has_attachment :storage => :cloud_files, :processor => :rmagick, :cloudfiles_config_path => File.join(File.dirname(__FILE__), '../rackspace_cloudfiles.yml')
282   - validates_as_attachment
283   - end
284   -
285   - class S3WithPathPrefixAttachment < S3Attachment
286   - has_attachment :storage => :s3, :path_prefix => 'some/custom/path/prefix', :processor => :rmagick
287   - validates_as_attachment
288   - end
289   -
290   - class CloudFilesWithPathPrefixAttachment < CloudFilesAttachment
291   - has_attachment :storage => :cloud_files, :path_prefix => 'some/custom/path/prefix', :processor => :rmagick
292   - validates_as_attachment
293   - end
294   -
295   -rescue
296   - puts "S3 error: #{$!}"
297   -end
vendor/plugins/pothoven-attachment_fu/test/fixtures/files/fake/rails.png

4.12 KB

vendor/plugins/pothoven-attachment_fu/test/fixtures/files/foo.txt
... ... @@ -1 +0,0 @@
1   -foo
2 0 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/test/fixtures/files/rails.jpg

2.43 KB

vendor/plugins/pothoven-attachment_fu/test/fixtures/files/rails.png

1.75 KB

vendor/plugins/pothoven-attachment_fu/test/geometry_test.rb
... ... @@ -1,114 +0,0 @@
1   -require 'test/unit'
2   -require File.expand_path(File.join(File.dirname(__FILE__), '../lib/geometry')) unless Object.const_defined?(:Geometry)
3   -
4   -class GeometryTest < Test::Unit::TestCase
5   - def test_should_resize
6   - assert_geometry 50, 64,
7   - "50x50" => [39, 50],
8   - "60x60" => [47, 60],
9   - "100x100" => [78, 100]
10   - end
11   -
12   - def test_should_resize_no_width
13   - assert_geometry 50, 64,
14   - "x50" => [39, 50],
15   - "x60" => [47, 60],
16   - "x100" => [78, 100]
17   - end
18   -
19   - def test_should_resize_no_height
20   - assert_geometry 50, 64,
21   - "50" => [50, 64],
22   - "60" => [60, 77],
23   - "100" => [100, 128]
24   - end
25   -
26   - def test_should_resize_no_height_with_x
27   - assert_geometry 50, 64,
28   - "50x" => [50, 64],
29   - "60x" => [60, 77],
30   - "100x" => [100, 128]
31   - end
32   -
33   - def test_should_resize_with_percent
34   - assert_geometry 50, 64,
35   - "50x50%" => [25, 32],
36   - "60x60%" => [30, 38],
37   - "120x112%" => [60, 72]
38   - end
39   -
40   - def test_should_resize_with_percent_and_no_width
41   - assert_geometry 50, 64,
42   - "x50%" => [50, 32],
43   - "x60%" => [50, 38],
44   - "x112%" => [50, 72]
45   - end
46   -
47   - def test_should_resize_with_percent_and_no_height
48   - assert_geometry 50, 64,
49   - "50%" => [25, 32],
50   - "60%" => [30, 38],
51   - "120%" => [60, 77]
52   - end
53   -
54   - def test_should_resize_with_less
55   - assert_geometry 50, 64,
56   - "50x50<" => [50, 64],
57   - "60x60<" => [50, 64],
58   - "100x100<" => [78, 100],
59   - "100x112<" => [88, 112],
60   - "40x70<" => [50, 64]
61   - end
62   -
63   - def test_should_resize_with_less_and_no_width
64   - assert_geometry 50, 64,
65   - "x50<" => [50, 64],
66   - "x60<" => [50, 64],
67   - "x100<" => [78, 100]
68   - end
69   -
70   - def test_should_resize_with_less_and_no_height
71   - assert_geometry 50, 64,
72   - "50<" => [50, 64],
73   - "60<" => [60, 77],
74   - "100<" => [100, 128]
75   - end
76   -
77   - def test_should_resize_with_greater
78   - assert_geometry 50, 64,
79   - "50x50>" => [39, 50],
80   - "60x60>" => [47, 60],
81   - "100x100>" => [50, 64],
82   - "100x112>" => [50, 64],
83   - "40x70>" => [40, 51]
84   - end
85   -
86   - def test_should_resize_with_greater_and_no_width
87   - assert_geometry 50, 64,
88   - "x40>" => [31, 40],
89   - "x60>" => [47, 60],
90   - "x100>" => [50, 64]
91   - end
92   -
93   - def test_should_resize_with_greater_and_no_height
94   - assert_geometry 50, 64,
95   - "40>" => [40, 51],
96   - "60>" => [50, 64],
97   - "100>" => [50, 64]
98   - end
99   -
100   - def test_should_resize_with_aspect
101   - assert_geometry 50, 64,
102   - "35x35!" => [35, 35],
103   - "70x70!" => [70, 70]
104   - end
105   -
106   - protected
107   - def assert_geometry(width, height, values)
108   - values.each do |geo, result|
109   - # run twice to verify the Geometry string isn't modified after a run
110   - geo = Geometry.from_s(geo)
111   - 2.times { assert_equal result, [width, height] / geo }
112   - end
113   - end
114   -end
115 0 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/test/processors/core_image_test.rb
... ... @@ -1,58 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
2   -
3   -class CoreImageTest < Test::Unit::TestCase
4   - attachment_model CoreImageAttachment
5   -
6   - if Object.const_defined?(:OSX)
7   - def test_should_resize_image
8   - attachment = upload_file :filename => '/files/rails.png'
9   - assert_valid attachment
10   - assert attachment.image?
11   - # test core image thumbnail
12   - assert_equal 42, attachment.width
13   - assert_equal 55, attachment.height
14   -
15   - thumb = attachment.thumbnails.detect { |t| t.filename =~ /_thumb/ }
16   - geo = attachment.thumbnails.detect { |t| t.filename =~ /_geometry/ }
17   - aspect = attachment.thumbnails.detect { |t| t.filename =~ /_aspect/ }
18   -
19   - # test exact resize dimensions
20   - assert_equal 50, thumb.width
21   - assert_equal 51, thumb.height
22   -
23   - # test geometry strings
24   - assert_equal 31, geo.width
25   - assert_equal 41, geo.height
26   - assert_equal 25, aspect.width
27   - assert_equal 25, aspect.height
28   -
29   - # This makes sure that we didn't overwrite the original file
30   - # and will end up with a thumbnail instead of the original
31   - assert_equal 42, attachment.width
32   - assert_equal 55, attachment.height
33   -
34   - end
35   -
36   - def test_should_handle_jpeg_quality
37   - attachment_model CoreImageAttachment
38   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
39   - full_size = attachment.size
40   - attachment_model LowerQualityCoreImageAttachment
41   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
42   - lq_size = attachment.size
43   - assert lq_size <= full_size * 0.9, 'Lower-quality JPEG filesize should be congruently smaller'
44   -
45   - # FIXME: wait for Marcus' reply to determine whether I can get exact-quality output or need to adjust for CoreImage.
46   - # attachment_model CoreImageWithPerThumbJpegAttachment
47   - # attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
48   - # assert_file_jpeg_quality attachment, :thumb, 90
49   - # assert_file_jpeg_quality attachment, :avatar, 80
50   - # assert_file_jpeg_quality attachment, :editorial, 75
51   - # assert_file_jpeg_quality attachment, nil, 75
52   - end
53   - else
54   - def test_flunk
55   - puts "CoreImage not loaded, tests not running"
56   - end
57   - end
58   -end
59 0 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/test/processors/gd2_test.rb
... ... @@ -1,51 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
2   -
3   -class GD2Test < Test::Unit::TestCase
4   - attachment_model GD2Attachment
5   -
6   - if Object.const_defined?(:GD2)
7   - def test_should_resize_image
8   - attachment = upload_file :filename => '/files/rails.png'
9   - assert_valid attachment
10   - assert attachment.image?
11   - # test gd2 thumbnail
12   - assert_equal 43, attachment.width
13   - assert_equal 55, attachment.height
14   -
15   - thumb = attachment.thumbnails.detect { |t| t.filename =~ /_thumb/ }
16   - geo = attachment.thumbnails.detect { |t| t.filename =~ /_geometry/ }
17   - aspect = attachment.thumbnails.detect { |t| t.filename =~ /_aspect/ }
18   -
19   - # test exact resize dimensions
20   - assert_equal 50, thumb.width
21   - assert_equal 51, thumb.height
22   -
23   - # test geometry strings
24   - assert_equal 31, geo.width
25   - assert_equal 40, geo.height
26   - assert_equal 25, aspect.width
27   - assert_equal 25, aspect.height
28   - end
29   -
30   - def test_should_handle_jpeg_quality
31   - attachment_model GD2Attachment
32   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
33   - full_size = attachment.size
34   - attachment_model LowerQualityGD2Attachment
35   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
36   - lq_size = attachment.size
37   - assert lq_size <= full_size * 0.9, 'Lower-quality JPEG filesize should be congruently smaller'
38   -
39   - attachment_model GD2WithPerThumbJpegAttachment
40   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
41   - assert_file_jpeg_quality attachment, :thumb, 90
42   - assert_file_jpeg_quality attachment, :avatar, 80
43   - assert_file_jpeg_quality attachment, :editorial, 75
44   - assert_file_jpeg_quality attachment, nil, 75
45   - end
46   - else
47   - def test_flunk
48   - puts "GD2 not loaded, tests not running"
49   - end
50   - end
51   -end
52 0 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/test/processors/image_science_test.rb
... ... @@ -1,54 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
2   -
3   -class ImageScienceTest < Test::Unit::TestCase
4   - attachment_model ImageScienceAttachment
5   -
6   - if Object.const_defined?(:ImageScience)
7   - def test_should_resize_image
8   - attachment = upload_file :filename => '/files/rails.png'
9   - assert_valid attachment
10   - assert attachment.image?
11   - # test image science thumbnail
12   - assert_equal 42, attachment.width
13   - assert_equal 55, attachment.height
14   -
15   - thumb = attachment.thumbnails.detect { |t| t.filename =~ /_thumb/ }
16   - geo = attachment.thumbnails.detect { |t| t.filename =~ /_geometry/ }
17   - aspect = attachment.thumbnails.detect { |t| t.filename =~ /_aspect/ }
18   -
19   - # test exact resize dimensions
20   - assert_equal 50, thumb.width
21   - assert_equal 51, thumb.height
22   -
23   - # test geometry strings
24   - assert_equal 31, geo.width
25   - assert_equal 41, geo.height
26   - assert_equal 25, aspect.width
27   - assert_equal 25, aspect.height
28   - end
29   -
30   - def test_should_handle_jpeg_quality
31   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
32   - full_size = attachment.size
33   - attachment_model ImageScienceLowerQualityAttachment
34   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
35   - lq_size = attachment.size
36   - if ImageScience.instance_method(:save).arity == -2 # tdd-image_science: JPEG quality processing
37   - assert lq_size <= full_size * 0.75, 'Lower-quality JPEG filesize should be congruently smaller'
38   - else
39   - assert_equal full_size, lq_size, 'Unsupported lower-quality JPEG should yield exact same file size'
40   - end
41   -
42   - attachment_model ImageScienceWithPerThumbJpegAttachment
43   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
44   - assert_file_jpeg_quality attachment, :thumb, 90
45   - assert_file_jpeg_quality attachment, :avatar, 80
46   - assert_file_jpeg_quality attachment, :editorial, 75
47   - assert_file_jpeg_quality attachment, nil, 75
48   - end
49   - else
50   - def test_flunk
51   - puts "ImageScience not loaded, tests not running"
52   - end
53   - end
54   -end
55 0 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/test/processors/mini_magick_test.rb
... ... @@ -1,122 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
2   -
3   -class MiniMagickTest < Test::Unit::TestCase
4   - attachment_model MiniMagickAttachment
5   -
6   - if Object.const_defined?(:MiniMagick)
7   - def test_should_resize_image
8   - attachment = upload_file :filename => '/files/rails.png'
9   - assert_valid attachment
10   - assert attachment.image?
11   - # test MiniMagick thumbnail
12   - assert_equal 43, attachment.width
13   - assert_equal 55, attachment.height
14   -
15   - thumb = attachment.thumbnails.detect { |t| t.filename =~ /_thumb/ }
16   - geo = attachment.thumbnails.detect { |t| t.filename =~ /_geometry/ }
17   - aspect = attachment.thumbnails.detect { |t| t.filename =~ /_aspect/ }
18   -
19   - # test exact resize dimensions
20   - assert_equal 50, thumb.width
21   - assert_equal 51, thumb.height
22   -
23   - # test geometry strings
24   - assert_equal 31, geo.width
25   - assert_equal 40, geo.height
26   - assert_equal 25, aspect.width
27   - assert_equal 25, aspect.height
28   - end
29   -
30   - def test_should_crop_image(klass = ImageThumbnailCrop)
31   - attachment_model klass
32   - attachment = upload_file :filename => '/files/rails.png'
33   - assert_valid attachment
34   - assert attachment.image?
35   - # has_attachment :thumbnails => { :square => "50x50c", :vertical => "30x60c", :horizontal => "60x30c"}
36   -
37   - square = attachment.thumbnails.detect { |t| t.filename =~ /_square/ }
38   - vertical = attachment.thumbnails.detect { |t| t.filename =~ /_vertical/ }
39   - horizontal = attachment.thumbnails.detect { |t| t.filename =~ /_horizontal/ }
40   -
41   - # test excat resize
42   - assert_equal 50, square.width
43   - assert_equal 50, square.height
44   -
45   - assert_equal 30, vertical.width
46   - assert_equal 60, vertical.height
47   -
48   - assert_equal 60, horizontal.width
49   - assert_equal 30, horizontal.height
50   - end
51   -
52   - # tests the first step in resize, crop the image in original size to right format
53   - def test_should_crop_image_right(klass = ImageThumbnailCrop)
54   - @@testcases.collect do |testcase|
55   - image_width, image_height, thumb_width, thumb_height = testcase[:data]
56   - image_aspect, thumb_aspect = image_width/image_height, thumb_width/thumb_height
57   - crop_comand = klass.calculate_offset(image_width, image_height, image_aspect, thumb_width, thumb_height,thumb_aspect)
58   - # pattern matching on crop command
59   - if testcase.has_key?(:height)
60   - assert crop_comand.match(/^#{image_width}x#{testcase[:height]}\+0\+#{testcase[:yoffset]}$/)
61   - else
62   - assert crop_comand.match(/^#{testcase[:width]}x#{image_height}\+#{testcase[:xoffset]}\+0$/)
63   - end
64   - end
65   - end
66   -
67   - def test_should_handle_jpeg_quality
68   - attachment_model MiniMagickAttachment
69   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
70   - full_size = attachment.size
71   - attachment_model LowerQualityMiniMagickAttachment
72   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
73   - lq_size = attachment.size
74   - assert lq_size <= full_size * 0.9, 'Lower-quality JPEG filesize should be congruently smaller'
75   -
76   - attachment_model MiniMagickWithPerThumbJpegAttachment
77   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
78   - assert_file_jpeg_quality attachment, :thumb, 90
79   - assert_file_jpeg_quality attachment, :avatar, 80
80   - assert_file_jpeg_quality attachment, :editorial, 75
81   - assert_file_jpeg_quality attachment, nil, 75
82   - end
83   - else
84   - def test_flunk
85   - puts "MiniMagick not loaded, tests not running"
86   - end
87   - end
88   -
89   - @@testcases = [
90   - # image_aspect <= 1 && thumb_aspect >= 1
91   - {:data => [10.0,40.0,2.0,1.0], :height => 5.0, :yoffset => 17.5}, # 1b
92   - {:data => [10.0,40.0,1.0,1.0], :height => 10.0, :yoffset => 15.0}, # 1b
93   -
94   - # image_aspect < 1 && thumb_aspect < 1
95   - {:data => [10.0,40.0,1.0,2.0], :height => 20.0, :yoffset => 10.0}, # 1a
96   - {:data => [2.0,3.0,1.0,2.0], :width => 1.5, :xoffset => 0.25}, # 1a
97   -
98   - # image_aspect = thumb_aspect
99   - {:data => [10.0,10.0,1.0,1.0], :height => 10.0, :yoffset => 0.0}, # QUADRAT 1c
100   -
101   - # image_aspect >= 1 && thumb_aspect > 1 && image_aspect < thumb_aspect
102   - {:data => [6.0,3.0,4.0,1.0], :height => 1.5, :yoffset => 0.75}, # 2b
103   - {:data => [6.0,6.0,4.0,1.0], :height => 1.5, :yoffset => 2.25}, # 2b
104   -
105   - # image_aspect > 1 && thumb_aspect > 1 && image_aspect > thumb_aspect
106   - {:data => [9.0,3.0,2.0,1.0], :width => 6.0, :xoffset => 1.5}, # 2a
107   -
108   - # image_aspect > 1 && thumb_aspect < 1 && image_aspect < thumb_aspect
109   - {:data => [10.0,5.0,0.1,2.0], :width => 0.25, :xoffset => 4.875}, # 4
110   - {:data => [10.0,5.0,1.0,2.0], :width => 2.5, :xoffset => 3.75}, # 4
111   -
112   - # image_aspect > 1 && thumb_aspect > 1 && image_aspect > thumb_aspect
113   - {:data => [9.0,3.0,2.0,1.0], :width => 6.0, :xoffset => 1.5}, # 3a
114   - # image_aspect > 1 && thumb_aspect > 1 && image_aspect < thumb_aspect
115   - {:data => [9.0,3.0,5.0,1.0], :height => 1.8, :yoffset => 0.6} # 3a
116   - ]
117   -
118   -
119   -
120   -
121   -
122   -end
vendor/plugins/pothoven-attachment_fu/test/processors/rmagick_test.rb
... ... @@ -1,272 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
2   -class RmagickTest < Test::Unit::TestCase
3   - attachment_model Attachment
4   -
5   - if Object.const_defined?(:Magick)
6   - def test_should_create_image_from_uploaded_file
7   - assert_created do
8   - attachment = upload_file :filename => '/files/rails.png'
9   - assert_valid attachment
10   - assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
11   - assert attachment.image?
12   - assert !attachment.size.zero?
13   - #assert_equal 1784, attachment.size
14   - assert_equal 50, attachment.width
15   - assert_equal 64, attachment.height
16   - assert_equal '50x64', attachment.image_size
17   - end
18   - end
19   -
20   - def test_should_create_image_from_uploaded_file_with_custom_content_type
21   - assert_created do
22   - attachment = upload_file :content_type => 'foo/bar', :filename => '/files/rails.png'
23   - assert_valid attachment
24   - assert !attachment.image?
25   - assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
26   - assert !attachment.size.zero?
27   - #assert_equal 1784, attachment.size
28   - assert_nil attachment.width
29   - assert_nil attachment.height
30   - assert_equal [], attachment.thumbnails
31   - end
32   - end
33   -
34   - def test_should_create_thumbnail
35   - attachment = upload_file :filename => '/files/rails.png'
36   -
37   - assert_created do
38   - basename, ext = attachment.filename.split '.'
39   - thumbnail = attachment.create_or_update_thumbnail(attachment.create_temp_file, 'thumb', 50, 50)
40   - assert_valid thumbnail
41   - assert !thumbnail.size.zero?
42   - #assert_in_delta 4673, thumbnail.size, 2
43   - assert_equal 50, thumbnail.width
44   - assert_equal 50, thumbnail.height
45   - assert_equal [thumbnail.id], attachment.thumbnails.collect(&:id)
46   - assert_equal attachment.id, thumbnail.parent_id if thumbnail.respond_to?(:parent_id)
47   - assert_equal "#{basename}_thumb.#{ext}", thumbnail.filename
48   - end
49   - end
50   -
51   - def test_should_create_thumbnail_with_geometry_strings
52   - attachment = upload_file :filename => '/files/rails.png'
53   -
54   - assert_created do
55   - basename, ext = attachment.filename.split '.'
56   - { 'x50' => [39, 50], '25x25!' => [25, 25] }.each do |geo, (w, h)|
57   - thumbnail = attachment.create_or_update_thumbnail(attachment.create_temp_file, 'thumb', geo)
58   - assert_valid thumbnail
59   - assert !thumbnail.size.zero?
60   - assert_equal w, thumbnail.width
61   - assert_equal h, thumbnail.height
62   - assert_equal [thumbnail], attachment.thumbnails
63   - assert_equal attachment.id, thumbnail.parent_id if thumbnail.respond_to?(:parent_id)
64   - assert_equal "#{basename}_thumb.#{ext}", thumbnail.filename
65   - end
66   - end
67   - end
68   -
69   - def test_should_resize_image(klass = ImageAttachment)
70   - attachment_model klass
71   - assert_equal [50, 50], attachment_model.attachment_options[:resize_to]
72   - attachment = upload_file :filename => '/files/rails.png'
73   - assert_valid attachment
74   - assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
75   - assert attachment.image?
76   - assert !attachment.size.zero?
77   - #assert_in_delta 4673, attachment.size, 2
78   - assert_equal 50, attachment.width
79   - assert_equal 50, attachment.height
80   - end
81   -
82   - test_against_subclass :test_should_resize_image, ImageAttachment
83   -
84   - def test_should_resize_image_with_geometry(klass = ImageOrPdfAttachment)
85   - attachment_model klass
86   - assert_equal 'x50', attachment_model.attachment_options[:resize_to]
87   - attachment = upload_file :filename => '/files/rails.png'
88   - assert_valid attachment
89   - assert !attachment.db_file.new_record? if attachment.respond_to?(:db_file)
90   - assert attachment.image?
91   - assert !attachment.size.zero?
92   - #assert_equal 3915, attachment.size
93   - assert_equal 39, attachment.width
94   - assert_equal 50, attachment.height
95   - end
96   -
97   - test_against_subclass :test_should_resize_image_with_geometry, ImageOrPdfAttachment
98   -
99   - def test_should_give_correct_thumbnail_filenames(klass = ImageWithThumbsFileAttachment)
100   - attachment_model klass
101   - assert_created 3 do
102   - attachment = upload_file :filename => '/files/rails.png'
103   - thumb = attachment.thumbnails.detect { |t| t.filename =~ /_thumb/ }
104   - geo = attachment.thumbnails.detect { |t| t.filename =~ /_geometry/ }
105   -
106   - [attachment, thumb, geo].each { |record| assert_valid record }
107   -
108   - assert_match /rails\.png$/, attachment.full_filename
109   - assert_match /rails_geometry\.png$/, attachment.full_filename(:geometry)
110   - assert_match /rails_thumb\.png$/, attachment.full_filename(:thumb)
111   - end
112   - end
113   -
114   - test_against_subclass :test_should_give_correct_thumbnail_filenames, ImageWithThumbsFileAttachment
115   -
116   - def test_should_automatically_create_thumbnails(klass = ImageWithThumbsAttachment)
117   - attachment_model klass
118   - assert_created 3 do
119   - attachment = upload_file :filename => '/files/rails.png'
120   - assert_valid attachment
121   - assert !attachment.size.zero?
122   - #assert_equal 1784, attachment.size
123   - assert_equal 55, attachment.width
124   - assert_equal 55, attachment.height
125   - assert_equal 2, attachment.thumbnails.length
126   - # assert_equal 1.0, attachment.aspect_ratio
127   -
128   - thumb = attachment.thumbnails.detect { |t| t.filename =~ /_thumb/ }
129   - assert !thumb.new_record?, thumb.errors.full_messages.join("\n")
130   - assert !thumb.size.zero?
131   - #assert_in_delta 4673, thumb.size, 2
132   - assert_equal 50, thumb.width
133   - assert_equal 50, thumb.height
134   - # assert_equal 1.0, thumb.aspect_ratio
135   -
136   - geo = attachment.thumbnails.detect { |t| t.filename =~ /_geometry/ }
137   - assert !geo.new_record?, geo.errors.full_messages.join("\n")
138   - assert !geo.size.zero?
139   - #assert_equal 3915, geo.size
140   - assert_equal 50, geo.width
141   - assert_equal 50, geo.height
142   - # assert_equal 1.0, geo.aspect_ratio
143   - end
144   - end
145   -
146   - test_against_subclass :test_should_automatically_create_thumbnails, ImageWithThumbsAttachment
147   -
148   - # same as above method, but test it on a file model
149   - test_against_class :test_should_automatically_create_thumbnails, ImageWithThumbsFileAttachment
150   - test_against_subclass :test_should_automatically_create_thumbnails_on_class, ImageWithThumbsFileAttachment
151   -
152   - def test_should_use_thumbnail_subclass(klass = ImageWithThumbsClassFileAttachment)
153   - attachment_model klass
154   - attachment = nil
155   - assert_difference ImageThumbnail, :count do
156   - attachment = upload_file :filename => '/files/rails.png'
157   - assert_valid attachment
158   - end
159   - assert_kind_of ImageThumbnail, attachment.thumbnails.first
160   - if attachment.thumbnails.first.respond_to?(:parent)
161   - assert_equal attachment.id, attachment.thumbnails.first.parent.id
162   - assert_kind_of FileAttachment, attachment.thumbnails.first.parent
163   - end
164   - assert_equal 'rails_thumb.png', attachment.thumbnails.first.filename
165   - assert_equal attachment.thumbnails.first.full_filename, attachment.full_filename(attachment.thumbnails.first.thumbnail),
166   - "#full_filename does not use thumbnail class' path."
167   - assert_equal attachment.destroy, attachment
168   - end
169   -
170   - test_against_subclass :test_should_use_thumbnail_subclass, ImageWithThumbsClassFileAttachment
171   -
172   - def test_should_remove_old_thumbnail_files_when_updating(klass = ImageWithThumbsFileAttachment)
173   - attachment_model klass
174   - attachment = nil
175   - assert_created 3 do
176   - attachment = upload_file :filename => '/files/rails.png'
177   - end
178   -
179   - old_filenames = [attachment.full_filename] + attachment.thumbnails.collect(&:full_filename)
180   -
181   - assert_not_created do
182   - use_temp_file "files/rails.png" do |file|
183   - attachment.filename = 'rails2.png'
184   - attachment.temp_paths.unshift File.join(FIXTURE_PATH, file)
185   - attachment.save
186   - new_filenames = [attachment.reload.full_filename] + attachment.thumbnails.collect { |t| t.reload.full_filename }
187   - new_filenames.each { |f| assert File.exists?(f), "#{f} does not exist" }
188   - old_filenames.each { |f| assert !File.exists?(f), "#{f} still exists" }
189   - end
190   - end
191   - end
192   -
193   - test_against_subclass :test_should_remove_old_thumbnail_files_when_updating, ImageWithThumbsFileAttachment
194   -
195   - def test_should_delete_file_when_in_file_system_when_attachment_record_destroyed(klass = ImageWithThumbsFileAttachment)
196   - attachment_model klass
197   - attachment = upload_file :filename => '/files/rails.png'
198   - filenames = [attachment.full_filename] + attachment.thumbnails.collect(&:full_filename)
199   - filenames.each { |f| assert File.exists?(f), "#{f} never existed to delete on destroy" }
200   - attachment.destroy
201   - filenames.each { |f| assert !File.exists?(f), "#{f} still exists" }
202   - end
203   -
204   - test_against_subclass :test_should_delete_file_when_in_file_system_when_attachment_record_destroyed, ImageWithThumbsFileAttachment
205   -
206   - def test_should_have_full_filename_method(klass = FileAttachment)
207   - attachment_model klass
208   - attachment = upload_file :filename => '/files/rails.png'
209   - assert_respond_to attachment, :full_filename
210   - end
211   -
212   - test_against_subclass :test_should_have_full_filename_method, FileAttachment
213   -
214   - def test_should_overwrite_old_thumbnail_records_when_updating(klass = ImageWithThumbsAttachment)
215   - attachment_model klass
216   - attachment = nil
217   - assert_created 3 do
218   - attachment = upload_file :filename => '/files/rails.png'
219   - end
220   - assert_not_created do # no new db_file records
221   - use_temp_file "files/rails.png" do |file|
222   - attachment.filename = 'rails2.png'
223   - # The above test (#test_should_have_full_filename_method) to pass before be can set the temp_path below --
224   - # #temp_path calls #full_filename, which is not getting mixed into the attachment. Maybe we don't need to
225   - # set temp_path at all?
226   - #
227   - # attachment.temp_paths.unshift File.join(FIXTURE_PATH, file)
228   - attachment.save!
229   - end
230   - end
231   - end
232   -
233   - test_against_subclass :test_should_overwrite_old_thumbnail_records_when_updating, ImageWithThumbsAttachment
234   -
235   - def test_should_overwrite_old_thumbnail_records_when_renaming(klass = ImageWithThumbsAttachment)
236   - attachment_model klass
237   - attachment = nil
238   - assert_created 3 do
239   - attachment = upload_file :class => klass, :filename => '/files/rails.png'
240   - end
241   - assert_not_created do # no new db_file records
242   - attachment.filename = 'rails2.png'
243   - attachment.save
244   - assert !attachment.reload.size.zero?
245   - assert_equal 'rails2.png', attachment.filename
246   - end
247   - end
248   -
249   - test_against_subclass :test_should_overwrite_old_thumbnail_records_when_renaming, ImageWithThumbsAttachment
250   -
251   - def test_should_handle_jpeg_quality
252   - attachment_model ImageWithThumbsAttachment
253   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
254   - full_size = attachment.size
255   - attachment_model LowerQualityAttachment
256   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
257   - lq_size = attachment.size
258   - assert lq_size <= full_size * 0.9, 'Lower-quality JPEG filesize should be congruently smaller'
259   -
260   - attachment_model ImageWithPerThumbJpegAttachment
261   - attachment = upload_file :filename => '/files/rails.jpg', :content_type => 'image/jpeg'
262   - assert_file_jpeg_quality attachment, :thumb, 90
263   - assert_file_jpeg_quality attachment, :avatar, 85
264   - assert_file_jpeg_quality attachment, :large, 75
265   - assert_file_jpeg_quality attachment, nil, 75
266   - end
267   - else
268   - def test_flunk
269   - puts "RMagick not installed, no tests running"
270   - end
271   - end
272   -end
vendor/plugins/pothoven-attachment_fu/test/schema.rb
... ... @@ -1,136 +0,0 @@
1   -ActiveRecord::Schema.define(:version => 0) do
2   - create_table :attachments, :force => true do |t|
3   - t.column :db_file_id, :integer
4   - t.column :parent_id, :integer
5   - t.column :imageable_id, :integer
6   - t.column :imageable_type, :string, :limit => 255
7   - t.column :thumbnail, :string
8   - t.column :filename, :string, :limit => 255
9   - t.column :content_type, :string, :limit => 255
10   - t.column :size, :integer
11   - t.column :width, :integer
12   - t.column :height, :integer
13   - t.column :aspect_ratio, :float
14   - end
15   -
16   - create_table :file_attachments, :force => true do |t|
17   - t.column :parent_id, :integer
18   - t.column :thumbnail, :string
19   - t.column :filename, :string, :limit => 255
20   - t.column :content_type, :string, :limit => 255
21   - t.column :size, :integer
22   - t.column :width, :integer
23   - t.column :height, :integer
24   - t.column :type, :string
25   - t.column :aspect_ratio, :float
26   - end
27   -
28   - create_table :file_attachments_with_string_id, :id => false, :force => true do |t|
29   - t.column :id, :string
30   - t.column :parent_id, :string
31   - t.column :thumbnail, :string
32   - t.column :filename, :string, :limit => 255
33   - t.column :content_type, :string, :limit => 255
34   - t.column :size, :integer
35   - t.column :width, :integer
36   - t.column :height, :integer
37   - t.column :type, :string
38   - t.column :aspect_ratio, :float
39   - end
40   -
41   - create_table :gd2_attachments, :force => true do |t|
42   - t.column :parent_id, :integer
43   - t.column :thumbnail, :string
44   - t.column :filename, :string, :limit => 255
45   - t.column :content_type, :string, :limit => 255
46   - t.column :size, :integer
47   - t.column :width, :integer
48   - t.column :height, :integer
49   - t.column :type, :string
50   - end
51   -
52   - create_table :image_science_attachments, :force => true do |t|
53   - t.column :parent_id, :integer
54   - t.column :thumbnail, :string
55   - t.column :filename, :string, :limit => 255
56   - t.column :content_type, :string, :limit => 255
57   - t.column :size, :integer
58   - t.column :width, :integer
59   - t.column :height, :integer
60   - t.column :type, :string
61   - end
62   -
63   - create_table :core_image_attachments, :force => true do |t|
64   - t.column :parent_id, :integer
65   - t.column :thumbnail, :string
66   - t.column :filename, :string, :limit => 255
67   - t.column :content_type, :string, :limit => 255
68   - t.column :size, :integer
69   - t.column :width, :integer
70   - t.column :height, :integer
71   - t.column :type, :string
72   - end
73   -
74   - create_table :mini_magick_attachments, :force => true do |t|
75   - t.column :parent_id, :integer
76   - t.column :thumbnail, :string
77   - t.column :filename, :string, :limit => 255
78   - t.column :content_type, :string, :limit => 255
79   - t.column :size, :integer
80   - t.column :width, :integer
81   - t.column :height, :integer
82   - t.column :type, :string
83   - end
84   -
85   - create_table :mini_magick_attachments, :force => true do |t|
86   - t.column :parent_id, :integer
87   - t.column :thumbnail, :string
88   - t.column :filename, :string, :limit => 255
89   - t.column :content_type, :string, :limit => 255
90   - t.column :size, :integer
91   - t.column :width, :integer
92   - t.column :height, :integer
93   - t.column :type, :string
94   - end
95   -
96   - create_table :orphan_attachments, :force => true do |t|
97   - t.column :db_file_id, :integer
98   - t.column :filename, :string, :limit => 255
99   - t.column :content_type, :string, :limit => 255
100   - t.column :size, :integer
101   - end
102   -
103   - create_table :minimal_attachments, :force => true do |t|
104   - t.column :size, :integer
105   - t.column :content_type, :string, :limit => 255
106   - end
107   -
108   - create_table :db_files, :force => true do |t|
109   - t.column :data, :binary
110   - end
111   -
112   - create_table :s3_attachments, :force => true do |t|
113   - t.column :parent_id, :integer
114   - t.column :thumbnail, :string
115   - t.column :filename, :string, :limit => 255
116   - t.column :content_type, :string, :limit => 255
117   - t.column :size, :integer
118   - t.column :width, :integer
119   - t.column :height, :integer
120   - t.column :type, :string
121   - t.column :aspect_ratio, :float
122   - end
123   -
124   - create_table :cloud_files_attachments, :force => true do |t|
125   - t.column :parent_id, :integer
126   - t.column :thumbnail, :string
127   - t.column :filename, :string, :limit => 255
128   - t.column :content_type, :string, :limit => 255
129   - t.column :size, :integer
130   - t.column :width, :integer
131   - t.column :height, :integer
132   - t.column :type, :string
133   - t.column :aspect_ratio, :float
134   - end
135   -
136   -end
vendor/plugins/pothoven-attachment_fu/test/test_helper.rb
... ... @@ -1,169 +0,0 @@
1   -$LOAD_PATH.unshift(File.dirname(__FILE__))
2   -$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3   -
4   -ENV['RAILS_ENV'] = 'test'
5   -
6   -require 'rails/all'
7   -require 'test/unit'
8   -require 'pothoven-attachment_fu'
9   -include ActionDispatch::TestProcess
10   -
11   -# Define the application and configuration
12   -module RbConfig
13   - class Application < ::Rails::Application
14   - # configuration here if needed
15   - config.active_support.deprecation = :stderr
16   - end
17   -end
18   -
19   -# Initialize the application
20   -RbConfig::Application.initialize!
21   -
22   -# Setup database
23   -load(File.dirname(__FILE__) + "/schema.rb")
24   -
25   -FIXTURE_PATH = File.dirname(__FILE__) + "/fixtures"
26   -$LOAD_PATH.unshift(FIXTURE_PATH)
27   -
28   -class Test::Unit::TestCase #:nodoc:
29   - # include ActionDispatch::TestProcess
30   - def create_fixtures(*table_names)
31   - if block_given?
32   - Fixtures.create_fixtures(FIXTURE_PATH, table_names) { yield }
33   - else
34   - Fixtures.create_fixtures(FIXTURE_PATH, table_names)
35   - end
36   - end
37   -
38   - def setup
39   - Attachment.saves = 0
40   - DbFile.transaction { [Attachment, FileAttachment, OrphanAttachment, MinimalAttachment, DbFile].each { |klass| klass.delete_all } }
41   - attachment_model self.class.attachment_model
42   - end
43   -
44   - def teardown
45   - FileUtils.rm_rf File.join(File.dirname(__FILE__), 'files')
46   - # Files generated by random_tempfile_filename
47   - FileUtils.rm_rf Dir['[0-9]*.{png,jpg}']
48   - end
49   -
50   - #self.use_transactional_fixtures = true
51   - #self.use_instantiated_fixtures = false
52   -
53   - def self.attachment_model(klass = nil)
54   - @attachment_model = klass if klass
55   - @attachment_model
56   - end
57   -
58   - def self.test_against_class(test_method, klass, subclass = false)
59   - define_method("#{test_method}_on_#{:sub if subclass}class") do
60   - klass = Class.new(klass) if subclass
61   - attachment_model klass
62   - send test_method, klass
63   - end
64   - end
65   -
66   - def self.test_against_subclass(test_method, klass)
67   - test_against_class test_method, klass, true
68   - end
69   -
70   - protected
71   - def upload_file(options = {})
72   - use_temp_file options[:filename] do |file|
73   -puts options
74   - opts = { :uploaded_data => fixture_file_upload(file, options[:content_type] || 'image/png') }
75   - opts.update(options.reject { |k, v| ![:imageable_type, :imageable_id].include?(k) })
76   - att = attachment_model.create opts
77   - att.reload unless att.new_record?
78   - return att
79   - end
80   - end
81   -
82   - def upload_merb_file(options = {})
83   - use_temp_file options[:filename] do |file|
84   - att = attachment_model.create :uploaded_data => {"size" => file.size, "content_type" => options[:content_type] || 'image/png', "filename" => file, 'tempfile' => fixture_file_upload(file, options[:content_type] || 'image/png')}
85   - att.reload unless att.new_record?
86   - return att
87   - end
88   - end
89   -
90   - def use_temp_file(fixture_filename)
91   - temp_path = File.join('/tmp', File.basename(fixture_filename))
92   - temp_dir = File.join(FIXTURE_PATH, 'tmp')
93   - use_file = File.join(FIXTURE_PATH, temp_path)
94   - FileUtils.mkdir_p temp_dir
95   - FileUtils.cp File.join(FIXTURE_PATH, fixture_filename), use_file
96   - yield use_file
97   - ensure
98   - FileUtils.rm_rf temp_dir
99   - end
100   -
101   - def assert_created(num = 1)
102   - assert_difference attachment_model.base_class, :count, num do
103   - if attachment_model.included_modules.include? DbFile
104   - assert_difference DbFile, :count, num do
105   - yield
106   - end
107   - else
108   - yield
109   - end
110   - end
111   - end
112   -
113   - def assert_valid(record)
114   - assert record.valid?, record.errors.full_messages.join("\n")
115   - end
116   -
117   - def assert_file_jpeg_quality(model, thumbnail, expected)
118   - filename = if model.respond_to?(:full_filename)
119   - model.full_filename(thumbnail)
120   - else
121   - thumb = thumbnail ? model.thumbnails.find(:first, :conditions => { :thumbnail => thumbnail.to_s }, :include => :db_file) : model
122   - unless thumb && thumb.db_file && thumb.db_file.data && thumb.db_file.data.size > 0
123   - STDERR.puts "Cannot find DB file data for thumbnail #{thumbnail.inspect} -> Aborting JPEG quality check."
124   - return
125   - end
126   - result = Tempfile.new('dbfile_dump').path
127   - File.open(result, 'wb') { |f| f.write(thumb.db_file.data) }
128   - result
129   - end
130   - quality = %x(identify -format '%Q' "#{filename}" 2> /dev/null)
131   - if $?.success?
132   - assert_equal expected, quality.to_i, "Produced JPEG quality (thumbnail: #{thumbnail.inspect}) is incorrect."
133   - else
134   - STDERR.puts "ImageMagick's identify not found / not in PATH: can't quickly check produced image quality."
135   - end
136   - end
137   -
138   - def assert_not_created
139   - assert_created(0) { yield }
140   - end
141   -
142   - def should_reject_by_size_with(klass)
143   - attachment_model klass
144   - assert_not_created do
145   - attachment = upload_file :filename => '/files/rails.png'
146   - assert attachment.new_record?
147   - assert attachment.errors.on(:size)
148   - assert_nil attachment.db_file if attachment.respond_to?(:db_file)
149   - end
150   - end
151   -
152   - def assert_difference(object, method = nil, difference = 1)
153   - initial_value = object.send(method)
154   - yield
155   - assert_equal initial_value + difference, object.send(method)
156   - end
157   -
158   - def assert_no_difference(object, method, &block)
159   - assert_difference object, method, 0, &block
160   - end
161   -
162   - def attachment_model(klass = nil)
163   - @attachment_model = klass if klass
164   - @attachment_model
165   - end
166   -end
167   -
168   -require File.join(File.dirname(__FILE__), 'fixtures/attachment')
169   -require File.join(File.dirname(__FILE__), 'base_attachment_tests')
vendor/plugins/pothoven-attachment_fu/test/validation_test.rb
... ... @@ -1,55 +0,0 @@
1   -require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
2   -
3   -class ValidationTest < Test::Unit::TestCase
4   - def test_should_invalidate_big_files
5   - @attachment = SmallAttachment.new
6   - assert !@attachment.valid?
7   - assert @attachment.errors[:size]
8   -
9   - @attachment.size = 2000
10   - assert !@attachment.valid?
11   - assert @attachment.errors[:size], @attachment.errors.full_messages.to_sentence
12   -
13   - @attachment.size = 1000
14   - assert !@attachment.valid?
15   - assert @attachment.errors[:size].empty?
16   - end
17   -
18   - def test_should_invalidate_small_files
19   - @attachment = BigAttachment.new
20   - assert !@attachment.valid?
21   - assert @attachment.errors[:size]
22   -
23   - @attachment.size = 2000
24   - assert !@attachment.valid?
25   - assert @attachment.errors[:size], @attachment.errors.full_messages.to_sentence
26   -
27   - @attachment.size = 1.megabyte
28   - assert !@attachment.valid?
29   - assert @attachment.errors[:size].empty?
30   - end
31   -
32   - def test_should_validate_content_type
33   - @attachment = PdfAttachment.new
34   - assert !@attachment.valid?
35   - assert @attachment.errors[:content_type]
36   -
37   - @attachment.content_type = 'foo'
38   - assert !@attachment.valid?
39   - assert @attachment.errors[:content_type]
40   -
41   - @attachment.content_type = 'pdf'
42   - assert !@attachment.valid?
43   - assert @attachment.errors[:content_type].empty?
44   - end
45   -
46   - def test_should_require_filename
47   - @attachment = Attachment.new
48   - assert !@attachment.valid?
49   - assert @attachment.errors[:filename]
50   -
51   - @attachment.filename = 'foo'
52   - assert !@attachment.valid?
53   - assert @attachment.errors[:filename].empty?
54   - end
55   -end
56 0 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/vendor/red_artisan/core_image/filters/color.rb
... ... @@ -1,27 +0,0 @@
1   -module RedArtisan
2   - module CoreImage
3   - module Filters
4   - module Color
5   -
6   - def greyscale(color = nil, intensity = 1.00)
7   - create_core_image_context(@original.extent.size.width, @original.extent.size.height)
8   -
9   - color = OSX::CIColor.colorWithString("1.0 1.0 1.0 1.0") unless color
10   -
11   - @original.color_monochrome :inputColor => color, :inputIntensity => intensity do |greyscale|
12   - @target = greyscale
13   - end
14   - end
15   -
16   - def sepia(intensity = 1.00)
17   - create_core_image_context(@original.extent.size.width, @original.extent.size.height)
18   -
19   - @original.sepia_tone :inputIntensity => intensity do |sepia|
20   - @target = sepia
21   - end
22   - end
23   -
24   - end
25   - end
26   - end
27   -end
28 0 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/vendor/red_artisan/core_image/filters/effects.rb
... ... @@ -1,31 +0,0 @@
1   -module RedArtisan
2   - module CoreImage
3   - module Filters
4   - module Effects
5   -
6   - def spotlight(position, points_at, brightness, concentration, color)
7   - create_core_image_context(@original.extent.size.width, @original.extent.size.height)
8   -
9   - @original.spot_light :inputLightPosition => vector3(*position), :inputLightPointsAt => vector3(*points_at),
10   - :inputBrightness => brightness, :inputConcentration => concentration, :inputColor => color do |spot|
11   - @target = spot
12   - end
13   - end
14   -
15   - def edges(intensity = 1.00)
16   - create_core_image_context(@original.extent.size.width, @original.extent.size.height)
17   -
18   - @original.edges :inputIntensity => intensity do |edged|
19   - @target = edged
20   - end
21   - end
22   -
23   - private
24   -
25   - def vector3(x, y, w)
26   - OSX::CIVector.vectorWithX_Y_Z(x, y, w)
27   - end
28   - end
29   - end
30   - end
31   -end
vendor/plugins/pothoven-attachment_fu/vendor/red_artisan/core_image/filters/perspective.rb
... ... @@ -1,25 +0,0 @@
1   -module RedArtisan
2   - module CoreImage
3   - module Filters
4   - module Perspective
5   -
6   - def perspective(top_left, top_right, bottom_left, bottom_right)
7   - create_core_image_context(@original.extent.size.width, @original.extent.size.height)
8   -
9   - @original.perspective_transform :inputTopLeft => top_left, :inputTopRight => top_right, :inputBottomLeft => bottom_left, :inputBottomRight => bottom_right do |transformed|
10   - @target = transformed
11   - end
12   - end
13   -
14   - def perspective_tiled(top_left, top_right, bottom_left, bottom_right)
15   - create_core_image_context(@original.extent.size.width, @original.extent.size.height)
16   -
17   - @original.perspective_tile :inputTopLeft => top_left, :inputTopRight => top_right, :inputBottomLeft => bottom_left, :inputBottomRight => bottom_right do |tiled|
18   - @target = tiled
19   - end
20   - end
21   -
22   - end
23   - end
24   - end
25   -end
26 0 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/vendor/red_artisan/core_image/filters/quality.rb
... ... @@ -1,25 +0,0 @@
1   -module RedArtisan
2   - module CoreImage
3   - module Filters
4   - module Quality
5   -
6   - def reduce_noise(level = 0.02, sharpness = 0.4)
7   - create_core_image_context(@original.extent.size.width, @original.extent.size.height)
8   -
9   - @original.noise_reduction :inputNoiseLevel => level, :inputSharpness => sharpness do |noise_reduced|
10   - @target = noise_reduced
11   - end
12   - end
13   -
14   - def adjust_exposure(input_ev = 0.5)
15   - create_core_image_context(@original.extent.size.width, @original.extent.size.height)
16   -
17   - @original.exposure_adjust :inputEV => input_ev do |adjusted|
18   - @target = adjusted
19   - end
20   - end
21   -
22   - end
23   - end
24   - end
25   -end
26 0 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/vendor/red_artisan/core_image/filters/scale.rb
... ... @@ -1,47 +0,0 @@
1   -module RedArtisan
2   - module CoreImage
3   - module Filters
4   - module Scale
5   -
6   - def resize(width, height)
7   - create_core_image_context(width, height)
8   -
9   - scale_x, scale_y = scale(width, height)
10   -
11   - @original.affine_clamp :inputTransform => OSX::NSAffineTransform.transform do |clamped|
12   - clamped.lanczos_scale_transform :inputScale => scale_x > scale_y ? scale_x : scale_y, :inputAspectRatio => scale_x / scale_y do |scaled|
13   - scaled.crop :inputRectangle => vector(0, 0, width, height) do |cropped|
14   - @target = cropped
15   - end
16   - end
17   - end
18   - end
19   -
20   - def thumbnail(width, height)
21   - create_core_image_context(width, height)
22   -
23   - transform = OSX::NSAffineTransform.transform
24   - transform.scaleXBy_yBy *scale(width, height)
25   -
26   - @original.affine_transform :inputTransform => transform do |scaled|
27   - @target = scaled
28   - end
29   - end
30   -
31   - def fit(size)
32   - original_size = @original.extent.size
33   - scale = size.to_f / (original_size.width > original_size.height ? original_size.width : original_size.height)
34   - resize (original_size.width * scale).to_i, (original_size.height * scale).to_i
35   - end
36   -
37   - private
38   -
39   - def scale(width, height)
40   - original_size = @original.extent.size
41   - return width.to_f / original_size.width.to_f, height.to_f / original_size.height.to_f
42   - end
43   -
44   - end
45   - end
46   - end
47   -end
48 0 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/vendor/red_artisan/core_image/filters/watermark.rb
... ... @@ -1,32 +0,0 @@
1   -module RedArtisan
2   - module CoreImage
3   - module Filters
4   - module Watermark
5   -
6   - def watermark(watermark_image, tile = false, strength = 0.1)
7   - create_core_image_context(@original.extent.size.width, @original.extent.size.height)
8   -
9   - if watermark_image.respond_to? :to_str
10   - watermark_image = OSX::CIImage.from(watermark_image.to_str)
11   - end
12   -
13   - if tile
14   - tile_transform = OSX::NSAffineTransform.transform
15   - tile_transform.scaleXBy_yBy 1.0, 1.0
16   -
17   - watermark_image.affine_tile :inputTransform => tile_transform do |tiled|
18   - tiled.crop :inputRectangle => vector(0, 0, @original.extent.size.width, @original.extent.size.height) do |tiled_watermark|
19   - watermark_image = tiled_watermark
20   - end
21   - end
22   - end
23   -
24   - @original.dissolve_transition :inputTargetImage => watermark_image, :inputTime => strength do |watermarked|
25   - @target = watermarked
26   - end
27   - end
28   -
29   - end
30   - end
31   - end
32   -end
33 0 \ No newline at end of file
vendor/plugins/pothoven-attachment_fu/vendor/red_artisan/core_image/processor.rb
... ... @@ -1,123 +0,0 @@
1   -require 'rubygems'
2   -require 'osx/cocoa'
3   -require 'active_support'
4   -
5   -require 'red_artisan/core_image/filters/scale'
6   -require 'red_artisan/core_image/filters/color'
7   -require 'red_artisan/core_image/filters/watermark'
8   -require 'red_artisan/core_image/filters/quality'
9   -require 'red_artisan/core_image/filters/perspective'
10   -require 'red_artisan/core_image/filters/effects'
11   -
12   -# Generic image processor for scaling images based on CoreImage via RubyCocoa.
13   -#
14   -# Example usage:
15   -#
16   -# p = Processor.new OSX::CIImage.from(path_to_image)
17   -# p.resize(640, 480)
18   -# p.render do |result|
19   -# result.save('resized.jpg', OSX::NSJPEGFileType)
20   -# end
21   -#
22   -# This will resize the image to the given dimensions exactly, if you'd like to ensure that aspect ratio is preserved:
23   -#
24   -# p = Processor.new OSX::CIImage.from(path_to_image)
25   -# p.fit(640)
26   -# p.render do |result|
27   -# result.save('resized.jpg', OSX::NSJPEGFileType)
28   -# end
29   -#
30   -# fit(size) will attempt its best to resize the image so that the longest width/height (depending on image orientation) will match
31   -# the given size. The second axis will be calculated automatically based on the aspect ratio.
32   -#
33   -# Scaling is performed by first clamping the image so that its external bounds become infinite, this helps when scaling so that any
34   -# rounding discrepencies in dimensions don't affect the resultant image. We then perform a Lanczos transform on the image which scales
35   -# it to the target size. We then crop the image to the traget dimensions.
36   -#
37   -# If you are generating smaller images such as thumbnails where high quality rendering isn't as important, an additional method is
38   -# available:
39   -#
40   -# p = Processor.new OSX::CIImage.from(path_to_image)
41   -# p.thumbnail(100, 100)
42   -# p.render do |result|
43   -# result.save('resized.jpg', OSX::NSJPEGFileType)
44   -# end
45   -#
46   -# This will perform a straight affine transform and scale the X and Y boundaries to the requested size. Generally, this will be faster
47   -# than a lanczos scale transform, but with a scaling quality trade.
48   -#
49   -# More than welcome to intregrate any patches, improvements - feel free to mail me with ideas.
50   -#
51   -# Thanks to
52   -# * Satoshi Nakagawa for working out that OCObjWrapper needs inclusion when aliasing method_missing on existing OSX::* classes.
53   -# * Vasantha Crabb for general help and inspiration with Cocoa
54   -# * Ben Schwarz for example image data and collaboration during performance testing
55   -#
56   -# Copyright (c) Marcus Crafter <crafterm@redartisan.com> released under the MIT license
57   -#
58   -module RedArtisan
59   - module CoreImage
60   - class Processor
61   -
62   - def initialize(original)
63   - if original.respond_to? :to_str
64   - @original = OSX::CIImage.from(original.to_str)
65   - else
66   - @original = original
67   - end
68   - end
69   -
70   - def render(&block)
71   - raise "unprocessed image: #{@original}" unless @target
72   - block.call @target
73   - end
74   -
75   - include Filters::Scale, Filters::Color, Filters::Watermark, Filters::Quality, Filters::Perspective, Filters::Effects
76   -
77   - private
78   -
79   - def create_core_image_context(width, height)
80   - output = OSX::NSBitmapImageRep.alloc.initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bytesPerRow_bitsPerPixel(nil, width, height, 8, 4, true, false, OSX::NSDeviceRGBColorSpace, 0, 0)
81   - context = OSX::NSGraphicsContext.graphicsContextWithBitmapImageRep(output)
82   - OSX::NSGraphicsContext.setCurrentContext(context)
83   - @ci_context = context.CIContext
84   - end
85   -
86   - def vector(x, y, w, h)
87   - OSX::CIVector.vectorWithX_Y_Z_W(x, y, w, h)
88   - end
89   - end
90   - end
91   -end
92   -
93   -module OSX
94   - class CIImage
95   - include OCObjWrapper
96   -
97   - def method_missing_with_filter_processing(sym, *args, &block)
98   - f = OSX::CIFilter.filterWithName("CI#{sym.to_s.camelize}")
99   - return method_missing_without_filter_processing(sym, *args, &block) unless f
100   -
101   - f.setDefaults if f.respond_to? :setDefaults
102   - f.setValue_forKey(self, 'inputImage')
103   - options = args.last.is_a?(Hash) ? args.last : {}
104   - options.each { |k, v| f.setValue_forKey(v, k.to_s) }
105   -
106   - block.call f.valueForKey('outputImage')
107   - end
108   -
109   - alias_method_chain :method_missing, :filter_processing
110   -
111   - def save(target, format = OSX::NSJPEGFileType, properties = nil)
112   - bitmapRep = OSX::NSBitmapImageRep.alloc.initWithCIImage(self)
113   - blob = bitmapRep.representationUsingType_properties(format, properties)
114   - blob.writeToFile_atomically(target, false)
115   - end
116   -
117   - def self.from(filepath)
118   - raise Errno::ENOENT, "No such file or directory - #{filepath}" unless File.exists?(filepath)
119   - OSX::CIImage.imageWithContentsOfURL(OSX::NSURL.fileURLWithPath(filepath))
120   - end
121   - end
122   -end
123   -