Close and Go BackBack to Viget

Tips and Tricks

Unpublished Keyboard Shortcuts on Mac OS X

Tony Pitale
Tony Pitale, Web Developer, September 04, 2008 0

This is just the quickest of tips for everyone using Mac OS X.

Keyboard shortcuts are one of my favorite features on Mac OS X and something that I think few operating systems get right. Not only are there a staggering number of predefined shortcuts (some aren’t even advertised, but we’ll get to that in a moment) but also, for any menu item, a custom shortcut can be defined within System Preferences -> Keyboard & Mouse -> Keyboard Shortcuts (the right-most tab).

I find this to be immensely useful, especially in overriding the shortcut behavior of a variety of third party applications that have the same function. For example, Firefox, Textmate, and almost every other application that has tabbed windows provides a shortcut on the keyboard to switch between tabs (left and right). For Apple’s application, the shortcut is likely to be Command-Option-Arrow Key. By default many other applications use Command-Option-Brace (curly brace, or square bracket?). A quick pair of keyboard shortcuts overrides these behaviors to be standard to your shortcut preference.

If you can’t recall a keyboard shortcut, users of the latest version 10.5 (Leopard), can make instant use of the help menu which, like Spotlight for files, will search for text amongst the seemingly endless sea of menu options. This feature has saved me time, and again, in applications such as any of the Adobe suite of products.

Lastly, I’d like to touch on three very useful but, unadvertised, keyboard shortcuts.
Use Command-Option-Eject Key to set your computer into a blissful sleep state,
Command-Control-Eject Key to reset your Mac immediately, or
combine those two and get Command-Option-Control-Eject Key to shut it down until you need it again.

Overall, the mouse is unbelievably slow for pre-defined activities, in comparison to a keyboard shortcut. Thanks to Apple’s latest OS X, you don’t even have to remember them all.

Protip: Use Your Factories in Development

Clinton R. Nixon
Clinton R. Nixon, Senior Developer, August 17, 2008 1

I’ve been training a new Rails developer recently, and I’ve found it rewarding. His questions are great: without already-built habits, he thinks of ways to do things I never would.

Last week, he said, “I need to test this view with some real data to make sure it looks OK. We have all these factory methods to use in our unit tests. Can we use those in development?” I almost said no, but then I realized it was a pretty great idea.

We’re using FixtureReplacement on this project, but this technique will work with any factories. We opened script/console and typed the following:

require 'fixture_replacement'
include FixtureReplacement
require RAILS_ROOT + '/db/example_data'

With that, I could use, for example, our create_completed_order method to make a purchased cart with multiple items in it so we could see how the admin interface was looking. It’s no replacement for good testing, but for quick view checks, it’s a pretty cool trick.

Named Scope Caching

Brian Landau
Brian Landau, Web Developer, August 07, 2008 3

When working on high-traffic Rails sites, it often becomes necessary to find ways to improve performance with caching. One place we’ve found this is most convenient and easy-to-do is by caching an ActiveRecord result set for models that change rarely or not at all. An easy example of this is a Category model.

Often times, you have a categorization hierarchy that will never or rarely change over the life of an application. Ideally you would fetch the results once from the database and never have to again. So how do we go about caching this? First let’s look at our model and create a named_scope for it:

class Category < ActiveRecord::Base
  acts_as_tree
  named_scope :find_top_level, :conditions => 'categories.parent_id IS NULL',
                              :order      => 'categories.name'
end

Next, we need to create create a method that fetches the results for our new scope and caches it in a class variable. It should also only do caching if in production environment (alternatively or additionally, we could use the ActionController.perform_caching config value), as this can cause problems in tests.

def self.top_level
  unless ('production' == RAILS_ENV) && ActionController.perform_caching
    @@top_level_cache = self.find_top_level
  else
    @@top_level_cache ||= self.find_top_level
  end
end

Finally, we need to create a method to invalidate our cache when records are saved or deleted. Since we know this isn’t happening often (if at all), this should rarely be performed but is a good safeguard so we know our cache is current.

after_save :reset_cached_finder
after_destroy :reset_cached_finder

def reset_cached_finder
  @@top_level_cache = nil
end

This is something that we could easily see doing in a number of models for a number of finders. Since this involves a lot of similar code, it would be great if we could create some meta code that would allow us to define these caches with a simple one liner.

Continue reading "Named Scope Caching"

A Confusing Rubyism

Ben Scofield
Ben Scofield, Development Director, July 12, 2008 5

The following code has the potential to be terribly confusing:

if x = some_method
  monkify
else
  rhinofy
end

In Ruby, the return value of an assignment statement is the value assigned (run a = 1 in irb and you'll see it returns 1), so this code can be understood as:

  1. Evaluate some_method and assign the value to x
  2. If the new value of x evaluates to true, run monkify
  3. If the new value of x evaluates to false, run rhinofy

Unfortunately, however, most developers are much more accustomed to seeing the equality operator == in conditionals, which means that often we'll misinterpret that code as:

  1. Evaluate some_method and compare the result to x
  2. If they are the same, run monkify
  3. If they are different, run rhinofy

In the interest of clarity, then, it's probably better to avoid using an assignment statement in a conditional. Of course, other concerns may override the need for clarity - but it's something to keep in mind.

Inheritance is Unlikely

Justin Marney
Justin Marney, Web Developer, June 05, 2008 8 What do you do when you identify common sets of shared behavior across several classes?

A common solution is to move the shared code into a base class and inherit.
# Filled with api interaction behavior
class Base
  def api_specific_behavior
    puts "connect to api"
  end
end

class User < Base
  def user_specific_behavior
    puts "I am a user"
  end
end
The problem with inheritance in this situation lies primarily in a subtle violation of the Liskov Substitution Principal which essentially states that inheritance should implement an "is-a" relationship. If we have a class called User that inherits from Base, are we trying to model the part of our domain where a User is a Base? This doesn't make sense given that we never actually have any Bases (i.e. instances of Base).

Continue reading "Inheritance is Unlikely"

A Development Community for Viget Labs and Beyond

Every team member here at Viget Labs strives to be an innovator. We members of the development team are no different - that's why we're constantly engaging in community discussions and exploring the unknown that is the next generation of open-source web applications.

Viget Is Hiring!

Viget has job openings for Ruby Developers, Interns, and Front-End Developers. Learn More »

Upcoming Events

Jack Speaks at WebExpo - September 16
Jack's Talking Agile Sept. 16-19

Recent Comments

I have used several different strategies for achieving this, and have settled on the plugin seed_fu to accomplish this task. Because it uses plain ruby files you have quite a few more options for manipulating your seed data as opposed to using fixtures. I have found that this lets me create seed data that is much less brittle than fixtures can be. You can find seed_fu on...