Get image dimensions with Paperclip in Rails

Hi, it’s been some time since the last post. Lots of work and excuses.
Today I will present a challenge that I had in a new project. The client wanted the original dimensions when uploading images. So I made a private method to extract it with the help of ImageMagick’s Geometry module.

First, add new columns through a migration:

bundle exec rails g migration AddImageDimensionsToPosts
class AddImageDimensionsToPosts < ActiveRecord::Migration[5.0]
  def up
    add_column :posts, :image_width, :integer
    add_column :posts, :image_height, :integer
  end

  def down
    remove_column :posts, :image_width, :integer
    remove_column :posts, :image_height, :integer
  end
end
bundle exec rails db:migrate

Then implement the method:

class User < ApplicationRecord
  belongs_to :team
  has_attached_file :image, {
    styles: {
      new_thumb: 'x1144',
      new_medium: '1242x',
      web_feed: '600x',
      thumb: '200x'
    }
  }

  before_save :extract_dimensions

  # .....

  private
    def extract_dimensions
    tempfile = self.temp_image_url
    unless tempfile.nil?
      geometry = Paperclip::Geometry.from_file(tempfile.sub('https', 'http'))
      geometry.auto_orient
      self.image_width = geometry.width.to_i
      self.image_height = geometry.height.to_i
    end
  end
end

As you saw we replaced https with http because it gave problems with Amazon’s AWS security which is being used to save the files.

Next we wanted to update all the users’ images that were already in the system. And as a need we created the following script:

heroku run rails console

def update_posts
  time = Time.now
  posts_count = 0
  posts_total = Post.where(image_width: nil, image_height: nil).count
  Post.where(image_width: nil, image_height: nil).find_each do |post|
    image = post.image(:original)
    geometry = Paperclip::Geometry.from_file(image.sub('https', 'http'))
    geometry.auto_orient
    post.update_attributes(image_width: geometry.width.to_i, image_height: geometry.height.to_i)
    posts_count = posts_count + 1
    puts "#{posts_count}/#{posts_total}"
  end
  puts"#{Time.now - time}"
end

update_posts

We used the find_each method instead of each, with each all the objects are loaded into memory and find_each loads one by one and in our case was much faster as it did not stress the server.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s