dragonfly 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of dragonfly might be problematic. Click here for more details.

data/.yardopts CHANGED
@@ -9,4 +9,5 @@ extra_docs/Shortcuts.md
9
9
  extra_docs/Analysers.md
10
10
  extra_docs/Processing.md
11
11
  extra_docs/Encoding.md
12
+ extra_docs/ExampleUseCases.md
12
13
  LICENSE
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.1
1
+ 0.4.2
data/dragonfly.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{dragonfly}
8
- s.version = "0.4.1"
8
+ s.version = "0.4.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Mark Evans"]
12
- s.date = %q{2010-01-07}
12
+ s.date = %q{2010-01-10}
13
13
  s.email = %q{mark@new-bamboo.co.uk}
14
14
  s.extra_rdoc_files = [
15
15
  "LICENSE",
@@ -1,17 +1,196 @@
1
1
  Example Use Cases
2
2
  =================
3
3
 
4
+ This document is concerned with different Dragonfly configurations, for various use cases.
5
+
6
+ In a Rails app the configuration would generally be done in an initializer.
7
+
8
+ In other Rack-based apps it could be config.ru, or anywhere where the application is generally set up.
9
+
4
10
  Image thumbnails in Rails
5
11
  -------------------------
12
+ See {file:UsingWithRails}
13
+
14
+
15
+ Image thumbnails in Rails, hosted on Heroku with S3 storage
16
+ -----------------------------------------------------------
17
+ {http://heroku.com Heroku} is a commonly used platform for hosting Rack-based websites.
18
+ The following assumes your site is set up for deployment onto Heroku.
19
+
20
+ As explained in {file:UsingWithRails}, we can use a generator to create an initializer for setting up Dragonfly.
21
+
22
+ ./script/generate dragonfly_app images
23
+
24
+ The default configuration won't work out of the box for Heroku, because
25
+
26
+ - Heroku doesn't allow saving files to the filesystem (although it does use tempfiles)
27
+ - We won't need {http://tomayko.com/src/rack-cache/ Rack::Cache} on Heroku because it already uses the caching proxy {http://varnish.projects.linpro.no/ Varnish}, which we can make use of
28
+
29
+ Instead of the normal {Dragonfly::DataStorage::FileDataStore FileDataStore}, we can use the {Dragonfly::DataStorage::S3DataStore S3DataStore}.
30
+ Amazon's {http://aws.amazon.com/s3 S3} is a commonly used platform for storing data.
31
+
32
+ The following assumes you have an S3 account set up, and know your provided 'access key' and 'secret'.
33
+
34
+ Assuming we don't bother with any caching for development/testing environments, our environment.rb then has:
35
+
36
+ config.gem 'rmagick', :lib => 'RMagick'
37
+ config.gem 'dragonfly', :source => "http://www.gemcutter.org"
38
+
39
+ (these are ignored by Heroku but you might want them locally)
40
+
41
+ The gems file for Heroku, `.gems`, has
42
+
43
+ dragonfly
44
+
45
+ (rmagick not needed because it is already installed)
46
+
47
+ Then in our configuration initializer, we replace
48
+
49
+ c.datastore.configure do |d|
50
+ d.root_path = "#{Rails.root}/public/system/dragonfly/#{Rails.env}"
51
+ end
52
+
53
+ with
54
+
55
+ # Use S3 for production
56
+ if Rails.env == 'production'
57
+ c.datastore = Dragonfly::DataStorage::S3DataStore.new
58
+ c.datastore.configure do |d|
59
+ d.bucket_name = 'my_s3_bucket_name'
60
+ d.access_key_id = ENV['S3_KEY'] || raise("ENV variable 'S3_KEY' needs to be set")
61
+ d.secret_access_key = ENV['S3_SECRET'] || raise("ENV variable 'S3_SECRET' needs to be set")
62
+ end
63
+ # and filesystem for other environments
64
+ else
65
+ c.datastore.configure do |d|
66
+ d.root_path = "#{Rails.root}/public/system/dragonfly/#{Rails.env}"
67
+ end
68
+ end
69
+
70
+ We've left the datastore as {Dragonfly::DataStorage::FileDataStore FileDataStore} for non-production environments.
71
+
72
+ As you can see we've used `ENV` to store the S3 access key and secret to avoid having them in the repository.
73
+ Heroku has a {http://docs.heroku.com/config-vars way of setting these} using the command line (we only have to do this once).
74
+
75
+ From your app's directory:
76
+
77
+ heroku config:add S3_KEY=XXXXXXXXX S3_SECRET=XXXXXXXXXX
78
+
79
+ Obviously you replace 'XXXXXXXXX' with your access key and secret.
80
+
81
+ Now you can benefit use Dragonfly in the normal way, benefitting from super-fast images served straight from Heroku's cache!
82
+
83
+ The only downside is that Heroku's cache is cleared every time you deploy, so if this is an issue you may want to look into using something like
84
+ a Memcached add-on, or maybe an after-deploy hook for hitting specific Dragonfly urls you want to cache, etc.
85
+ It won't be a problem for most sites though.
86
+
87
+
88
+ Attaching files to ActiveRecord models with no processing or encoding
89
+ ---------------------------------------------------------------------
90
+ Although Dragonfly is normally concerned with processing and encoding, you may want to just use it with arbitrary uploaded files
91
+ (e.g. .doc, .xls, .pdf files, etc.) without processing or encoding them, so as to still benefit from the {file:ActiveRecord ActiveRecord Extensions} API.
92
+
93
+ The below shows how to do it in Rails, but the principles are the same in any context.
94
+ Let's generate a configuration for a Dragonfly App called 'attachments'
6
95
 
7
- Rails thumbnails on Heroku with S3
8
- ----------------------------------
96
+ ./script/generate dragonfly_app attachments
97
+
98
+ This generates an initializer for configuring the Dragonfly App 'attachments'.
99
+
100
+ We won't be using RMagick or Rack::Cache (as there is no processing), so our environment.rb only has:
101
+
102
+ config.gem 'dragonfly', :source => 'http://gemcutter.org'
103
+
104
+ and in the generated configuration, we DELETE the line
105
+
106
+ app.configure_with(Dragonfly::RMagickConfiguration)
107
+
108
+ Then in the configure block, we add the lines
109
+
110
+ c.url_handler.configure do |u|
111
+ # ...
112
+ u.protect_from_dos_attacks = false
113
+ end
114
+ c.register_analyser(Dragonfly::Analysis::FileCommandAnalyser)
115
+ c.register_encoder(Dragonfly::Encoding::TransparentEncoder)
116
+
117
+ We don't need to protect the urls from Denial-of-service attacks as we aren't doing any expensive processing.
118
+ The {Dragonfly::Analysis::FileCommandAnalyser FileCommandAnalyser} is needed to know the mime-type of the content,
119
+ and the {Dragonfly::Encoding::TransparentEncoder TransparentEncoder} is like a 'dummy' encoder which does nothing
120
+ (the way to switch off encoding may change in the future).
121
+
122
+ If a user uploads a file called 'report.pdf', then normally the original file extension will be lost.
123
+ Thankfully, to record it is as easy as adding an 'ext' column as well as the usual uid column to our migration
124
+ (see {file:ActiveRecord} for more info about 'magic attributes'):
125
+
126
+ add_column :my_models, :attachment_uid, :string
127
+ add_column :my_models, :attachment_ext, :string
128
+
129
+ Then we include a helper method in our model for setting the correct file extension when we link to the attachment:
130
+
131
+ class MyModel < ActiveRecord::Base
132
+
133
+ attachment_accessor :attachment
134
+
135
+ def url_for_attachment
136
+ attachment.url :format => attachment_ext
137
+ end
138
+ end
139
+
140
+ Now we can add links to the attached file in our views:
141
+
142
+ <%= link_to 'Attachment', @my_model.url_for_attachment %>
9
143
 
10
- Serving attachments with no processing
11
- --------------------------------------
12
144
 
13
145
  Generating test data
14
146
  --------------------
147
+ We may want to generate a load of test data in a test / populate script.
148
+
149
+ Each {Dragonfly::App Dragonfly App} has a 'generate' method, which returns an {Dragonfly::ExtendedTempObject ExtendedTempObject} with generated data.
150
+ The actual generation is delegated to the registered processors (along with any args passed in).
151
+
152
+ For example, if our app is registered with the {Dragonfly::Processing::RMagickProcessor RMagickProcessor} (which is already done if using with one of
153
+ the Rails helper files/generators)
154
+
155
+ Dragonfly::App[:my_app].register_processor(Dragonfly::Processing::RMagickProcessor)
156
+
157
+ then we can generate images of different sizes/formats):
158
+
159
+ image = Dragonfly::App[:my_app].generate(300, 200) # creates a png image of size 300x200 (as an ExtendedTempObject)
160
+ image.to_file('out.png') # writes to file 'out.png'
161
+ image = Dragonfly::App[:my_app].generate(50, 50, :gif) # creates a gif image of size 50x50
162
+
15
163
 
16
164
  Text image replacement
17
165
  ----------------------
166
+ A common technique for making sure a specific font is displayed on a website is replacing text with images.
167
+
168
+ We can easily use Dragonfly to do this on-the-fly.
169
+
170
+ The {Dragonfly::Processing::RMagickProcessor RMagickProcessor} has a 'text' method, which takes content in the form of text,
171
+ and creates an image of the text, given the options passed in.
172
+
173
+ We can also make use of the simple {Dragonfly::DataStorage::TransparentDataStore TransparentDataStore}, where rather than fetch
174
+ data for a given uid, the uid IS the data.
175
+
176
+ The configuration will look something like:
177
+
178
+ Dragonfly::App[:text].configure do |c|
179
+ c.datastore = Dragonfly::DataStorage::TransparentDataStore.new
180
+ c.register_analyser(Dragonfly::Analysis::FileCommandAnalyser)
181
+ c.register_processor(Dragonfly::Processing::RMagickProcessor)
182
+ c.register_encoder(Dragonfly::Encoding::RMagickEncoder)
183
+ c.parameters.configure do |p|
184
+ p.default_format = :png
185
+ p.default_processing_method = :text
186
+ end
187
+ end
188
+
189
+ We need the {Dragonfly::Analysis::FileCommandAnalyser FileCommandAnalyser} for mime-type analysis.
190
+
191
+ Then when we visit a url like
192
+
193
+ url = Dragonfly::App[:text].url_for('some text', :processing_options => {:font_size => 30, :font_family => 'Monaco'})
194
+
195
+ we get a png image of the text. We could easily wrap this in some kind of helper if we use it often.
196
+
data/extra_docs/Index.md CHANGED
@@ -19,6 +19,7 @@ Use the links at the top-right to navigate around the code, or jump straight to
19
19
  - {file:Processing.md Processing}
20
20
  - {file:Encoding.md Encoding}
21
21
  - {file:Shortcuts.md Shortcuts for processing and encoding}
22
+ - {file:ExampleUseCases.md Example use cases}
22
23
 
23
24
  Installation
24
25
  ------------
@@ -82,3 +82,6 @@ but make sure to change the 'secret' configuration option, so as to protect your
82
82
  # :metastore => "file:#{Rails.root}/tmp/dragonfly/cache/meta",
83
83
  # :entitystore => "file:#{Rails.root}/tmp/dragonfly/cache/body"
84
84
  # }
85
+
86
+
87
+ To see what you can do with the active record accessors, see {file:ActiveRecord}.
@@ -1,4 +1,25 @@
1
1
  module Dragonfly
2
+
3
+ # An ExtendedTempObject is just a TempObject that belongs to a Dragonfly App.
4
+ #
5
+ # Because of this, it can make use of the app's registered processors, encoders and analysers
6
+ #
7
+ # Analysis methods can be accessed on the object itself, e.g. for a registered analysis method 'width', we have
8
+ # temp_object.width # ===> 280
9
+ #
10
+ # Processing methods can be accessed using 'process', e.g. for a registered process method 'resize', we have
11
+ # temp_object.process(:resize, {:some => 'option'}) # ===> processed ExtendedTempObject
12
+ #
13
+ # Similarly, encoding with the method 'encode' delegates to the app's registered encoders
14
+ # temp_object.encode(:png, {:some => 'option'}) # ===> encoded ExtendedTempObject
15
+ #
16
+ # We can use bang methods to operate on the temp_object itself, rather than return a new one:
17
+ # temp_object.process!(:resize, {:some => 'option'})
18
+ # temp_object.encode!(:png, {:some => 'option'})
19
+ #
20
+ # You can make use of the app's registered parameter shortcuts (for processing and encoding in one go) using 'transform', e.g.
21
+ # temp_object.transform('300x200', :gif) # ===> return a new processed and encoded ExtendedTempObject
22
+ # temp_object.transform!('300x200', :gif) # ===> operate on self
2
23
  class ExtendedTempObject < TempObject
3
24
 
4
25
  # Exceptions
@@ -52,8 +52,8 @@ module Dragonfly
52
52
  end
53
53
 
54
54
  def from_args(*args)
55
- if args.empty? then new
56
- elsif args.length == 1 && args.first.is_a?(Hash) then new(args.first)
55
+ if args.empty? then new_with_defaults
56
+ elsif args.length == 1 && args.first.is_a?(Hash) then new_with_defaults(args.first)
57
57
  elsif args.length == 1 && args.first.is_a?(Parameters) then args.first.dup
58
58
  else from_shortcut(*args)
59
59
  end
@@ -1,6 +1,32 @@
1
1
  require 'tempfile'
2
2
 
3
3
  module Dragonfly
4
+
5
+ # A TempObject is used for HOLDING DATA.
6
+ # It's the thing that is passed between the datastore, the processor and the encoder, and is useful
7
+ # for separating how the data was created and how it is later accessed.
8
+ #
9
+ # You can initialize it various ways:
10
+ #
11
+ # temp_object = Dragonfly::TempObject.new('this is the content') # with a String
12
+ # temp_object = Dragonfly::TempObject.new(File.new('path/to/content')) # with a File
13
+ # temp_object = Dragonfly::TempObject.new(some_tempfile) # with a Tempfile
14
+ # temp_object = Dragonfly::TempObject.new(some_other_temp_object) # with another TempObject
15
+ #
16
+ # However, no matter how it was initialized, you can always access the data a number of ways:
17
+ #
18
+ # temp_object.data # returns a data string
19
+ # temp_object.file # returns a file object holding the data
20
+ # temp_object.path # returns a path for the file
21
+ #
22
+ # The data/file are created lazily, something which you may wish to take advantage of.
23
+ #
24
+ # For example, if a TempObject is initialized with a file, and temp_object.data is never called, then
25
+ # the data string will never be loaded into memory.
26
+ #
27
+ # Conversely, if the TempObject is initialized with a data string, and neither temp_object.file nor temp_object.path
28
+ # are ever called, then the filesystem will never be hit.
29
+ #
4
30
  class TempObject
5
31
 
6
32
  # Class configuration
@@ -231,13 +231,13 @@ describe Dragonfly::Parameters do
231
231
  @parameters_class.default_format = :tif
232
232
  end
233
233
 
234
- it "should be the same as 'new' if empty args" do
235
- @parameters_class.from_args.should == @parameters_class.new
234
+ it "should be the same as 'new_with_defaults' if empty args" do
235
+ @parameters_class.from_args.should == @parameters_class.new_with_defaults
236
236
  end
237
237
 
238
- it "should treat the arguments as actual parameter values if args is a single hash" do
238
+ it "should treat the arguments as actual parameter values (including defaults) if args is a single hash" do
239
239
  @parameters_class.from_args(:uid => 'some_uid', :processing_method => :resize).
240
- should == @parameters_class.new(:uid => 'some_uid', :processing_method => :resize)
240
+ should == @parameters_class.new_with_defaults(:uid => 'some_uid', :processing_method => :resize)
241
241
  end
242
242
 
243
243
  it "should simply return the same parameters if args is a single parameters object" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dragonfly
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Evans
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-07 00:00:00 +00:00
12
+ date: 2010-01-10 00:00:00 +00:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency