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.

Error installing Ruby 2.0.0-p0 with Homebrew, OpenSSL 1.0.1e errors

This has been driving me crazy all evening. It turns out when you use Homebrew, the installation directories for OpenSSL and Readline libraries are different. Fortunately, there’s a compilation override as mentioned on the ruby-build Issues page:

RUBY_CONFIGURE_OPTS=”–with-openssl-dir=`brew –prefix openssl` –with-readline-dir=`brew –prefix readline`” rbenv install 2.0.0-p0

You can of course change which Ruby version to install, like 1.9.3-p392.

Stubbing Devise helpers to get RSpec to pass

I have literally been bashing my head into the wall this past week trying to figure out how to get RSpec view tests to pass when using Devise. I finally figured it out after a lot of trial and error because there is a particular combination of things you have to have in place to make things work.

First, the what: I added some navigation to a menu bar that only shows up if the user is logged in. It was just:

<nav>
  <% if user_logged_in? %>
    <%= link_to ...blah... %>
  <% end %>
</nav>

The trouble is, I kept getting this error:

Failure/Error: render
ActionView::Template::Error:
  undefined method `authenticate' for nil:NilClass

The first problem was figuring out why Devise’s helpers weren’t being loaded. According to the Devise documentation you should create a spec/support/devise.rb file like:

RSpec.configure do |config|
  config.include Devise::TestHelpers, :type => :controller
end

But what about running view tests? The missing line is:

RSpec.configure do |config|
  config.include Devise::TestHelpers, :type => :controller
  config.include Devise::TestHelpers, :type => :view
end

Great! But that only solves the missing helpers. What about getting current_user to actually return a user? I tried all sorts of things and spent days searching for the answer and it comes down to stubbing out the helpers … but which object? The answer is on the view itself:

module ApplicationRspecHelpers
  def stub_user
    @user = double('user')
    @user.stub(:id => 100)
    view.stub(:user_signed_in? => true)
    view.stub(:current_user => @user)
  end
end

That works exactly as I want it. So now I can write my view tests like:

require 'spec_helper'

describe 'layouts/application' do
  include ApplicationRspecHelpers

  describe 'authentication nav' do
    context 'when authenticated' do
      it 'should have Log Out' do
        stub_user
        render
        rendered.should have_selector('nav a', text: 'Log Out')
      end
    end
  end
end

iPhone fever … fading?

It feels like trolling, but an article I recently read on The Atlantic Wire describes weakening iPhone demand as reported in the Wall Street Journal. (Aside: I think using the term “fan boy blogs” is just belittling.) But it feels like the real story here is that Apple’s grip on the mindshare of would-be buyers is loosening. I don’t know for sure but there could be truth in this.

A huge weakness for Apple I’ve long felt has been a solid command in web services—or any web services beyond what iTunes scantily provides. I can’t embed or link to Apple maps, link to an Apple-based social feed, or even use Apple-hosted services. What about Keynote presentations or online editing of Pages documents? iMovie or Garage Band galleries or portfolios hosted by Apple would be huge.

Google and Amazon are way out ahead here and because they now pretty much have the backbone of the internet where all the web services live they command the future. Aside from programming in Objective C, I can’t use web APIs to push and pull information, can I? I use APIs and hosted services because I can multiply my developer power by a factor only limited by my access to funds—and outside funding can make that ceiling very very high. These companies are companies I can grow into, not grow out of.

Being a leader in devices is nice, but a saturation point gets reached where everyone has the same phone or the same app and the “cool” factor dictates that a rebel band find a new niche. Is it truly the rebels that define the future? I think there is a strong pull by them at the very least. It’s not just because something is labeled “awesome” that makes an app, a service, or a product a hit. Rather, when eyeballs and creative energy is being applied to something it gets better. And that means the innovation goes there. If innovation is solely left to Apple’s employees they can be hamstrung by layers of management or company directives. Innovation in the wild is unbridled creativity that finds organic applications for technology that a corporate mindmeld can’t achieve.

Does that mean that Apple doesn’t innovate? Of course it does—my iPhone and MacBooks are among the best-built and well-designed devices I’ve ever used on a regular basis. But Apple certainly doesn’t seem to care the web. They are only providing access to it. And if you also believe that the future is in device-agnostic connected information, then you have to look beyond pretty Gorilla Glass and aluminum to see where the data is going—and the data is not going to Apple’s servers.

Too many ideas

It needs to be more mass-market.

That is what I keep telling myself. I have been dawdling on a project I have been coding in my spare time. I threw the base of it together maybe a couple of months ago? Then a few weeks ago I started shopping it around to my friends. I saw the warts and I cringed. I saw the directions this thing could take. I seriously contemplated throwing it all into /dev/null and starting over—even up to last night.

But I just had a moment of clarity. Right now.

Just ship it.

I am laid up in bed sick and here I am on my iPhone typing away on the WordPress app and I realized that my original idea is still valid. So very much so. I still might toss the codebase away a fresh copy based mostly off it, but the core of the idea is solid. I am not going to pivot.

I felt when I came up with this idea that it wasn’t a sexy idea. After demoing it to a small number of people I got lured into the trap that it wasn’t pretty enough. That it wasn’t simple enough. That my mom wouldn’t be able to grok it. That I should pivot—is the word veer these days?

No. I am on my bed and fairly lucid and I want—nay, need—exactly what I have built right now and I know of no replacement. I still know that the direction I was going to change to is a potential future but I think my current physical condition validates my efforts.

At the end of the day I know that am the one that must be the primary use case because I saw something that wasn’t available and I know how to solve this.

Hide the iPhone address bar (navigation bar) without appearing to move the page

The popular trick most people apparently do to remove that iPhone address bar in mobile Safari is to scroll the window up by 1 pixel:

window.scrollTo(0, 1);

My problem with this is it shifts the canvas up thereby losing 1 pixel. It turns out you can specify a fraction of a pixel and the trick works just fine still:

Note: I added a 100ms delay to it because it made it work better. I tried listening to the window “load” event it just wasn’t as reliable.

Setup Rails gem Devise to work with Amazon’s Simple Email Service (SES)

This post is mostly for me to remember how to do this. :)

It turns out that getting Devise (or the built-in mailer for that matter) to send email through Amazon Web Services’ (AWS) Simple Email Service (SES) is stupid easy. Most of the work is just getting SES set up properly. After that:

1. Verify some email addresses

  • If you just set up SES you are probably still in sandbox mode. You need to add new recipients on the Verified Senders dashboard first.

2. Generate your SES SMTP Credentials

  • You must generate a new SMTP User and SMTP Password to connect ActionMailer to AWS SES. These are NOT your AWS login credentials!
  • Go to the SMTP Settings dashboard.
  • Click the button “Create My SMTP Credentials”.
  • Copy the information out—it will not be displayed again!

3. Edit your ActionMailer settings in the production.rb file

That should do it! Send yourself a test message.

Remember: you can only send to verified email addresses while in Sandbox Mode. You must request Production Mode access to send to any unverified email address. Otherwise you will probably see the Rails log error: Net::SMTPFatalError (554 Message rejected: Email address is not verified.)

Setup Amazon’s (AWS) Simple Email Service (SES) + DKIM with DreamHost’s DNS

This is mostly a note to myself on how to do this. :)

Amazon’s Simple Email Service (SES) seems pretty easy to use but working with the DreamHost DNS management proved slightly tricky because of the large amount of steps and the order of them. Getting the DNS values right was also not completely obvious. Here’s my recipe:

1. Register a Domain

  • Log into your DreamHost Panel
  • Add a domain (Domains -> Registrations)

2. Change the Domain to DNS-only

  • Click the Edit link for your domain (Domains -> Manage Domains -> Edit)
  • Scroll all the way down to the DNS Only section
  • Choose that

3. Turn on Amazon SES

  • Create your Amazon Web Services (AWS) account
  • Go to the console page
  • Click SES to get to your SES dashboard
  • Click Verify New Sender
  • Click Verify a New Email Address
  • Wait until your new email address shows up in the Email Addresses list (or hit Refresh)
  • Click on the new email address to get its Details, you should see Status: pending verification

4. Verify Your Email Address

  • You should have gotten an email with the verification link in it: click it
  • Go back to the SES dashboard and click on the new email

5. Update DNS custom records on DreamHost

  • Return to your DreamHost Panel
  • Click Domains -> Manage Domains
  • Click the DNS link under your domain
  • Scroll down to the “Add a custom DNS record to YOURDOMAIN.com” section
  • Add a TXT record with the full value:
    • Notice: SES might recommend a text record of _amazonses.YOURDOMAIN.com. Do not paste this full value in! You must remove the “.YOURDOMAIN.com” part. That’s right, just enter: _amazonses
  • You might also want to add DKIM to your domain as well.
    • Click the “copy record” link to see the full name and value.
    • Notice: Again, SES might recommend a CNAME record that looks like abcdefghijklmnop1234567890._domainkey.YOURDOMAIN.comYou need to remove “.YOURDOMAIN.com” for DreamHost.

6. Wait…!

  • It takes a while for the DNS records to propagate. You will also get an email notification that says the sender is verified and the DKIM verification is complete.