OS X Yosemite: Fixes for developers

Apple released OS X Yosemite to the public for free yesteday. So far, it isn’t bad. But, as a Web developer, I’ve hit a few bumps on the way, even during installation. Hopefully, if you’re a developer too, you’ll be wiser than me, do some research before installing, and maybe then this article will be of use to you.

This list isn’t meant to be exhaustive. I’m simply a Web developer often writing in Ruby nowadays, and I wish other Web developers will get back on track fast if they encounter the problems I have.


Unending installation

If you’re not a developer, the upgrade to OS X Yosemite will be quick and smooth. If you are a developer, and you’re using Homebrew to install packages, the installation may take longer, many hours longer.

Jim Lindley wrote about this issue in detail and what to do for a faster installation. The work around is simple: make sure you have a backup of your main volume, open the Terminal, and move the /usr/local directory away in your home directory:

$ mv /usr/local ~/usr-local

Once the installation is done and you complain how ugly the new Finder icon is, open the Terminal again and move that directory back:

$ mv ~/usr-local /usr/local

Alternatively, you can clean up Homebrew, removing several old packages you’re not using anymore. That way, you won’t move anything around, and the installation process won’t have too worry about dealing with a large amount of files:

$ brew cleanup

In my case, I was already in the middle of the installation. The progress indicated “About 2 minutes remaining” for 3 hours. I thought it froze, so I forced the computer to shut down by holding down the Power button.

After I complained about this issue online, I was told about this article by Jim, who recommends not to restart the computer if you’re already in the middle of the installation. Oops. Sorry about that, Jim, but thank you for the tip.

Nothing broke, luckily. After I interrupted the installation by forcing my Mac to restart, here are the steps I took to apply the workaround described above:

  • Held down Command-R on startup, before the Apple logo appears, for the OS X Recovery.
  • From the OS X Utilities window, opened Disk Utility.
  • Selected the main volume of my main media. (In my case, the greyed-out Macintosh HD.)
  • As the volume is encrypted with FileVault, clicked Unlock to unlock it using my user account password.
  • Once unlocked, clicked Mount to mount the volume, making the files accessible.
  • Quit Disk Utility.
  • From the menu bar, opened Utilities, and selected Terminal.
  • In Terminal, did the following commands (as the main volume just mounted is called Macintosh HD and my username is remi):

    $ cd "/Volumes/Macintosh HD"
    $ mv usr/local Users/remi/usr-local
    
  • Ah, but the directory wasn’t there! I had to look for it, and it was lodged in a system recovery folder. That was probably caused by my forced restart. Here’s the command I used to locate the usr/local directory:

    $ cd "/Volumes/Macintosh HD"
    $ find . -iname 'local' -type d | grep usr/local
    
  • Of course, I was smart enough to cd into the directory I found and out of it once I confirmed it was the Homebrew directory. Then, I moved it in Users/remi/usr-local, like I tried to do above.
  • Quit Terminal.
  • From the OS X Utilities window, selected Reinstall OS X.

This restarted the OS X Yosemite installation from the beginning. It asked me for my App Store account password, and redownloaded the package. That was inconvenient, but the installation went much faster than last time!

Once I started Yosemite, and looked at the Dock with the weird Finder icon in it, I moved the usr/local directory back in its place using the Terminal. (Or for me, iTerm 2.)

It’s all good. Now, on to more problems…


Xcode & Command Line Tools reinstallation

Since I’m using zsh with oh-my-zsh, starting a terminal like I have above will have a check for updates with git. That made OS X tell me the Command Line Tools needed to be installed, and offered to do so after downloading them automatically. After each upgrade of OS X, I knew I’ll have to install them again, but it used to be a manual process until now.

Although, what I didn’t expect was for Xcode to simply vanish. Maybe that was caused by my impatient restart during the installation. I had to reinstall Xcode from the App Store.


Upgrade Homebrew

You might as well do it now, after you just installed OS X Yosemite:

$ brew update
$ brew upgrade
$ brew cleanup

Although, I had problems updating Ghostscript and PhantomJS. For the earlier, the download connection simply kept dropping, so I only had to restart the upgrade over and over, and let Homebrew resume the download. As for PhantomJS, I have more details below.


Slow Ruby and Unicorn

One of my Ruby on Rails apps is using the Unicorn Web server in development, matching its production environment on Heroku. Yet strangely, Unicorn was so slow, connections to it from the Web browser kept timing out.

I found out Ruby needed to be recompiled. I’m using Ruby 2.1.2 for that Rails app. That’s not a problem, but it was compiled with Darwin 13 (OS X Mavericks) using rbenv. Assuming you’ve upgraded Homebrew like I described above, since you need the updated ruby-build package, I recompiled Ruby for Darwin 14 (OS X Yosemite) with the following:

$ rbenv install 2.1.2

It will tell you it’s already installed, but it’ll also give you the option to reinstall.

Once it’s done, calling ruby -v should show darwin14.0 instead of darwin13.0.

Naturally, I also had to reinstall my app’s gems with bundle install. However, thanks to the recompiled Ruby, Unicorn was working smoothly again.


PhantomJS cannot be compiled

If you try to upgrade PhantomJS with Homebrew on Yosemite, you’ll be disppointed to see it fail when trying to call qmake. The update for Qt in Homebrew, of which qmake is part, compiles just fine, but PhantomJS is using its own copy of Qt. As it sounds like the team behind PhantomJS is focusing on version 2 for the next update in Homebrew rather than fixing the current version, it’s unlikely there’ll be a fix for that soon.

That’s a real bummer, because I need PhantomJS to run my Cucumber tests in my Rails apps. Half of those tests are failing when PhantomJS is not available!

Luckily, you don’t really need Homebrew to get it, and you likely don’t need to recompile it. Just download the PhantomJS binary for OS X and copy it in usr/local/bin (or any other directory in your PATH), and phantomjs will work just fine. Now my Cucumber tests are all green again!


therubyracer won’t compile

Chances are you ran bundle for a new Ruby app with a Gemfile in it and you were slapped with an error message saying therubyracer couldn’t be compiled.

Don’t panic. (Like I do.)

If you ran into the other issues above, you probably have the correct versions of Ruby and GCC already installed, as well as the Xcode command line tools. You can verify, just to be sure:

$ ruby -v
ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin14.0]

$ gcc -v
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 6.0 (clang-600.0.51) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin14.0.0
Thread model: posix

$ xcode-select --install
xcode-select: error: command line tools are already installed, use "Software Update" to install updates

If your version of Ruby is older, and you have RBEnv, maybe you forgot to switch away from the system version to the newest version first?

$ ruby -v
ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-darwin12.4.0]

$ rbenv global 2.1.2

$ ruby -v
ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin14.0]

All you likely need to do is to update the libv8 gem, then try to install therubyracer again:

$ gem install libv8
$ gem install therubyracer

This should do it. Then, just bundle away!


These are the issues I experienced so far in OS X Yosemite. What problems have you run into? Do you dislike to new Finder icon as much as I do? Share your thoughts by leaving a comment below!

Ruby on Rails: Minify HTML, CSS, & JS, and compress with gzip

Update (2015-08-21): Do not use this. You will hate me for saying this, as this page is one of my most popular on the site, but after using my code on this page with Rails for quite a while, I came back on my own decision to use it. I knew compressing pages on every request would add some overhead, but I didn’t think it would be that significant – and it is, a lot.

While this would work with preprocessors like Middleman, which compresses all the files only once, doing so with an app generating pages on every request will slow down the application. You may install performance monitoring software like New Relic then toggle the compression to see the difference.

When optimising Web sites or apps for speed, any little bit helps. One of the easiest things to do is to “minify” all source files, removing all unncessary blank spaces, line breaks, and comments, and then compress them on the fly using gzip.

The simple initializer file below can be dropped in any Ruby on Rails app running via Rack (which includes Heroku) to minify all HTML, CSS, and JavaScript files, as well as compressing them with gzip for HTTP connections before sending them to the browser:

# config/initializers/compression.rb

Rails.application.configure do
  # Use environment names or environment variables:
  # break unless Rails.env.production? 
  break unless ENV['ENABLE_COMPRESSION'] == '1'
  
  # Strip all comments from JavaScript files, even copyright notices.
  # By doing so, you are legally required to acknowledge
  # the use of the software somewhere in your Web site or app:
  uglifier = Uglifier.new output: { comments: :none }

  # To keep all comments instead or only keep copyright notices (the default):
  # uglifier = Uglifier.new output: { comments: :all }
  # uglifier = Uglifier.new output: { comments: :copyright }

  config.assets.compile = true
  config.assets.debug = false

  config.assets.js_compressor = uglifier
  config.assets.css_compressor = :sass

  config.middleware.use Rack::Deflater
  config.middleware.insert_before ActionDispatch::Static, Rack::Deflater

  config.middleware.use HtmlCompressor::Rack,
    compress_css: true,
    compress_javascript: true,
    css_compressor: Sass,
    enabled: true,
    javascript_compressor: uglifier,
    preserve_line_breaks: false,
    remove_comments: true,
    remove_form_attributes: false,
    remove_http_protocol: false,
    remove_https_protocol: false,
    remove_input_attributes: true,
    remove_intertag_spaces: false,
    remove_javascript_protocol: true,
    remove_link_attributes: true,
    remove_multi_spaces: true,
    remove_quotes: true,
    remove_script_attributes: true,
    remove_style_attributes: true,
    simple_boolean_attributes: true,
    simple_doctype: false
end

Also available as a gist on GitHub.

Notes

  • The code above uses environment variables by default, which I often use to enable or disable features instead of going by the environment name.
  • Despite the point above, no matter how hard you try, Rails will only allow Sass to compress the output on production.
  • As indicated in the code comments, enabling comments: :none for the JavaScript Uglifier will strip absolutely all comments, even copyright notices. When doing so, you are legally required to acknowledge the use of the software in a note somewhere on your site or app. Alternatives are to strip comments except legal notes with comments: :copyright or keep all comments with comments: :all.
  • There seems to be no way for Sass to strip out copyright notices, or any such comments usually beginning with /*!.

OS X, Homebrew, PostgreSQL: Work around false running report by launchctl

Logos of OS X, PostgreSQL, and Homebrew.

You have PostgreSQL installed with Homebrew on OS X. After you restarted your Mac, somehow Rails or other apps using PostgreSQL will report the server is not running while trying to start it with launchctl will say otherwise.

Turns out, the .plist file used by launchctl is only checking for the existance of the .pid file written by PostgreSQL when starting up. If you don’t shut down PostgreSQL before restarting the computer, that file will stay there. When your Mac starts up again, launchctl will see that .pid file and will assume PostgreSQL is already running while it’s actually not. Annoying, I know.

Solution

  • First, make sure PostgreSQL is actually not running:

    $ ps aux | grep bin/postgres
    

    Maybe except for grep bin/postgres, the above command should display nothing. If that is the case, then PostgreSQL is not running.

  • Unload the launcher with launchctl:

    $ launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist
    
  • Remove the .pid file:

    $ rm /usr/local/var/postgres/postmaster.pid
    
  • Load the launcher with launchctl:

    $ launchctl load ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist
    
  • Check to see if PostgreSQL is running:

    $ ps aux | grep bin/postgres
    

    The above command should now display a process of PostgreSQL running.

That should bring your PostgreSQL server back up, and let Rails or whatever else use it.

Rack & Ruby on Rails: Force SSL

Nowadays, your Web app likely needs security and encryption with SSL. Once your SSL certificate and Web server are set up, one good way to ensure SSL is used is to redirect all HTTP traffic to HTTPS.

In the world of Ruby, I’ll explain how to do it for any application running with Rack or anything built with Ruby on Rails. Your Ruby on Rails application is probably running on top of Rack anyway, so the odds are you just need one of the two methods below.

Both techniques are using environment variables to enable features as I explained in another article. In this case, I’m using the FORCE_SSL variable: if it is set to '1', it means the app should force the usage of SSL connections all the time.

Force SSL with Rack

All you need to do is use the rack-ssl gem and add a line in config.ru:

  • Add this line in your Gemfile:

    gem 'rack-ssl'
    
  • Update your installation of gems:

    $ bundle install
    
  • Add this line to config.ru:

    use Rack::SSL if ENV['FORCE_SSL'] == '1'
    
  • Don’t forget to set FORCE_SSL among the environment variables for the app:

    FORCE_SSL=1
    

Chances are you want to go with this method. Many apps on different frameworks like Ruby on Rails or Sinatra is using Rack as the Web middleware between the actual application and what the Web server, such as nginx or Passenger for Apache. Heroku also uses Rack with the Unicorn Web server to serve Ruby on Rails apps.

This way, forcing SSL connections is handled by that intermediate layer rather than the app itself, so you generally won’t have to worry about making your app aware of SSL connections.

Additionally, rack-ssl is enabling a few other nice security features:

  • Flag all cookies as “secure.”
  • Set Strict-Transport-Security (HSTS) header: a way to tell the browser to only use HTTPS connections and skip redirections on subsequent visits to the HTTP site.

Force SSL with Ruby on Rails

If for some reason you have a Ruby on Rails app, yet cannot use Rack, you can always set the app itself to force SSL connections. Simply add an initializer file:

  • Save the following in config/initializers/ssl.rb:

    Rails.application.configure do
      config.force_ssl = (ENV['FORCE_SSL'] == '1')
    end
    
  • Don’t forget to set FORCE_SSL among the environment variables for the app:

    FORCE_SSL=1
    

It is not as automatic as using rack-ssl, but you don’t need any extra gems for this. There are probably ways to implement HSTS and secure cookies with this too, but I didn’t have a need to look into doing so, as I always use Rack. These missing bits aside, it does the job just fine, which is to redirect all HTTP connections to HTTPS.

Now that you see redirecting HTTP traffic to HTTPS isn’t a hard thing to do with Rack or Ruby on Rails, you have no excuse not to do it now. 😛

Lock image shown in banner made by user Hk kng and available in Wikimedia Commons.