Autonomous Machine

Showing Articles

Convert string values to Ruby objects

On a project at work we've started to use environment variables to toggle features on and off in the application. We're just getting into feature toggling, and this seemed to be the best lightest-weight way to get started.

Since environment variables are strings, and some of our values will be objects of other types, we needed a way to convert these strings into Ruby objects. A preliminary search yielded many options that utilized complicated regular expressions and other gymnastics. There had to be a better way.

Enter YAML. It supports serializing the types we needed:

irb(main):001:0> require 'yaml'
=> true
irb(main):002:0> YAML.load('true')
=> true
irb(main):003:0> YAML.load('108')
=> 108
irb(main):004:0> YAML.load('just a string')
=> "just a string"

Beautiful.

  • October 03, 2012
  • Article
  • Ruby

Troubleshooting db:push errors on Heroku

Here is the error I was seeing today (truncated for brevity):

$ heroku db:push --app=my-app-name --confirm=my-app-name
Loaded Taps v0.3.23
Auto-detected local database: postgres://localhost/app_development?encoding=utf8

Sending schema
Schema:        100% |==========================================| Time: 00:00:29
Sending indexes
table_1:       100% |==========================================| Time: 00:00:01
schema_migrat: 100% |==========================================| Time: 00:00:00
table_2:       100% |==========================================| Time: 00:00:00
Sending data
20 tables, 2,783 records
table_3:       0% |                                          | ETA:  --:--:--
Saving session to push_201205300813.dat..
!!! Caught Server Exception
HTTP CODE: 500
Taps Server Error: LoadError: no such file to load -- sequel/adapters/
["/app/.bundle/gems/ruby/1.9.1/gems/sequel-3.20.0/lib/sequel/core.rb:249:in `require'", ...

This was caused by my app not having a DATABASE_URL config variable set. I assumed that db:push would fail much earlier if it wasn't able to connect to a database, but this turned out to not be accurate.

The simple solution was to promote the existing database:

$ heroku pg:promote HEROKU_POSTGRESQL_COPPER --app=my-app-name

To find the name of the database to use in the previous command, use heroku config --app=my-app-name. It should have a name like HEROKU_POSTGRESQL_*_URL.

  • May 30, 2012
  • Article
  • Heroku, Taps

Running Ruby 1.9.3 on Heroku Cedar

Heroku now supports specifying a Ruby version in an application's Gemfile:

# Gemfile
ruby '1.9.3'

This requires Bundler 1.2.0, which can be installed with the --pre flag:

gem install bundler --pre

You also need to move 'bin' to the beginning of your application's PATH so the correct Ruby binary is found when starting your web processes:

heroku config:add PATH=bin:vendor/bundle/ruby/1.9.1/bin:/usr/local/bin:/usr/bin:/bin --app YOU_APP_NAME

Commit the Gemfile changes and push to Heroku, and your app should be running under Ruby 1.9.3!

  • May 23, 2012
  • Article
  • Heroku, Ruby

Use Active Model Serializers with Mongoid

I'm adding some new features to Forkchop using Ember, ember-rails, and the associated active_model_serializers. The only hiccup is that I'm using Mongoid, and Active Model Serializers only hooks into Active Record when it loads. This means that Rails doesn't automatically look for the appropriate serializer when using render json: @object.

To remedy this, I added the following lines from this Gist to config/initializers/mongoid_active_model_initializers:

Mongoid::Document.send(:include, ActiveModel::SerializerSupport)
Mongoid::Criteria.delegate(:active_model_serializer, to: :to_a)
  • May 05, 2012
  • Article
  • Active Model Serializers, Ember, Mongoid, Rails

Store Hashie::Mash objects in Mongoid Documents

I've started using Mongoid's support for abitrary field types on a project. It involves working with a lot of nested hashes that are the result of parsing JSON, and I've found wrapping a Hashie::Mash around these data structures helps keep the code interacting with them clean:

doc.data.key.another_key.and_another_key
# vs
doc.data['key']['another_key']['and_another_key']

Since Hashie::Mash objects are just a subclass of Ruby's standard Hash, they can be stored in a field that's defined as a Hash in Mongoid:

class Doc
  include Mongoid::Document
  field :data, type: Hash
end

But when these documents are loaded back out of the database, the data field will contain a standard Hash. I'd like these hashes to be Hashie::Mash instances. To accomplish this, I defined a new column type for Mongoid called Mashed:

class Mashed
  include Mongoid::Fields::Serializable

  def deserialize(object)
    Hashie::Mash.new(object)
  end

  def serialize(object)
    Hash[object]
  end
end

That's all that is required to create a new column type in Mongoid, which can be specified just like any other in your document class:

class Doc
  include Mongoid::Document
  field :data, type: Mashed
end

Now I can save and load documents with Hashie::Mash fields. This is a trivally simple example, but by replacing the implementations of deserialize and serialize above, just about any kind of object could be persisted in a Mongoid document.

  • March 24, 2012
  • Article
  • MongoDB, Mongoid, Ruby

Tell Sprockets to precompile files other than application.js

I usually bundle all of a Rails project's JavaScript together. Occasionally, only a few pages need a large JavaScript library, and I don't want it to have to be downloaded on every page of the application. In these situations, I don't require the large library file or it's dependencies in application.js so it won't be bundled with the rest of the project's scripts. I'll add a script tag for the library to just the pages that need it, which works locally in development mode. And then inevitably I deploy and the additional files can't be found on the server because they haven't been precompiled.

It is in the docs, but I always seem to forget that for Sprockets to precompile anything other than application.js, the additional files must be specifed in config/application.rb:

config.assets.precompile += ['another_file.js']

That's all there is to it.

  • March 17, 2012
  • Article
  • Rails, Sprockets

Teaching Ruby/ProgressBar to play nice with log files

From my pull request:

We have several scripts we use during application development that monitor long running processes with ruby-progressbar. We also have these scripts running in automated environments (such as CI), and the output in these situations is very noisy. We could alter the scripts, but I think it would be nicer if this library could gracefully handle these situations.

This patch adds a baseline behavior in non-tty environments so that things like log files aren't filled with every frame of the progress bar animation.

This was merged into the master branch, so one can pick up the change by using a git source in her Gemfile.

  • December 17, 2011
  • Article
  • Ruby

A Brief Summary of 2 Mongoid Search Libraries

In the course of developing Forkchop, I've tried out a few of the Mongoid-compatible search plugins.

The goal of these libraries is to provide lightweight search functionality that precludes the need for a full search engine. And while most projects will graduate to something like Sphinx (or IndexTank or Lucene/Solr), it's nice to be able to start out with something simpler when a project's search needs are still basic.

Mongoid Search

This library is a better choice for searching the text of articles. It doesn't offer nearly as many options as Mongoid Fulltext Search, but its code is much shorter and extensible. I am currently using this library and paginating result sets with Kaminari.

Mongoid Fulltext Search

This project is best suited for providing autocomplete-type functionality. I tried to use it first, but ran into some problems trying to modify it's behavior (for example, there isn't an easy way to use an $any query instead of $all without overriding a large internal method).

  • October 17, 2011
  • Article
  • mongoid, rails, search

Cucumber, Capybara, Selenium, and Alerts

Although I try to avoid alert boxes in general, sometimes using them makes sense, especially when initially building out a feature.

This morning I was using Cucumber (and Capybara) to test deleting an object on a small project, and I needed to figure out how to click OK to dismiss in an alert and have the scenario continue. Here's the Cucumber step I ended up using:

When /^I click OK in the alert box$/ do
  page.driver.browser.switch_to.alert.accept
end

alert is returning an instance of Selenium::WebDriver::Alert, which also responds to dismiss and send_keys should you need to do something other than just click OK.

  • August 25, 2011
  • Article
  • Capybara, Cucumber, Ruby, Selenium

Inheritable Page Attributes in Rails

On most webpages there are a number of what I call 'page attributes'. These are little bits of data that have to be set based on the context of the app: the page title, a body class, etc.

It's easy enough to just use content_for to handle this scenario:

# in a view template
content_for(:title, 'Epic Page Title')

# in the page layout
yield :title

But I've found I often want to define these things at a higher level, perhaps at the controller level, either using a class method or inside an action body like this:

class UnicornsController
  page_attr :body_class, 'unicorns'
  def party
    # such a special action deserves a special class
    page_attr :body_class, 'unicorn-party'
  end
end

Or even in a view:

<%- page_attr :body_class, 'out-of-control-unicorn-shindig' -%>

This is a contrived example, but the idea is page attributes are inherited the way one would expect (controller class -> controller action -> template), while potentially being overridden at the lower levels. Here's the code:

# in app/controllers/application_controller.rb
include PageAttributes

# in config/initilizers/requires.rb
require 'page_attributes'

# in lib/page_attributes.rb
module PageAttributes
  def self.included(base)
    base.helper_method :page_attr
    base.class_attribute :page_attributes
    base.page_attributes = {}
    base.class_eval do
      def self.page_attr(key, value)
        self.page_attributes[key] = value
      end
    end
  end

  protected

  def page_attr(key, value=nil)
    @page_attributes ||= {}
    if value.nil?
      @page_attributes[key] || self.class.page_attributes[key]
    else
      @page_attributes[key] = value
    end
  end
end
  • June 20, 2011
  • Article
  • Rails, Ruby

Killing Processes in Ruby

Killing a process in Ruby is pretty straight forward. You just need to know the process ID for the process, and which signal you want to send:

Process.kill('INT', pid) # where pid is the process id of the process to be killed

A list of signals supported by your system is available from Signal.list, but knowing which one to use is easier after looking at the definitions. I typically use SIGINT (you can just use INT in Ruby) to kill processes.

Something that I've always found messy (and error prone) is cleaning up a bunch of dependent processes that were spawned as part of an automated script. A common case for this is running integration tests where you have at least one process that is the server, a process that is running tests against that server, and potentially other helper processes for web browser automation, etc.

This is a hard problem because it isn't easy to know the process IDs for all of the child processes of a script. It may spawn additional processes, and commonly the process IDs returned to Ruby when spawning processes end up being incorrect due to redirection or process replacement.

UNIX!

It turns out that there is a simple UNIX solution to this problem: process groups. By sending a signal to a process group instead of a single process ID, we are able to send it to all of a script's child processes without knowing their individual process IDs.

To do this, use Process.getpgrp to get the process group of the current process, and pass it to Process.kill as a negative number, which indicates the argument is a process group and not a process ID. And since the current process is going to receive the signal as well, use trap to catch it and provide a clean exit. In a script used for testing, use a non-zero exit status if any tests failed.

trap("INT") do
  exit
end
Process.kill('INT', -Process.getpgrp)

It appears that it is also possible to use 0 as the second argument to Process.kill, and have the same behavior. For the sake of clarity, though, I prefer the former option.

Everything in this article should work in POSIX environments, but I have no idea if it will work on Windows.

  • June 02, 2011
  • Article
  • POSIX, Ruby

SASS and Sinatra on Heroku

Hosting SASS (or any dynamically generated asset) on Heroku can be a challenge, as most of the libraries that generate browser-ready versions of these assets expect to have write access to the filesystem.

There are a variety of libraries that provide asset compiling and caching, and some of these offer ways to do this in a Heroku-friendly way (usually by leveraging Varnish. But sometimes you don't want to install and learn how to use a new asset packaging library just to get a 100 line Sinatra app up and running IN THE CLOUD.

Heroku provides official instructions for using SASS on their platform, but like a lot of their documentation, it is Rails-specific. So here are the official instructions, converted for use with Sinatra (or I imagine, most Rack apps):

require 'sinatra'
require 'sass/plugin/rack'

use Sass::Plugin::Rack

configure :production do
  use Rack::Static,
      urls: ['/stylesheets'],
      root: File.expand_path('../tmp', __FILE__)

  Sass::Plugin.options.merge!(template_location: 'public/stylesheets/sass',
                              css_location: 'tmp/stylesheets')
end

get '/' do
  # your app here
end
  • This assumes that the Sinatra app is in the root directory of the project, and that all SASS files live at public/stylesheets/sass.
  • Don't forget to add public/stylesheets/*.css to .gitignore to help prevent checking generated CSS files into git during development.
  • No files will be served from public/stylesheets in production, so make sure all stylesheets are in the sass directory. For CSS resets and the like, change their extensions to scss and drop them into the sass directory.
  • May 18, 2011
  • Article
  • Heroku, SASS, Sinatra

Tweaking Ruby Enterprise Edition's garbage collection settings to speed up tests

I've been looking at ways to get the test suite for a project I'm working on running faster, and I came across slides from a presentation that present several ways to speed up tests. In particular, there are some environment variables that you can use to control the behavior of REE's garbage collector. I've found that using the values suggested in the slides decreases my test run times by 20-30%:

export RUBY_HEAP_MIN_SLOTS=1000000
export RUBY_HEAP_SLOTS_INCREMENT=1000000
export RUBY_HEAP_SLOTS_GROWTH_FACTOR=1
export RUBY_HEAP_FREE_MIN=500000
export RUBY_GC_MALLOC_LIMIT=1000000000

I saved this script to my path, and when I want run Ruby with these settings, I prepend the command I'm running with 'rmem'. Or, as suggested by the slides, you can add the settings to your profile. Be careful, as they cause Ruby processes to use significantly more memory.

  • August 21, 2010
  • Article
  • Code, Rails, Rspec, Ruby

A simple content_for in PHP

I'd been meaning to check out PHP 5.3's closures. When someone asked me a question about Fitzgerald today, I had to look at the source to find the answer. I then spent five minutes sketching the following, which is a very minimal implementation of Rails' content_for view helper.

<?php

$contents = array();

function content_for($name, $method) {
  global $contents;
  $contents[$name] = $method;
}

function yield($name) {
  global $contents;
  if (array_key_exists($name, $contents)) {
      return $contents[$name]();
  }
}

$variable = "something great";

?>

<?php content_for('header', function() use($variable) { ?>
  <h1>'<?php echo $variable ?>' should be in the header</h1>
<?php })?>

<?php content_for('footer', function() { ?>
  <h1>should be in the footer</h1>
<?php })?>

<div class="header">
  <?php yield('header')?>
</div>

<p>Here is the content for a page.</p>

<div class="footer">
  <?php yield('footer')?>
</div>

The rendered result looks like this:

<div class="header"> 
    <h1>'something great' should be in the header</h1> 
</div> 
 
<p>Here is the content for a page.</p> 
 
<div class="footer"> 
    <h1>should be in the footer</h1> 
</div> 

Having to declare inherited variables with use is a little annoying, but otherwise, I'm impressed with this addition to PHP.

  • June 04, 2010
  • Article
  • Code, PHP

ocrunner provides prettier OCUnit output

The testing landscape in the Objective-C world is much more sparsely populated than it is in the Ruby world, with the best two options being OCUnit and Google's customized version of OCUnit which ships as a part of their Google Toolbox for Mac. If you haven't tested with OCUnit before, Apple has a nice article to get you started.

Not in Kansas Anymore

Coming from the Ruby world, I was accustomed to tests running constantly in a console as wrote code. When I started doing iPhone development, it took me a while to setup a confortable working environment. Figuring out the best way to run tests was the biggest component of this period of acclimation.

After working on my first iPhone app for a few weeks, I found running tests via the Xcode GUI to be occasionally useful for debugging, but in general I felt having to switch between targets in Xcode in order to build the tests provided to much resistance. I started using the xcodebuild command line programs to run tests, which was great, except the output is hopelessly verbose, which makes it quite difficult to see if a test failed.

Ruby to the Rescue

OCRunner is a little Ruby wrapper for xcodebuild. It will run your tests with xcodebuild and display the results in a concise and colorful manner:

Screenshot of OCRunner in action

To try it out:

gem install ocrunner
cd /your/project/directory
ocrunner --auto

The --auto options will rerun tests whenever an Objective-C or header file is modified. ocrunner --help will tell you about all the available options. The code is on GitHub.

In Closing

I'm now thinking that the best way to test Objective-C code probably involves MacRuby, but if you're using OCUnit, OCRunner will give you a more streamlined workflow for TDD.

  • May 25, 2010
  • Article
  • Code, OCUnit, Objective-C, Ruby

Carmen now supports states for nine countries

Thanks to Andriy Tyurnikov and Tobias Schmidt for recently adding support for the Ukraine and Germany, respectively. And to the others that have fixed bugs or brought issues to my attention.

Carmen is a collection of country and state names and abbreviations, along with replacements for the state_select and country_select plugins that leverage this data.

  • December 16, 2009
  • Article
  • Code, Rails, Ruby

Apply jQuery event handlers once with $.fn.safe()

Today I was in this situation:

  • I had a page that could mutate in a lot of different ways (AJAX, user interaction, etc)
  • I needed a way to execute a block of code against only the new DOM elements on the page (to avoid duplicating the event handlers on the already existing elements)
  • I didn't want to use livequery (delegation would have created its own set of problems)

This is what I came up with:

$('ul.choices a').safe('choices').click(function(event) {
  // code to only execute once for any DOM element
};

$.fn.safe works similarly to jQuery's filter. It returns a jQuery object containing only DOM elements that haven't already been returned for the specified key ('choices' in the above example). So it's safe to execute the code above multiple times without repercussions. Obviously, looping through a large set of elements can be costly, but for smaller sets this simple solution works great.

Here's what's going on behind the scenes:

var $$ = function(param) {
    var node = jQuery(param)[0];
    var id = jQuery.data(node);
    jQuery.cache[id] = jQuery.cache[id] || {};
    jQuery.cache[id].node = node;
    return jQuery.cache[id];
};

$.fn.safe = function(name) {
  return this.filter(function(i, element) {
    $$(this).unsafe = $$(this).unsafe || [];
    if ($.inArray(name, $$(this).unsafe) == -1) {
      $$(this).unsafe.push(name);
      return true;
    } else {
      return false;
    }
  });
};

I'm using the $$ helper I first saw on Yahuda Katz's blog- you should too. It makes working with jQuery's data cache much easier.

See Also

LowPro for Prototype will only apply a given behavior to a DOM element once, but I haven't used it since moving to jQuery for all new projects.

  • November 20, 2009
  • Article
  • Code, JavaScript, jQuery

Convert HTML to Haml within Textmate

I have been integrating a lot of well built HTML templates into Rails applications this week. I've found Haml to be the best templating language, and I like to convert preexisting templates to use it as I add them to a project.

The Haml gem installs a command line executable that performs this conversion, html2haml. The program takes whatever is passed as standard input, performs the conversion, and writes the result to standard out. For a while I was using command this in combination with the pbcopy/pbpaste commands (I work on a Mac) to apply this to the content of the clipboard:

pbpaste | html2haml | pbcopy

This worked, but the extra copying and pasting was annoying. So I made a TextMate command to eliminate the tedium:

Screenshot of the TextMate bundle editor

The actual command is this (it's a bit hard to see above):

echo $TM_SELECTED_TEXT | html2haml

You could add a key binding as well, but so far I haven't bothered to.

  • November 13, 2009
  • Article
  • Code, Mac, Rails, Ruby

Add an ActiveRecord scope for easier eager loading

In the optimization phase of a project, one of the first things I do is look for pages that could benefit from the use of ActiveRecord's eager loading. Since named_scopes were introduced in Rails 2.1, most of my model loading has involved a chain of scopes, and it is always frustrating to have to change

@blogs = Blog.published.active

to

@blogs = Blog.published.active.scoped(:include => [:slugs, :topic => :slugs])

It's a small difference, but one I've never really liked. It seems like an obvious choice would be to add a named_scope to all subclasses of ActiveRecord::Base and have that handle the :include parameter. I finally wrote the 11 lines of code required to do this today:

module ActiveRecord
  module EagerLoadScope
    def self.included(base)
      base.named_scope :eager_load, lambda { |*inclusion|
        {:include => inclusion}
      }
    end
  end
end

ActiveRecord::Base.class_eval { include ActiveRecord::EagerLoadScope }

And now that line looks like this:

@blogs = Blog.published.active.eager_load(:slugs, :topic => :slugs)

Again, it's a small improvement, but one I consider worthwhile.

  • October 28, 2009
  • Article
  • Code, Rails, Ruby

Hiding parts of a view while in development

Most of my recent projects have involved working with a front end developer, who would provide HTML/CSS templates with dummy content to be integrated into a Rails backend. During the process of wiring up the views, I often wish to hide a section of a template or partial until the models and controllers are setup to support them.

I've started using this little view helper to hide code in a view, while providing a console message to remind me to go back and address the issue when the time is right:

def hide(&block)
  if Rails.env == 'development'
    match, file, line = caller.first.match(/([^:]+):(\d+).+/).to_a
    Rails.logger.info "** Hiding content on line #{line} of #{file}"
  end
end

It's simple to use, especially in HAML:

- hide do
  = some_view_code_that_will_not_execute

The helper will print something like this to your console:

** Hiding content on line 14 of /Users/jimb/Projects/demo/app/views/objects/show.html.haml
  • September 11, 2009
  • Article
  • CSS, Rails, Ruby