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'))
      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'))
    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.

Solving Algorithms – Bubble Sort

Why are solving algorithms Adnilson, shouldn’t you work on building applications? Yes, you are right! The thing with algorithms is that it helps you solve problems and are good to make your mind look for solutions. This way you build a blueprint and whenever you get a problem you tackle the problem instead of being tackled by it.

In Ruby things sometimes are too easy and today I will go back to school and review the bubble sort, this algorithm is not the most efficient way of sorting but is a simple and cool exercise.
In Ruby if you want to sort say, an array you can do it by doing array.sort and bam! There it is.
The code:

 

length = array.length - 1
loop do
  swapped = false
  (0...length).each do |i|
    if array[i] > array[i+1]
      array[i], array[i+1] = array[i+1], array[i]
      swapped = true
    end
  end
  break if !swapped
end

puts array

I guess the code speaks for itself. In a lower level language the program would have an extra variable to store the value of one of the array contents in order to swap.
The first time I did this was in Pascal, then Fortran in college.

Solving Algorithms – Title Capitalisation

Today I encountered an algorithm to solve and the amazing Ruby syntax made me solve this problem with a succinct code with testing included.
All words in the title should be capitalised except a few ones like “a”, “the”, “to”, “at”, “in”, “with”, “and”, “but” and “or”.

To make this very short the solution is here:

require 'test/unit'

class MyTest &amp;lt; Test::Unit::TestCase
  test &amp;quot;capitalization&amp;quot; do
    assert_equal title_case("i love solving problems and it is fun!"),
                           ("I Love Solving Problems and It Is Fun!")
    assert_equal title_case("wHy DoeS A biRd Fly?"),
                           ("Why Does a Bird Fly?")
  end
end

def title_case(title)
  lower_list = %w(a the to at in with and but or)
  words = title.downcase.split
  words.each do |word|
    word.capitalize! unless lower_list.include?(word)
  end
  title = words.join(' ')
end

Ruby permutation method rocks!

Early today I was doing my first homework assignment for the SaaS course by University of California – Berkeley, and was making a Rspec test work. This method was meant to take 2 arguments, one array with integers and one integer. What we have to do is sum two numbers in the array until it gets equal to the second argument. Since I come from a Pascal and C background my mind started to think low level, and then I had to say “calm down Adnilson, this is Object Oriented” but, that didn’t keep me from trying. After hitting a wall I went to the Array documentation where I found Ruby’s permutation  method that permitted the program to sum all numbers in the array until it matches n, otherwise returns false. I don’t know if other programming languages have the same method, but this made me feel so happy! Below I will show the code:

def sum_to_n? arr, n
if arr.empty? || arr.length == 1
  false
  elsif arr.permutation(2).any? { |a, b| a + b == n }
    true
  else
    false
  end
end

How to Print Urls with Nokogiri

It has been a while since I made a post here, the excuses will be off and I’ll just get to the post.

I will show a way of printing a url by building a Ruby script with Nokogiri.
What I want is to print all the compressed files in the website, these are contained inside the td (table data) of tr (table rows).

require 'nokogiri'
require 'open-uri'

class Scraper
  def initilize(url)
    @url = url
  end

  def file_url
    page = Nokogiri::HTML(open(@url))
    rows = page.css('table tr')

    rows[1..-2].each do |row|
      hrefs = row.css("td a").map { |a|
        a['href'] if a['href'].match(".tar.gz")
      }.compact.uniq

      hrefs.each do |href|
        puts @url + href
      end
    end
  end
end

scrap = Scraper.new('https://cran.r-project.org/src/contrib/')

scrap.file_url

My first programming interview

First of all I finished after work the Ruby Koans, it was an awesome experience and made me understand much more about testing. It happened so fast that I felt sad for being so short but at the same time felt an inner feeling that I have accomplished something good. Rails Tutorial is next (for a second time).

My first interview. Oh when I received a phone call from a recruiter scheduling an interview for a Python position I was in complete awe! I remembered her saying: “next Tuesday at 4:30PM”. I was like: “Yes! Sure! “The following week I studied Python as a voracious bear that hunts his prey, mastered my skills and was prepared. When I went to the subway and read the confirmation email, saw that it was changed to 4PM, and the time was 3:55PM. I rushed to call the recruiter but she didn’t answer at first, the while on the train called again and got in touch with her.
I arrived late and had to wait an excruciating 20 minutes! Finally comes the girl that was going to interview me. She asked me a few pseudo technical questions which I got right and then asked me if I had completed my college education which I said no, and then she said that I wasn’t suitable for the job because of that. No tests whatsoever, then the entire interview questions were about Ruby and soon I realized that she had 0 knowledge about programming. She didn’t know that Ruby was an Object Oriented Language and that Ruby is not Ruby on Rails the later is a framework and the former is the language.
I was really pissed off and lost an opportunity (a story for a later post). It can be seen that the interviewer haven’t read my resume and also does not have respect for other people’s time.

After all life goes on and I grew from this experience and attacked coding with more power. There will be other interviews and the job that I want will come true. With hard work, habit and will-power, great things happen.