Module: Fleximage::Model::InstanceMethods
- Defined in:
- lib/fleximage/model.rb
Overview
Provides methods that every model instance that acts_as_fleximage needs.
Instance Method Summary collapse
-
#delete_image_file ⇒ Object
Delete the image file for this record.
-
#directory_path ⇒ Object
Returns the path to the master image file for this record.
-
#extension ⇒ Object
Returns original format of the image if the image_format column exists otherwise returns the globally set format.
-
#file_path ⇒ Object
Returns the path to the master image file for this record.
-
#has_image? ⇒ Boolean
Return true if this record has an image.
- #has_saved_image? ⇒ Boolean
- #image_file ⇒ Object
-
#image_file=(file) ⇒ Object
Sets the image file for this record to an uploaded file.
-
#image_file_base64=(data) ⇒ Object
Set the image for this record by reading in a file as a base64 encoded string.
-
#image_file_string=(data) ⇒ Object
Set the image for this record by reading in file data as a string.
-
#image_file_temp=(file_name) ⇒ Object
Sets the uploaded image to the name of a file in RAILS_ROOT/tmp that was just uploaded.
-
#image_file_url ⇒ Object
Return the @image_file_url that was previously assigned.
-
#image_file_url=(file_url) ⇒ Object
Assign the image via a URL, which will make the plugin go and fetch the image at the provided URL.
-
#load_image ⇒ Object
Load the image from disk/DB, or return the cached and potentially processed output image.
-
#operate(&block) ⇒ Object
Call from a .flexi view template.
-
#operate!(&block) ⇒ Object
Self destructive operate.
-
#output_image(options = {}) ⇒ Object
Convert the current output image to a jpg, and return it in binary form.
- #url_format ⇒ Object
-
#validate_image ⇒ Object
Execute image presence and validity validations.
Instance Method Details
#delete_image_file ⇒ Object
Delete the image file for this record. This is automatically ran after this record gets destroyed, but you can call it manually if you want to remove the image from the record.
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 |
# File 'lib/fleximage/model.rb', line 550 def delete_image_file return unless self.class.has_store? if self.class.db_store? update_attribute :image_file_data, nil unless frozen? elsif self.class.s3_store? AWS::S3::S3Object.delete "#{id}.#{self.class.image_storage_format}", self.class.s3_bucket else File.delete(file_path) if File.exists?(file_path) end clear_magic_attributes self end |
#directory_path ⇒ Object
Returns the path to the master image file for this record.
@some_image.directory_path #=> /var/www/myapp/uploaded_images
If this model has a created_at field, it will use a directory structure based on the creation date, to prevent hitting the OS imposed limit on the number files in a directory.
@some_image.directory_path #=> /var/www/myapp/uploaded_images/2008/3/30
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 |
# File 'lib/fleximage/model.rb', line 271 def directory_path directory = self.class.image_directory raise 'No image directory was defined, cannot generate path' unless directory # base directory directory = "#{RAILS_ROOT}/#{directory}" unless /^\// =~ directory # specific creation date based directory suffix. creation = self[:created_at] || self[:created_on] if self.class.use_creation_date_based_directories && creation "#{directory}/#{creation.year}/#{creation.month}/#{creation.day}" else directory end end |
#extension ⇒ Object
Returns original format of the image if the image_format column exists otherwise returns the globally set format.
296 297 298 299 300 301 302 303 304 305 306 307 |
# File 'lib/fleximage/model.rb', line 296 def extension if self.respond_to?( :image_format) case image_format when "JPEG" "jpg" else image_format ? image_format.downcase : self.class.image_storage_format end else self.class.image_storage_format end end |
#file_path ⇒ Object
Returns the path to the master image file for this record.
@some_image.file_path #=> /var/www/myapp/uploaded_images/123.png
290 291 292 |
# File 'lib/fleximage/model.rb', line 290 def file_path "#{directory_path}/#{id}.#{extension}" end |
#has_image? ⇒ Boolean
Return true if this record has an image.
449 450 451 |
# File 'lib/fleximage/model.rb', line 449 def has_image? @uploaded_image || @output_image || has_saved_image? end |
#has_saved_image? ⇒ Boolean
453 454 455 456 457 458 459 460 461 |
# File 'lib/fleximage/model.rb', line 453 def has_saved_image? if self.class.db_store? !!image_file_data elsif self.class.s3_store? AWS::S3::S3Object.exists?("#{id}.#{self.class.image_storage_format}", self.class.s3_bucket) elsif self.class.file_store? File.exists?(file_path) end end |
#image_file ⇒ Object
370 371 372 |
# File 'lib/fleximage/model.rb', line 370 def image_file has_image? end |
#image_file=(file) ⇒ Object
Sets the image file for this record to an uploaded file. This can be called directly, or passively like from an ActiveRecord mass assignment.
Rails will automatically call this method for you, in most of the situations you would expect it to.
# via mass assignment, the most common form you'll probably use
Photo.new(params[:photo])
Photo.create(params[:photo])
# via explicit assignment hash
Photo.new(:image_file => params[:photo][:image_file])
Photo.create(:image_file => params[:photo][:image_file])
# Direct Assignment, usually not needed
photo = Photo.new
photo.image_file = params[:photo][:image_file]
# via an association proxy
p = Product.find(1)
p.images.create(params[:photo])
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 |
# File 'lib/fleximage/model.rb', line 335 def image_file=(file) if self.class.image_file_exists(file) # Create RMagick Image object from uploaded file if file.path @uploaded_image = Magick::Image.read(file.path).first else @uploaded_image = Magick::Image.from_blob(file.read).first end # Sanitize image data @uploaded_image.colorspace = Magick::RGBColorspace @uploaded_image.density = '72' # Save meta data to database set_magic_attributes(file) # Success, make sure everything is valid @invalid_image = false save_temp_image(file) unless @dont_save_temp end rescue Magick::ImageMagickError => e error_strings = [ 'Improper image header', 'no decode delegate for this image format', 'UnableToOpenBlob', 'Must specify image size' ] if e.to_s =~ /#{error_strings.join('|')}/ @invalid_image = true else raise e end end |
#image_file_base64=(data) ⇒ Object
Set the image for this record by reading in a file as a base64 encoded string.
data = Base64.encode64(File.read('my_image_file.jpg'))
photo = Photo.find(123)
photo.image_file_base64 = data
photo.save
420 421 422 |
# File 'lib/fleximage/model.rb', line 420 def image_file_base64=(data) self.image_file_string = Base64.decode64(data) end |
#image_file_string=(data) ⇒ Object
Set the image for this record by reading in file data as a string.
data = File.read('my_image_file.jpg')
photo = Photo.find(123)
photo.image_file_string = data
photo.save
410 411 412 |
# File 'lib/fleximage/model.rb', line 410 def image_file_string=(data) self.image_file = StringIO.new(data) end |
#image_file_temp=(file_name) ⇒ Object
Sets the uploaded image to the name of a file in RAILS_ROOT/tmp that was just uploaded. Use as a hidden field in your forms to keep an uploaded image when validation fails and the form needs to be redisplayed
427 428 429 430 431 432 433 434 435 436 437 438 439 440 |
# File 'lib/fleximage/model.rb', line 427 def image_file_temp=(file_name) if !@uploaded_image && file_name && file_name.present? && file_name !~ %r{\.\./} @image_file_temp = file_name file_path = "#{RAILS_ROOT}/tmp/fleximage/#{file_name}" @dont_save_temp = true if File.exists?(file_path) File.open(file_path, 'rb') do |f| self.image_file = f end end @dont_save_temp = false end end |
#image_file_url ⇒ Object
Return the @image_file_url that was previously assigned. This is not saved in the database, and only exists to make forms happy.
444 445 446 |
# File 'lib/fleximage/model.rb', line 444 def image_file_url @image_file_url end |
#image_file_url=(file_url) ⇒ Object
Assign the image via a URL, which will make the plugin go and fetch the image at the provided URL. The image will be stored locally as a master image for that record from then on. This is intended to be used along side the image upload to allow people the choice to upload from their local machine, or pull from the internet.
@photo.image_file_url = 'http://foo.com/bar.jpg'
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 |
# File 'lib/fleximage/model.rb', line 381 def image_file_url=(file_url) @image_file_url = file_url if file_url =~ %r{^(https?|ftp)://} file = open(file_url) # Force a URL based file to have an original_filename eval <<-CODE def file.original_filename "#{file_url}" end CODE self.image_file = file elsif file_url.empty? # Nothing to process, move along else # invalid URL, raise invalid image validation error @invalid_image = true end end |
#load_image ⇒ Object
Load the image from disk/DB, or return the cached and potentially processed output image.
490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 |
# File 'lib/fleximage/model.rb', line 490 def load_image #:nodoc: @output_image ||= @uploaded_image # Return the current image if we have loaded it already return @output_image if @output_image # Load the image from disk if self.class.db_store? # Load the image from the database column if image_file_data && image_file_data.present? @output_image = Magick::Image.from_blob(image_file_data).first end elsif self.class.s3_store? # Load image from S3 filename = "#{id}.#{self.class.image_storage_format}" bucket = self.class.s3_bucket if AWS::S3::S3Object.exists?(filename, bucket) @output_image = Magick::Image.from_blob(AWS::S3::S3Object.value(filename, bucket)).first end else # Load the image from the disk @output_image = Magick::Image.read(file_path).first end if @output_image @output_image else master_image_not_found end rescue Magick::ImageMagickError => e if e.to_s =~ /unable to open (file|image)/ master_image_not_found else raise e end end |
#operate(&block) ⇒ Object
Call from a .flexi view template. This enables the rendering of operators so that you can transform your image. This is the method that is the foundation of .flexi views. Every view should consist of image manipulation code inside a block passed to this method.
# app/views/photos/thumb.jpg.flexi
@photo.operate do |image|
image.resize '320x240'
end
472 473 474 475 476 477 478 |
# File 'lib/fleximage/model.rb', line 472 def operate(&block) returning self do proxy = ImageProxy.new(load_image, self) block.call(proxy) @output_image = proxy.image end end |
#operate!(&block) ⇒ Object
Self destructive operate. This will modify the master image for this record with the updated and processed result of the operation AND SAVES THE RECORD
482 483 484 485 486 |
# File 'lib/fleximage/model.rb', line 482 def operate!(&block) operate(&block) self.image_file_string = output_image save end |
#output_image(options = {}) ⇒ Object
Convert the current output image to a jpg, and return it in binary form. options support a :format key that can be :jpg, :gif or :png
534 535 536 537 538 539 540 541 542 543 544 545 546 |
# File 'lib/fleximage/model.rb', line 534 def output_image( = {}) #:nodoc: format = ([:format] || :jpg).to_s.upcase @output_image.format = format @output_image.strip! if format == 'JPG' quality = @jpg_compression_quality || self.class.output_image_jpg_quality @output_image.to_blob { self.quality = quality } else @output_image.to_blob end ensure GC.start end |
#url_format ⇒ Object
309 310 311 |
# File 'lib/fleximage/model.rb', line 309 def url_format extension.to_sym end |
#validate_image ⇒ Object
Execute image presence and validity validations.
567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 |
# File 'lib/fleximage/model.rb', line 567 def validate_image #:nodoc: field_name = (@image_file_url && @image_file_url.present?) ? :image_file_url : :image_file # Could not read the file as an image if @invalid_image errors.add field_name, self.class. # no image uploaded and one is required elsif self.class.require_image && !has_image? errors.add field_name, self.class. # Image does not meet minimum size elsif self.class.validates_image_size && !@uploaded_image.nil? x, y = Fleximage::Operator::Base.size_to_xy(self.class.validates_image_size) if @uploaded_image.columns < x || @uploaded_image.rows < y errors.add field_name, self.class. end end end |