Category Archives: daily progress

Resizing (to fill) and cropping images with Paperclip :convert_options

It has been quite a while since I’ve used the Paperclip gem by ThoughtBot. I have a very simple model called Photo which has an image attribute acting as the attachment:

class Photo < ActiveRecord::Base
  attr_accessible :image
  has_attached_file :image,
    styles: {
      thumbnail: '200x200^',
      preview: '800x800^'
    },
    convert_options: {
      thumbnail: " -gravity center -crop '200x200+0+0'",
      preview: " -gravity center -crop '800x800+0+0'"
    },
  default_url: "/images/:style/missing.png"
end

For some reason I couldn’t remember how to resize images to fit neatly within a square, but after fiddling around this totally works:

  • 200×200^: This sets the output geometry to 200×200 pixels but the shortest side will be 200 pixels.
  • convert_options: This adds the extra options to:
    • -gravity center: First center the image. It’s important this is first!
    • -crop ‘200×200+0+0’: Then crop the image into a 200×200 square with 0,0 as the offset.

Getting output from Rails template helpers, plus blocks

I had something I was doing repetitively in an ERb template today and I figured I’d DRY it up by making a helper. Specifically, I was trying to output some given HTML unless a condition was met that should generate a hidden field instead—this case calls for handcrafted HTML generation.

I was doing things like:

<% ignore_these_fields = ['foo', 'bar'] %>

<% unless ignore_these_fields.include?('abc') %>
  <input type="text" name="abc" value="<%= @vals['abc'] %>" />
<% else %>
  <input type="hidden" name="abc" value="<%= @vals['abc'] %>" />
<% end %>

<% unless ignore_these_fields.include?('foo') %>
  <input type="radio" name="foo" value="<%= @vals['foo'] %>" /> One
  <input type="radio" name="foo" value="<%= @vals['foo'] %>" /> Two
<% else %>
  <input type="hidden" name="foo" value="<%= @vals['foo'] %>" />
<% end %>

<% unless ignore_these_fields.include?('bar') %>
  <select name="bar">
    <option <% 'selected' if @vals['bar']=='a'%>>blah1</option>
    <option <% 'selected' if @vals['bar']=='b'%>>blah2</option>
    <option <% 'selected' if @vals['bar']=='c'%>>blah3</option>
  </select>
<% else %>
  <input type="hidden" name="foo" value="<%= @vals['bar'] %>" />
<% end %>

Here, fairly different HTML form fields get rendered for each type of fields, and in some cases we do not want to show certain fields. So I wanted to do this instead: write a helper that would take a block and render its contents verbatim, otherwise create a hidden field.

<% ignore_these_fields = ['foo', 'bar'] %>

<% render_unless_ignored(ignore_these_fields, 'abc') do %>
  <input type="text" name="abc" value="<%= @vals['abc'] %>" />
<% end %>

<% render_unless_ignored(ignore_these_fields, 'foo') do %>
  <input type="radio" name="foo" value="<%= @vals['foo'] %>" /> One
  <input type="radio" name="foo" value="<%= @vals['foo'] %>" /> Two
<% end %>

<% render_unless_ignored(ignore_these_fields, 'bar') do %>
  <select name="bar">
    <option <% 'selected' if @vals['bar']=='a'%>>blah1</option>
    <option <% 'selected' if @vals['bar']=='b'%>>blah2</option>
    <option <% 'selected' if @vals['bar']=='c'%>>blah3</option>
  </select>
<% end %>

That’s a bit DRYer. But here came the tricky part: the helper. I had done what I thought was right:

def render_unless_ignored (ignoring_array, key)
  unless ignoring_array.include?(key)
    yield
  else
    %Q{<input type="hidden" name="#{CGI::escapeHTML key}" value="#{CGI::escapeHTML @vals[key]}" />}.html_safe
  end
end

The yielded content was showing up but the string result was not! The ERb template was not outputting it. Then a colleague pointed out that in this case we need to tell the ERb template to render the string with concat():

def render_unless_ignored (ignoring_array, key)
  unless ignoring_array.include?(key)
    yield
  else
    concat %Q{<input type="hidden" name="#{CGI::escapeHTML key}" value="#{CGI::escapeHTML @vals[key]}" />}.html_safe
  end
end

And THAT worked!

join() is slower than the

Turns out the Internet was right on this one: if you’re trying to create a big string from little ones it’s faster to << (less-than-less-than operator) on a String than to make an array of Strings and join its elements. Without diving into the Ruby code itself my guess is that strings are linked lists in memory and its end pointer is just moved, whereas making a bunch of array elements means new String objects for each and then having to walk all of the objects to form a new String in the end. (Granted, I’m using Ruby 1.8.7 still!)

Here’s the code:

require 'benchmark'
Benchmark.bm(20) do |x|
  x.report('join') do
    1_000.times do
      a = []
      1_000.times do
        a << 'This is some string stuff'
      end
      a.join
    end
  end
  x.report('<<') do
    1_000.times do
      a = ''
      1_000.times do
        a << 'This is some string stuff'
      end
      a
    end
  end
end

And the result:

          user     system      total      real
join  1.180000   0.390000   1.570000 (1.571057)
<<    1.090000   0.390000   1.480000 (1.491420)

Firebug error “invalid label” with Rails + UJS + jQuery

I’ve been playing more with Rails’ UJS via jQuery and I came across an error that took a while to track down. It turned out to be a content type problem.

Making the form was easy:

And the JavaScript hookup was also easy:

So was the Rails controller:

But Firebug kept showing the error “invalid label”. After much Googling and playing around with things I came to realize that there was one thing that was left out: the content type. Rails was returning the JSON as a string, not as a JSON data type. So a minor tweak to the controller solved everything:

Rails forms automatically insert a hidden utf8 field? (a.k.a. what’s with the checkmark/snowman?)

Yes, apparently this is true according to a response on StackOverflow. Let’s say you have a simple form from a model:

  <%= form_for @some_model do |f| %>
   ...
  <% end %>

You might see the following output in the generated HTML:

  <div style="margin:0;padding:0;display:inline">
  <input name="utf8" type="hidden" value="&#x2713;" />
  ...other stuff...
  </div>

Apparently in order to force browsers to submit the form in UTF-8 encoding mode this UTF-8 value (✓) does the trick. If you peer into the code you can see inside the actionpack form_tag_helper.rb that this is called the “snowman_tag”. A little Googling reveals this post on http://railssnowman.info:

What’s with the _utf8/_e/_snowman tag in Rails 3?

The _utf8 input tag forces Internet Explorer to properly respect your form’s character encoding.

Rails uses the accept-charset attribute in your form element to let the server know that it should be able to deal with unicode characters (think of a user searching for café).

But it looks like old snowman value &#9731; (☃) has been since replaced with the simple check mark &#x2713; (✓). 🙂

Making your bash prompt Git-aware (a.k.a. the superprompt)

I recently started on a project where I’m doing some pair programming and someone yesterday brought up the Pivotal Git scripts that help modify your Git local.name via a single command: git-pair [person1] [person2]. Then it was the case that another person said that they learned a trick of modifying their shell prompt to show the current local.name so you’d be reminded who you were working with—so you wouldn’t accidentally give attribution to someone you’re not pairing with. This turns out to be really helpful if you’re a freelancer like me who hops around different projects.

Later a nice addition was to show the current branch you’ve checked out. This is critical for me because I never remember and I’ve more than once created a new branch and forgotten to check it out.

And … today I was talking to some more devs and the request came up: “it’d be nice to know if I have modified files in my repo.”

So, I present to you a bunch of commands to add to your .bash_profile that do all of this:

function current_uname {
    uname -a | cut -d' ' -f2 | sed -e 's/..*$//'
}

function current_git_user {
    git config --get user.name
}

function current_git_branch {
    git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* (.*)/; 1/'
}

function git_repo_has_modified_files {
    git status 2> /dev/null | sed -e 's/^#.*modified:.*$/*/' -e '/^#/d' -e '/^[^*]/d' | uniq
}

export PS1='$(current_uname) [$(current_git_user)$(current_git_branch)$(git_repo_has_modified_files)] A w > '
export PS2='  > '