Some of my co-workers like to use Notational Velocity to store sensitive information. Though a fine application, I’m partial to my existing tools and wanted something more general-purpose and flexible.

To that end, I set up a simple encrypted disk image and configured it to mount with a password prompt when I log on.

  1. Open Disk Utility and select New Image from the toolbar.

  2. Configure the Disk Image. I don’t have any big files to encrypt so I opted for the smallest (10MB) image size. Select an option from the Encryption drop-down.

  3. Set up a password for your disk image.

  4. In order to require password entry to open the disk image you’ll need to set up the permissions in Keychain Access.

  5. Under Access Control for the disk image Keychain entry, remove diskimages-helper from the list of programs always allowed to access the entry.

  6. In the Accounts Preference Pane, configure the disk image to mount on login.

Now simply select the mounted volume as the destination for files you want encrypted and sleep easy.

Nick Kallen’s named_scope allows you to create readable, powerful class-specific finder scopes.

One thing that might bite new users is how it operates in the Class context. Specifically, Named Scopes created in a parent class, even those using the lambda syntax, are scoped to the parent class.

For example, we might have a generic SQL operation that finds records whose date field falls within a certain range in a parent class, and simply allow any child classes to provide the range.

class HighScore
  named_scope :for_date, lambda { |time| { :conditions => { :date => time_range_for(time) } } }
end
 
class DailyHighScore < HighScore
  def self.time_range_for time
    (time.beginning_of_day)..(time.beginning_of_day + 1.day)
  end
end
 
class WeeklyHighScore < HighScore
  def self.time_range_for time
    (time.beginning_of_week)..(time.beginning_of_week + 1.week)
  end
end

Wouldn’t it be lovely if we could just rely on the subclass to complete the conditions? Unfortunately, since time_range_for is not defined in the HighScore class, this code will not not work.

The solution is to create individual Named Scopes on the child classes. However, instead of declaring unique Named Scopes, common behavior is isolated in the parent class by providing a Named Scope builder.

class HighScore
  def self.has_named_scope_for_time_range
    named_scope :for_date, lambda { |time| { :conditions => { :date => time_range_for(time) } } }
  end
end
 
class DailyHighScore < HighScore
  def self.time_range_for time
    (time.beginning_of_day)..(time.beginning_of_day + 1.day)
  end
 
  has_named_scope_for_time_range
end
 
class WeeklyHighScore < HighScore
  def self.time_range_for time
    (time.beginning_of_week)..(time.beginning_of_week + 1.week)
  end
 
  has_named_scope_for_time_range
end

Now all child classes using has_named_scope_for_time_range get a for_date Scope that works just the way they want. An additional advantage of this approach is that the parent class no longer has the extraneous for_date Named Scope.

UpdateRick Olson pointed out the overhead in accessing instance_values, and suggested instead using instance_variable_get.

Done!

Ruby’s attr_accessor is incredibly handy for wiring up your class’s banal getters and setters. If you’re wiring up some simple booleans this way though, wouldn’t you like to get the beauty of Ruby’s method punctuation?

I mean come on, we’re asking a question here.

The old way:

class Doyen
  attr_accessor :recondite
 
  def recondite?
    self.recondite
  end
 
end

Blah… Let’s tidy that up.

class Doyen
  bool_attr_accessor :recondite
end

Now our Doyen no longer has doyen.recondite, but simply doyen.recondite? and no visual clutter.

The implementation is simple:

class Module
  def bool_attr_accessor *args
    args.each do |arg|
      self.instance_eval do
 
        define_method("#{arg}=") do |value|
          instance_variable_set("@#{arg}", !!value)
        end
 
        define_method("#{arg}?") do
          instance_variable_get("@#{arg}")
        end
 
      end
    end
 
  end
end

Originally I used an attr_writer *args to simplify the setters, but I decided that since this function would always return a boolean, it would be better to do the conversion on the setter and let the getter simply return the pre-converted value.

Delete and return the first instance of a given object from an array.

class Array
  def delete_first(to_delete)
    self.each_with_index do |item, index|
      return delete_at(index) if item == to_delete
    end
    return nil
  end
end

The subject of cropping and resizing images comes up fairly often in the Rails community, with a number of tools out there to automate these manipulations.

When manipulating images, I like to use MiniMagick to keep the memory footprint of the application server itself small. Since MiniMagick just wraps the command-line convert and mogrify tools, special-casing your image resizer is as simple as modifying the flags passed to the underlying system command.

There are a number of resizing algorithms in use. Various approaches include maintaining the original image’s aspect ratio, cropping over-sized images, and padding resized images.

In order to achieve good fit an image may need to be both scaled and cropped. A well-fit image will maintain as much of the original image as possible while still conforming to the final target dimensions and aspect.

To illustrate the desired results, we’ll be manipulating the speakersitter image.
Original 300 × 586

Check out some examples of the various approaches to fixed-size output.

  1. With over-sized images, by far the simplest approach is the naive crop. Unfortunately, this fails us when the image is too small, and looks pretty terrible in most cases anyway.

    Cropped to 150 × 90

  2. Next up is the naive scale. This approach is nice in that it delivers consistent results no matter what the image’s original dimensions were. On the down side, this consistent behavior typically sucks.

    Scaled to 150 × 90

  3. Padding can be a nice way of getting generally good-looking output. A padding algorithm will scale an image maintaining its aspect ratio so that none of its dimensions is greater than the corresponding output dimension, and then will composite that scaled image onto the center of a blank image of the target dimensions. In this example, the checkerboard pattern represents the background image onto which the original image is composited. In real world usage, this image would be pure white or transparent.

    Scaled to 46 × 90, Padded to 150 × 90

  4. The good fit approach is similar to the padding approach, in that the source image is immediately scaled with a fixed aspect ratio. In the padding approach the image’s dimensions such that none is greater than its corresponding output dimension, both are constrained such that none is less than the output dimension. This guarantees that part of the source image will be cropped unless it is exactly the same aspect as the output dimensions.

    The scaled source image can be cropped according to one of nine different gravities. If your application deals primarily with portraits and face images, North gravity is typically the best.

    Perfect Fit 150 × 90 North Gravity

    For most other applications, including avatar and thumbnail generation, Center Gravity can be preferable.

    Perfect Fit 150 × 90 Center Gravity

Sadly, MiniMagick doesn’t support doing this all from the command line without a little pre-computation. We must sadly scale and then crop according to offsets we compute ourselves. Fortunately, I have already taken care of this for you!

I monkey-patched these changes directly into attachment_fu’s mini_magick_processor, but the calculations and generated commandline flags should serve you wherever you use MiniMagick.

module Technoweenie::AttachmentFu::Processors::MiniMagickProcessor
  GRAVITY_TYPES = [ :north_west, :north, :north_east, :east, :south_east, :south, :south_west, :west, :center ]
 
  def resize_and_crop_image(img, size, options = {})
    gravity = options[:gravity] || :center
    g = Geometry.from_s(size.to_s)
    img.opaque
 
    img_width, img_height = *(img[:dimensions].map { |d| d.to_f } )
    resize_string = ''
 
    # Resize image to minimize difference between actual dimension and target dimension
    if img_width / g.width < img_height / g.height
      resize_string = "#{g.width.to_i}x"
      resultant_width = g.width
      resultant_height = (img_height * (g.width / img_width))
    else
      resize_string = "x#{g.height.to_i}"
      resultant_width = (img_width * (g.height / img_height))
      resultant_height = g.height
    end
 
    width_offset, height_offset = crop_offsets_by_gravity(
      gravity,
      [ resultant_width, resultant_height ],
      [ g.width, g.height ] )
 
    img.combine_options do |i|
      i.args << '+matte'
      i.resize(resize_string)
      i.gravity('NorthWest')
      i.crop "#{g.width.to_i}x#{g.height.to_i}+#{width_offset}+#{height_offset}!"
    end
  end
 
  def crop_offsets_by_gravity gravity, original_dimensions, cropped_dimensions
    raise(ArgumentError, "Gravity must be one of #{GRAVITY_TYPES.inspect}") unless GRAVITY_TYPES.include?(gravity.to_sym)
    raise(ArgumentError, "Original dimensions must be supplied as a [ width, height ] array") unless original_dimensions.kind_of?(Enumerable) && original_dimensions.size == 2
    raise(ArgumentError, "Cropped dimensions must be supplied as a [ width, height ] array") unless cropped_dimensions.kind_of?(Enumerable) && cropped_dimensions.size == 2
    original_width, original_height = original_dimensions
    cropped_width, cropped_height = cropped_dimensions
    # No vertical offset for northern gravity
    vertical_offset = case gravity
      when :north_west, :north, :north_east then 0
      when :center, :east, :west then [ ((original_height - cropped_height) / 2.0).to_i, 0 ].max
      when :south_west, :south, :south_east then (original_height - cropped_height).to_i
    end
    horizontal_offset = case gravity
      when :north_west, :west, :south_west then 0
      when :center, :north, :south then [ ((original_width - cropped_width) / 2.0).to_i, 0 ].max
      when :north_east, :east, :south_east then (original_width - cropped_width).to_i
    end
    return [ horizontal_offset, vertical_offset ]
  end
end

Nick Kallen noted that the behavior of has_many_with_args can be accomplished using has_finder.

Too true!

Imagine a system in which Users send Whispers to one another. We would like to see Whispers scoped so that:

  • A User viewing their own Whispers should see all Whispers they have received

  • A User viewing another User’s Whispers should see only Whispers they themselves sent

With the clean chainable syntax provided by has_finder, this is straight-forward. We return associations directly (notice, no find calls) and isolate declaration of the scoping the behavior to the class affected by it.

class Whisper < ActiveRecord::Base
  has_finder :from, lambda { |sender| { :conditions => [ 'sender_id = ?', sender.id ] } }
end
 
class User < ActiveRecord::Base
  has_many :received_whispers, :foreign_key => 'recipient_id'
 
  def whispers_viewable_by user
    return whispers if self == user
    whispers.from(user)
  end
end

How expressive is that? Business rules are cleanly captured in the models and our associations stay so limber!

Thanks to Pat Maddox for turning me on to has_finder, and Nick Kallen for writing it.

class Fixnum
  def clip_to range
    r = range.first < range.last ? range : (range.last)..(range.first)
    return [ [ r.min, self ].max, r.max ].min
  end
end

Updatehas_finder accomplishes everything has_many_with_args does in an elegant and extensible fashion. As it’s slated for inclusion in Rails 2.1, I thought I’d describe how to accomplish the scoped whispers example presented in this post using has_finder.

Read the solution here.

Rails Associations are powerful tools, but sometimes they can be a bit over-reaching.

Let’s examine a hypothetical has_many association and how it would traditionally be managed.

class User
  has_many :sent_whispers, :class_name => 'Whisper', :foreign_key => 'sender_id'
  has_many :received_whispers, :class_name => 'Whisper', :foreign_key => 'recipient_id'
end
 
class Whisper
  belongs_to :sender, :class_name => 'User'
  belongs_to :recipient, :class_name => 'User'
end

Now, if you’d like to scope down received whispers to just those sent by a specific user, you’d ordinarily probably use something along these lines.

def whispers_from sender
  with_scope( :find => { :conditions => [ 'sender_id = ?', sender.id ] } ) do
    received_whispers.find(:all)
  end
end

Unfortunately, this is pretty limiting. For example, any association extensions defined on :received_whispers are unavailable when accessing whispers_from. We also lose out on all the association calculation methods and can no longer use << to insert new elements directly into the association.

We could get the type of focused behavior we wanted by adding a conditions clause to the association.

has_many :whispers_from,
  :class_name => 'Whisper',
  :foreign_key => 'recipient_id',
  :conditions => [ 'sender_id = ?', sender.id ]

This won’t work either! sender isn’t defined in the class scope as the association is being created, so the conditions clause is at a loss. But all is not lost! A poorly-documented feature of the association methods is the lazy evaluation of conditions.

has_many :whispers_from,
  :class_name => 'Whisper',
  :foreign_key => 'recipient_id',
  :conditions => 'sender_id = #{sender.id}'

Notice that the conditions clause is singly-quoted. When the conditions clause is evaulated, the sender method will be called on the User. Better, but still not much use to us, as the User doesn’t have a sender method. Well, what if sender were an ordinary attr_reader on the User? If we could get @sender set prior to the evaluation of the association conditions, we’d be set!

Okay, we can do this!
I whipped up has_many_with_args (suggestions for a better name?) which allows you to create an association with teeth!

class User
  has_many_with_args :whispers_from, :sender,
    :class_name => 'Whisper',
    :foreign_key => 'recipient_id',
    :conditions => 'sender_id = #{sender.id}'
end

And that’s it! Now you can use all the regular has_many association methods, calculation methods, and your own association extensions. Boss!

alice = User.find(1)
bob = User.find(2)
alice.whispers_from(bob).count # SELECT COUNT(*) FROM users WHERE recipient_id=1 AND sender_id=2

It’s all packaged up as a plugin for you. Just install using piston:

piston import http://hasmanywithargs.googlecode.com/svn/trunk/ vendor/plugins/has_many_with_args

For the brave and curious, have a look at the source to see how the attr_readers are set up and initialized when the association is accessed.

Displaying ads on a site can be a little tricky. Many ad networks simply provide you with a snippet of javascript that must be embedded directly into a page where an ad is to be displayed. These often use document.write to generate more script tags which in turn may generate the actual ad content.

Regardless, sourcing external javascript files in this way can lead to choppy page loads as progressive rendering halts, waiting for this external content to be downloaded and evaluated. Yahoo!’s YSlow grades a page down for this, specifically for violation of Rule 6: Put Scripts at the Bottom.

With scripts, progressive rendering is blocked for all content below the script. Moving scripts as low in the page as possible means there’s more content above the script that is rendered sooner.

In some situations it’s not easy to move scripts to the bottom. If, for example, the script uses document.write to insert part of the page’s content, it can’t be moved lower in the page.

This was causing us serious pains as our ad-provider sometimes responded slowly, and sometimes responded not-at-all. In the spirit of graceful degradation, I crafted this solution for Rails.

Instead of generating the ad markup where the ad was supposed to appear, I first generate a placeholder DOM node, and using a content_for block, tuck the actual markup away. In the application’s layout template (application.rhtml), the last 3 lines are like so.

<%= yield :support_footer %>
  </body>
</html>

Generating the support_footer is straight-forward:

module DeferredContentInsertionHelper
 
  def deferred_insertion to_insert, options = {}
    content = case to_insert
    when String
      to_insert
    when Hash
      render_to_string(to_insert)
    end
 
    container = "di_#{content.hash}"
    defer_container = "defer_#{container}"
 
    content_for :support_footer do
      [ content_tag('div', content, :id => defer_container),
        javascript_tag("$('#{container}').parentNode.replaceChild($('#{defer_container}'), $('#{container}'));")
      ].join
    end
 
    # Insert a placeholder that the real content will replace once its loaded
    content_tag('span', '', :id => container)
  end
 
end

Now, when I want to generate an ad in the layout, instead of issuing:

<%= render :partial => 'ads/banner' %>

I can issue a deferred insertion and get a much more responsive page:

<%= deferred_insertion :partial => 'ads/banner' %>

Note how content generated in the support_footer is initially hidden, and is shown after it has been moved into place.

We were experiencing issues with ads being initially hidden and then moved into place. By leaving them visible, they render properly. The page layout changing as elements are added and removed can be overcome with appropriate css sizing.

I recently posted on determining whether two arrays contain the same elements irrespective of ordering.

The approach supplied works for some basic Ruby types, but failed for complex types such as arrays of instances of custom classes.

class Foo
  attr_accessor :i
 
  def initialize new_i
    self.i = new_i
  end
 
  def == another_foo
    self.i == another_foo.i
  end
 
end
 
foo1 = Foo.new(1)
foo2 = Foo.new(1)
 
[ foo1 ].same_elements?( [ foo2 ] ) # Expected true, got false

The culprit lay in Ruby’s Hash equality comparison method. In the original implementation of same_elements? a hash was built for each array. This hash’s keys were the unique elements of the array and its values were the counts of the number of occurrences of that key within the parent array.

Unfortunately, this led to the final comparison:

foo1 == foo2 # true
{ foo1 => 1 } == { foo2 => 1 } # false

To overcome this, we had to compare keys and values individually instead of with the built-in hash comparison.

class Array
  # Ask an Array whether it shares the same elements with another Array, irrespective of order
  # Options
  # :allow_duplicates
  #   If set to true arrays with the same elements, but differing numbers of those elements
  #   are treated as the same.
  #   Examples
  #     [ :a ].same_elements?( [ :a, :a ] ) => false
  #     [ :a ].same_elements?( [ :a, :a ], :allow_duplicates => true) => true
  def same_elements? another_array, options = {}
    raise ArgumentError, "#{another_array.inspect} was expected to be an Array" unless another_array.kind_of?(Array)
    s = self
    a = another_array
    if options[:allow_duplicates]
      s = s.uniq
      a = a.uniq
    end
 
    return element_counts(s) == element_counts(a)
  end
 
  private
    def element_counts obj
      result = []
      obj.uniq.map { |e|
        [ e, obj.inject(0) { |i, e2| i + (e == e2 ? 1 : 0 ) } ]
      }.each { |p| result << p.first; result << p.last }
 
      HashEqualityChecker.new(Hash[ *result ])
    end
end
 
class HashEqualityChecker < Hash
  def initialize new_hash
    self.replace new_hash
  end
 
  def == another_hash_equality_checker
    return false unless another_hash_equality_checker.size == size
 
    another_hash_equality_checker.inject(true) do |still_same, kv_pair|
      ak, av = kv_pair
 
      match = select do |k, v|
        k == ak && v == av
      end
 
      found_match = !match.empty?
      still_same && found_match
    end
  end
 
end

Now instead of using a default Hash for the element counts, we use the new HashEqualityChecker, which performs a == comparison on each pair of elements in the underlying Hash.