PageRenderTime 23ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/gems/paperclip-2.1.2/lib/paperclip.rb

https://github.com/palladius/lovd-by-less
Ruby | 244 lines | 122 code | 29 blank | 93 comment | 7 complexity | a9de4dead850880377422b7ed90177b0 MD5 | raw file
  1. # Paperclip allows file attachments that are stored in the filesystem. All graphical
  2. # transformations are done using the Graphics/ImageMagick command line utilities and
  3. # are stored in Tempfiles until the record is saved. Paperclip does not require a
  4. # separate model for storing the attachment's information, instead adding a few simple
  5. # columns to your table.
  6. #
  7. # Author:: Jon Yurek
  8. # Copyright:: Copyright (c) 2008 thoughtbot, inc.
  9. # License:: MIT License (http://www.opensource.org/licenses/mit-license.php)
  10. #
  11. # Paperclip defines an attachment as any file, though it makes special considerations
  12. # for image files. You can declare that a model has an attached file with the
  13. # +has_attached_file+ method:
  14. #
  15. # class User < ActiveRecord::Base
  16. # has_attached_file :avatar, :styles => { :thumb => "100x100" }
  17. # end
  18. #
  19. # user = User.new
  20. # user.avatar = params[:user][:avatar]
  21. # user.avatar.url
  22. # # => "/users/avatars/4/original_me.jpg"
  23. # user.avatar.url(:thumb)
  24. # # => "/users/avatars/4/thumb_me.jpg"
  25. #
  26. # See the +has_attached_file+ documentation for more details.
  27. require 'tempfile'
  28. require 'paperclip/upfile'
  29. require 'paperclip/iostream'
  30. require 'paperclip/geometry'
  31. require 'paperclip/thumbnail'
  32. require 'paperclip/storage'
  33. require 'paperclip/attachment'
  34. # The base module that gets included in ActiveRecord::Base.
  35. module Paperclip
  36. VERSION = "2.1.2"
  37. class << self
  38. # Provides configurability to Paperclip. There are a number of options available, such as:
  39. # * whiny_thumbnails: Will raise an error if Paperclip cannot process thumbnails of
  40. # an uploaded image. Defaults to true.
  41. # * image_magick_path: Defines the path at which to find the +convert+ and +identify+
  42. # programs if they are not visible to Rails the system's search path. Defaults to
  43. # nil, which uses the first executable found in the search path.
  44. def options
  45. @options ||= {
  46. :whiny_thumbnails => true,
  47. :image_magick_path => nil
  48. }
  49. end
  50. def path_for_command command #:nodoc:
  51. path = [options[:image_magick_path], command].compact
  52. File.join(*path)
  53. end
  54. def included base #:nodoc:
  55. base.extend ClassMethods
  56. end
  57. end
  58. class PaperclipError < StandardError #:nodoc:
  59. end
  60. class NotIdentifiedByImageMagickError < PaperclipError #:nodoc:
  61. end
  62. module ClassMethods
  63. # +has_attached_file+ gives the class it is called on an attribute that maps to a file. This
  64. # is typically a file stored somewhere on the filesystem and has been uploaded by a user.
  65. # The attribute returns a Paperclip::Attachment object which handles the management of
  66. # that file. The intent is to make the attachment as much like a normal attribute. The
  67. # thumbnails will be created when the new file is assigned, but they will *not* be saved
  68. # until +save+ is called on the record. Likewise, if the attribute is set to +nil+ is
  69. # called on it, the attachment will *not* be deleted until +save+ is called. See the
  70. # Paperclip::Attachment documentation for more specifics. There are a number of options
  71. # you can set to change the behavior of a Paperclip attachment:
  72. # * +url+: The full URL of where the attachment is publically accessible. This can just
  73. # as easily point to a directory served directly through Apache as it can to an action
  74. # that can control permissions. You can specify the full domain and path, but usually
  75. # just an absolute path is sufficient. The leading slash must be included manually for
  76. # absolute paths. The default value is "/:class/:attachment/:id/:style_:filename". See
  77. # Paperclip::Attachment#interpolate for more information on variable interpolaton.
  78. # :url => "/:attachment/:id/:style_:basename:extension"
  79. # :url => "http://some.other.host/stuff/:class/:id_:extension"
  80. # * +default_url+: The URL that will be returned if there is no attachment assigned.
  81. # This field is interpolated just as the url is. The default value is
  82. # "/:class/:attachment/missing_:style.png"
  83. # has_attached_file :avatar, :default_url => "/images/default_:style_avatar.png"
  84. # User.new.avatar_url(:small) # => "/images/default_small_avatar.png"
  85. # * +styles+: A hash of thumbnail styles and their geometries. You can find more about
  86. # geometry strings at the ImageMagick website
  87. # (http://www.imagemagick.org/script/command-line-options.php#resize). Paperclip
  88. # also adds the "#" option (e.g. "50x50#"), which will resize the image to fit maximally
  89. # inside the dimensions and then crop the rest off (weighted at the center). The
  90. # default value is to generate no thumbnails.
  91. # * +default_style+: The thumbnail style that will be used by default URLs.
  92. # Defaults to +original+.
  93. # has_attached_file :avatar, :styles => { :normal => "100x100#" },
  94. # :default_style => :normal
  95. # user.avatar.url # => "/avatars/23/normal_me.png"
  96. # * +path+: The location of the repository of attachments on disk. This can be coordinated
  97. # with the value of the +url+ option to allow files to be saved into a place where Apache
  98. # can serve them without hitting your app. Defaults to
  99. # ":rails_root/public/:class/:attachment/:id/:style_:filename".
  100. # By default this places the files in the app's public directory which can be served
  101. # directly. If you are using capistrano for deployment, a good idea would be to
  102. # make a symlink to the capistrano-created system directory from inside your app's
  103. # public directory.
  104. # See Paperclip::Attachment#interpolate for more information on variable interpolaton.
  105. # :path => "/var/app/attachments/:class/:id/:style/:filename"
  106. # * +whiny_thumbnails+: Will raise an error if Paperclip cannot process thumbnails of an
  107. # uploaded image. This will ovrride the global setting for this attachment.
  108. # Defaults to true.
  109. def has_attached_file name, options = {}
  110. include InstanceMethods
  111. write_inheritable_attribute(:attachment_definitions, {}) if attachment_definitions.nil?
  112. attachment_definitions[name] = {:validations => []}.merge(options)
  113. after_save :save_attached_files
  114. before_destroy :destroy_attached_files
  115. define_method name do |*args|
  116. a = attachment_for(name)
  117. (args.length > 0) ? a.to_s(args.first) : a
  118. end
  119. define_method "#{name}=" do |file|
  120. attachment_for(name).assign(file)
  121. end
  122. define_method "#{name}?" do
  123. ! attachment_for(name).original_filename.blank?
  124. end
  125. validates_each(name) do |record, attr, value|
  126. value.send(:flush_errors)
  127. end
  128. end
  129. # Places ActiveRecord-style validations on the size of the file assigned. The
  130. # possible options are:
  131. # * +in+: a Range of bytes (i.e. +1..1.megabyte+),
  132. # * +less_than+: equivalent to :in => 0..options[:less_than]
  133. # * +greater_than+: equivalent to :in => options[:greater_than]..Infinity
  134. # * +message+: error message to display, use :min and :max as replacements
  135. def validates_attachment_size name, options = {}
  136. attachment_definitions[name][:validations] << lambda do |attachment, instance|
  137. unless options[:greater_than].nil?
  138. options[:in] = (options[:greater_than]..(1/0)) # 1/0 => Infinity
  139. end
  140. unless options[:less_than].nil?
  141. options[:in] = (0..options[:less_than])
  142. end
  143. unless attachment.original_filename.blank? || options[:in].include?(instance[:"#{name}_file_size"].to_i)
  144. min = options[:in].first
  145. max = options[:in].last
  146. if options[:message]
  147. options[:message].gsub(/:min/, min.to_s).gsub(/:max/, max.to_s)
  148. else
  149. "file size is not between #{min} and #{max} bytes."
  150. end
  151. end
  152. end
  153. end
  154. # Adds errors if thumbnail creation fails. The same as specifying :whiny_thumbnails => true.
  155. def validates_attachment_thumbnails name, options = {}
  156. attachment_definitions[name][:whiny_thumbnails] = true
  157. end
  158. # Places ActiveRecord-style validations on the presence of a file.
  159. def validates_attachment_presence name, options = {}
  160. attachment_definitions[name][:validations] << lambda do |attachment, instance|
  161. if attachment.original_filename.blank?
  162. options[:message] || "must be set."
  163. end
  164. end
  165. end
  166. # Places ActiveRecord-style validations on the content type of the file assigned. The
  167. # possible options are:
  168. # * +content_type+: Allowed content types. Can be a single content type or an array. Allows all by default.
  169. # * +message+: The message to display when the uploaded file has an invalid content type.
  170. def validates_attachment_content_type name, options = {}
  171. attachment_definitions[name][:validations] << lambda do |attachment, instance|
  172. valid_types = [options[:content_type]].flatten
  173. unless attachment.original_filename.nil?
  174. unless options[:content_type].blank?
  175. content_type = instance[:"#{name}_content_type"]
  176. unless valid_types.any?{|t| t === content_type }
  177. options[:message] || ActiveRecord::Errors.default_error_messages[:inclusion]
  178. end
  179. end
  180. end
  181. end
  182. end
  183. # Returns the attachment definitions defined by each call to has_attached_file.
  184. def attachment_definitions
  185. read_inheritable_attribute(:attachment_definitions)
  186. end
  187. end
  188. module InstanceMethods #:nodoc:
  189. def attachment_for name
  190. @attachments ||= {}
  191. @attachments[name] ||= Attachment.new(name, self, self.class.attachment_definitions[name])
  192. end
  193. def each_attachment
  194. self.class.attachment_definitions.each do |name, definition|
  195. yield(name, attachment_for(name))
  196. end
  197. end
  198. def save_attached_files
  199. each_attachment do |name, attachment|
  200. attachment.send(:save)
  201. end
  202. end
  203. def destroy_attached_files
  204. each_attachment do |name, attachment|
  205. attachment.send(:queue_existing_for_delete)
  206. attachment.send(:flush_deletes)
  207. end
  208. end
  209. end
  210. end
  211. # Set it all up.
  212. if Object.const_defined?("ActiveRecord")
  213. ActiveRecord::Base.send(:include, Paperclip)
  214. File.send(:include, Paperclip::Upfile)
  215. end