Mongodb and Macports

Posted by Brian in tips (October 20th, 2009)

I just hit a bump in the road with installing MongoDB via Macports 1.8.1.

sudo port install boost pcre++ spidermonkey
sudo port install mongodb

When I ran

mongodb

I was greeted with

dyld: Library not loaded: /opt/local/lib/libnspr4.dylib
  Referenced from: /opt/local/lib/nspr/libplds4.dylib
  Reason: image not found
Trace/BPT trap

To fix, I simply copied the missing file from its origin to where Mongodb was looking.

 sudo  cp /opt/local/lib/nspr/libnspr4.dylib /opt/local/lib

And all was right.

Autocomplete forms in Rails 2.3.3

Posted by Brian in Howto, Rails (August 28th, 2009)

When Rails 2 was released, the core team dropped some of the Javascript Ajax helpers like in-place editing and autocompleting, and released them as plugins. However, if you’ve ever tried to use them with a modern Rails application, you may have encountered problems with routing and authenticity tokens. In this brief post, I’ll walk you through a trivial example that shows how to make Autocomplete work, using the advantages that Rails 2.3 has, including format responses.

First, let’s get a basic Rails app running with a Projects table with a single field, the project’s name :

 rails autocomplete
 cd autocomplete
 ruby script/generate model project name:string
 ruby script/generate resource projects
 rake db:migrate

Next, let’s load some test data.

 ruby script/runner "
 ['The Ninja project', 'The Top Secret project', 'World Domination'].each do |p|
    Project.create(:name => p)
 end
 "

Grab the autocomplete plugin from Rails’ Github repository and install it as a plugin:

 ruby script/plugin install git://github.com/rails/auto_complete.git

Our basic app is installed, but we need to implement a controller action to display projects.

Open app/controllers/projects_controller.rb and add this method:

  def index
    @projects = Project.all :limit => 10
    respond_to do |format|
      format.html
    end
  end

When the user requests HTML, we’ll show the last 10 projects created. Good enough for now. Let’s implement the layout and the view.

Open app/views/layouts/application.html.erb and build a very simple layout:

<html>
  <head>
    <title>Autocomplete</title>
    <% =javascript_include_tag :defaults %>
  </head>
 
  <body>
    <%= yield %>
  </body>
</html>

This very basic layout loads the default Javascript fiels for Rails and yields the template.

Now open app/views/projects/index.html and add this code:

<div id="search">
  <% form_tag(projects_path(), {:method => :get, :class => "form"}) do %>    
    <%=text_field_tag "query"%>
    <%=submit_tag "Search"%>
  <% end -%>
</div>
<div id="projects">
  <% if @projects.any? %>
    <ul>
      <%=render @projects %>
    </ul>
  <% else %>
    <p>There are no projects to show.</p>
  <% end %>
</div>

Here we have a list of projects, and when we click the submit button, we’ll filter the results. We’re using render here, and when you pass the render helper a collection, it looks for a partial that it can use render each of the elements in the collection.

Create app/views/projects/_project.erb and add this line:

<li><%=h(project.name)%></li>

Now we have to do the filtering in the controller. Since the search box is simply applying a filter to the list of projects, it makes sense for us to use the index action for the request. This means changing the controller’s index action slightly.

def index
  keyword = params[:query]
  if keyword.present?
    keyword = "%#{keyword}%"
    @projects = Project.all :conditions => ["name like ?", keyword], :order => "name asc", :limit => 10
  else
    @projects = Project.all :limit => 10, :order => "created_at desc"
  end
 
  respond_to do |format|
    format.html
    format.js do
      render :inline => "<%= auto_complete_result(@projects, 'name') %>"
    end
  end
end

If the query parameter comes in, then we want to filter. We build up a LIKE query and get the results. If no query parameter is present, we just get the top ten recent projects.

However, this is really messy. Let’s get that search logic out of the controller.

Open app/models/project.rb. Move the search logic into a new method:

def self.find_all_by_keyword(keyword)
  if keyword.present?
    keyword = "%#{keyword}%"
    @projects = Project.all :conditions => ["name like ?", keyword], :order => "name asc", :limit => 10
  else
    @projects = Project.all :limit => 10, :order => "created_at desc"
  end
end

Now change app/controllers/projects_controller.rb to call the method instead of doing the search:

def index
  @projects = Project.find_by_keyword(params[:query])
  respond_to do |format|
    format.html
    format.js do
      render :inline => "<%= auto_complete_result(@projects, 'name') %>"
    end
  end
end

Much better. At this point you have a non-Javascript search for your projects in a very short time.

Let’s add the autocomplete functionality. First, in the view, change the text field to this:

<%= text_field_with_auto_complete :project, :name, 
    { :name => "query" },
    {:method => :get, :url => projects_path(:format => :js) } %>

This sets up the autocomplete field to send its queries to our index action, but specifies that we should use the “js” format, perfectly appropriate for this, as it’s a Javascript-only request, so we should provide our response with Javascript.

Open the controller and modify the controller’s code so it looks like this:

def index
  @projects = Project.find_all_by_keyword(params[:query])
  respond_to do |format|
    format.html
    format.js do
      render :inline => "<%= auto_complete_result(@projects, 'name') %>"
    end
  end
end

The only real change is adding the format.js block of code. Here, we’re using Rails’ inline renderer which renders ERb code. Within that ERB, we’re calling the auto_complete_response helper provided by the autocomplete plugin to render the specially formatted list that the auto compelte text field expects. We’re using inline rendering here, but you could use a view with the .js extension. Since it’s one line, I’ll save the file I/O.

With the responder in place, the autocomplete should start working. This is a pretty simple example, but it does illustrate how to make the autocomplete plugin work in a current Rails application, without working about

Saving without callbacks

Posted by Brian in Howto, Rails, tips (August 19th, 2009)

Occasionally, you need to do something to a model without invoking callbacks. This is especially necessary for instances where you need to modify the record you just saved in an after_save callback. For example, say you want to create a hash based on the record’s ID. You won’t have the ID until after it’s been saved, and if you call self.save in an after_save callback, you’re going to end up in an endless loop.

It turns out that ActiveRecord has two private methods.

create_without_callbacks

and

update_without_callbacks

Remember that private in Ruby is less about keeping you from calling the methods and more about letting you know that you shouldn’t depend on them. With Ruby’s send method, using either of these in your application is easy.

Note that in Ruby 1.9, send doesn’t allow calling private methods, but send! does.

  class Project < ActiveRecord::Base
    after_save :create_hash_from_name_and_id
 
    private
      def create_hash_from_name_and_id
        self.hash = Digest::SHA1.hexdigest("#{self.id}#{Time.now.to_s}#{self.name}")
        self.send :update_without_callbacks
      end
  end

It’s my opinion that these methods should not be private. If I can skip validations with save(false), then I should be able to skip callbacks as well.

There are other patterns you can use to skip callbacks.

  class Project < ActiveRecord::Base
    attr_accessor :skip_callbacks
 
    with_options :unless => :skip_callbacks do |project|
      project.after_save :create_hash_from_name_and_id
      project.after_save :do_more_stuff
    end
 
    private
      def create_hash_from_name_and_id
        self.skip_callbacks = true
        self.hash = Digest::SHA1.hexdigest("#{self.id}#{Time.now.to_s}#{self.name}")
        self.save
      end
  end

So there you go. Go forth and skip callbacks at will.

Using a class method with or without named scopes

Posted by Brian in Howto, Rails (August 17th, 2009)

Here’s a quick one, building off of the previous post on Geokit and Named Scopes.

If you have defined a class method you want to run which operates on a collection of records, you can share it with named scopes.

class Project < ActiveRecord::Base
  validates_presence_of :name
  named_scope :completed, :conditions => {:completed => true}
 
  # returns array of names for projects
  def self.names
    scope = self.scoped({})
    scope.all.collect{|record| record.name}
  end
end

This allows you to do

@project_names = Project.names

Or

@project_names = Project.completed.names

If you return the scope, you can continue chaining. If you don’t return the scope, then you can’t. This comes in handy though for creating a method that returns other objects than the object you’re working with. Here’s a completely contrived example:

Say you want to find the actual hours you’ve spent on all your completed projects:

class Project < ActiveRecord::Base
  named_scope :completed, :conditions => {:completed => true}
 
  def self.tasks
    tasks = []
    self.scoped({}).all.each do |project|
      tasks += (project.tasks)
    end
    tasks
  end
 
  def self.actual_hours
    hours = 0
    tasks.each do |task|
      hours += task.hours
    end
    hours
  end

Grab the value like this:

actual_hours = Project.completed.actual_hours

Now, of course there are other ways to do this, and this particular method will result in a lot of queries. If you were doing this hours counting in a real app, you’d be better off using SQL. This example illustrates the point though. Now go build something more awesome.

Geokit and named_scope

Posted by Brian in Rails, tips (August 11th, 2009)

I discovered that the geokit_rails plugin doesn’t support named_scope. For those unfamiliar, named_scope methods can be chained to narrow down a query while only performing one query. Here’s an example:

class Business < ActiveRecord::Base
  acts_as_mappable 
  named_scope :active, :conditions => {:active => true}
  named_scope :nonprofit, :conditions => {:nonprofit => true}
end
 
@active_businesses = Business.active
@nonprofits = Business.nonprofit
@active_nonprofits = Business.active.nonprofit

Geokit has a really nice syntax for locating businesses within a certain distance.

@businesses = Business.find :all, :origin => "742 Evergreen Terrace, Springfield IL", :within => 10

However, you simply cannot, out of the box, use this with named_scopes. So I cannot do

@businesses = Business.active :origin => "742 Evergreen Terrace, Springfield IL", :within => 10

The way Geokit exposes itself to ActiveRecord is just not compatible.

RailsCasts to the Rescue!

Ryan Bates, Railscasts producer and all-around awesome guy, has posted a solution in which you can build your own dynamic named scopes. We can create our own scope for Geokit, because the Geokit-Rails plugin provides a public method to retrieve the distance SQL fragment.

First, we add a new named scope to our model

   named_scope :map_conditions, lambda { |*args| {:conditions => args} }

Next, we add our own method to handle the scopes.

    def self.by_location(options ={})
      scope = self.scoped({})
      scope = scope.map_conditions "#{distance_sql(options[:origin])} <= #{options[:within]}"
      scope
    end

We use this method to append our own conditions to the anonymous scope. we use the distance_sql method which takes whatever we pass in via our :origin option, and we concatonate the equality. In this case, we want distance less than or equal to our distance.

We can now do exactly what we wanted, although with modified syntax.

@businesses = Business.active.nonprofit.by_location :origin => "742 Evergreen Terrace, Springfield IL", :within => 10

Pretty amazing stuff.

Use Modules, not Inheritence to share behavior in Ruby

Posted by Brian in Howto, Rails, snacks (August 10th, 2009)

When working in Rails, I often find that several classes have the same behavior. A common approach to share code between objects is the tried-and-true method of inheritance, wherein you create a base class and then extend your subclasses from the parent. The child classes get the behaviors from the inheritance. Basically, Object Oriented Programming 101.

Languages like Java and Ruby only let you inherit from one base class, though, so that isn’t gonna work. However, Ruby programmers can use modules to “mix in” behavior.

Mixing it up and Mixing it in

Let’s say we have a Person class.

class Person
  def sleep
    puts "zzz"
  end
end

Now let’s say we need to define a Ninja. We could create a Ninja class and inherit from Person, but that’s not really practical. Ruby developers really don’t like changing the type of a class just because its behavior changes.

Instead, let’s create a Ninja module, and put the behaviors in that module.

module Ninja
  def attack
    "You are dead."
  end
end

We can then use this multiple ways.

Mixing it in to the parent class

In a situation where we would like every Person to be a ninja, we simply use the include directive:

  class Person
    include Ninja
  end

Every instance of the class now has the Ninja behaviors. When we include a module, we are mixing in its methods to the instance. We could also use the extend method, but this mixes the methods in as class methods.

Notice here that we redefined the class definition. This appends to the existing class; it does not overwrite it. This can be a dangerous technique if used improperly because it can be difficult to track down. This is the simplest form of monkeypatching.

There’s an alternative method.

Mixing in to an instance

We can simply alter the instance of an object, applying these behaviors to a specific instance and affecting nothing else.

  @brian = Person.new
  @brian.extend Ninja

Here, we use the extend method because we need to apply these as class methods to the object instance. In Ruby, classes are objects themselves. Our instance needs to be extended.

A more practical exaple – Geolocation

I was working on a project this weekend where I had several models that needed latitude and longitude data pulled in via Google’s web service. I used the GeoKit gem and the Geokit-Rails plugins to make this happen, but I soon noticed I was adding the same code to multiple classes.

acts_as_mappable
after_validation_on_create :geocode_address
 
def geocode_address
  geo=Geokit::Geocoders::MultiGeocoder.geocode (address)
  errors.add(:address, "Could not Geocode address") if !geo.success
  self.lat, self.lng = geo.lat,geo.lng if geo.success
end

It seemed immediately apparent that this should go in a module which could be included into my classes. However, I wanted to also make the two class method calls – the after_validation_on_create callback and the acts_as_mappable macro.

Ruby has a facility for that type of situation

self included

def self.included(base)
#
end

This method is called when a module is included into a class, and it gives you access to the class that’s doing the including. You can use this as a handle to call any class methods. With that, my geolocation module looks like this:

module Geolocation
 
  def self.included(base)
    base.acts_as_mappable
    base.after_validation_on_create :geocode_address
  end
 
  def geocode_address
    geo=Geokit::Geocoders::MultiGeocoder.geocode (address)
    errors.add(:address, "Could not Geocode address") if !geo.success
    self.lat, self.lng = geo.lat,geo.lng if geo.success
  end
 
end

So now any class that needs geolocation just needs to look like this:

class Business
  include Geolocation
end
 
class Nonprofit
  include Geolocation
end

Summary

The above problem could have been solved by using a parent class like MappableOjbect that included the code, but it then makes putting in additional behavior more difficult. Using modules to share code is the preferred way to attach behaviors to objects in your applications.

Accessible Rails Apps – Images and Alternative Text

Posted by Brian in Accessibility, Rails, Usability (July 3rd, 2009)

Many types of users make use of alternative text for images. Users who use screen reading software rely on those tags to describe the images they can’t see. Mobile users with slow connections or ‘pay by the minute’ plans often times turn off images to speed up the process.

Rails does something a little crazy with the image_tag helper… it automatically generates the ALT tag, which is just a horrible horrible idea.

  <%= image_tag "rails.png" %>

generates

  <img src="/images/rails/png" alt="rails" />

This is an absolutely awful idea, and I presume this was done just to shut up the XHTML Transitional validator which will complain if you leave ALT text off of your image elements.

You shouldn’t be adding ALT text to images to satisfy a validator. You should be doing it because it’s The Right Thing To Do.

ALT text is designed to describe the image, to be an alternative to the image. So, when placing the image on the page, take a few seconds to describe what it is.

  <%=image_tag "rails.png", :alt => "The Ruby on Rails Logo"
  <%=image_tag "banner.jpg", :alt => "Awesome Consulting Services - We Make Websites" %>

And for goodness sakes, please don’t prefix your description with “An image of…”. Screenreaders and other devices will make it completely clear to us that the content is supposed to be an image.

Some images convey more information than the ALT may allow, and so we’ll talk about that next.

Accessible Rails Apps – Rails Links, REST and JavaScript Hidden Forms

Posted by Brian in Accessibility, Rails, Usability (July 1st, 2009)

This is the first in a series of articles on developing accessible Rails applications. Accessibility is really important to me as I spend a lot of time working on web sites and applications that need to adhere to Section 508 guidelines. Making web sites accessible is also the Right Thing To Do.

JavaScript and Accessibility

When developing Rails applications, I try really hard to develop the entire application without using JavaScript, since a lot of users who rely on screen reading software can experience problems with AJAX, so these people tend to disable scripting. Using a screen reader is a lot like looking at a web page through a paper towel tube. You can’t see the whole thing at once, and it’s not likely that you are going to see something changing on the screen, and I’ve never come across screen reading software that can really let you know when a section of the page has been replaced. It might tell me that the content has changed, but I have to make it read the whole page back to me again and figure out what happened. Popup advertisements add to the problem, so people tend to just turn of the JavaScript completely.

Accessibility doesn’t just mean the users with disabilities, though. It can also mean those BlackBerry users who have horrible JavaScript support. So, what we’re really talking about is the age-old idea of “progressive enhancement.” Make a low-tech version work first, then spice it up.

Rails and REST

When you develop Rails applications and you’re working to keep your applications adhering to a RESTful design, certain URLS can only be accessed by certain methods. For example, to delete a record, you’re supposed to send a DELETE request to the destroy action of the controller.

Web browsers can only do GET and POST requests. GET requests are only supposed to read data, and POST requests are intended to change data. You POST to create something. Rails uses hidden form fields to emulate the DELETE and PUT methods.

However, Rails allows you to build links that can do other types of requests, like the DELETE request that’s planted in the default scaffolding. Honestly this is one of the single biggest mistakes the Rails core team has ever made. Here’s why:

This code:

  <%=link_to "Delete", project_path(@project), :method => :delete %>

actually produces a hidden HTML form. When you click this link, it actually submits the hidden form. This requires JavaScript to run and also mixes behavior with HTML markup. It’s a truly ugly situation that really should never be used.

A simple solution

The simple solution is to use the button_to helper instead. It generates the same form, but requires no JavaScript to activate it.

  <%=button_to "Delete", project_path(@project), :method => :delete %>

But I don’t want a button!

You don’t have to have one. As Tore Darell points out on his blog, the appropriate way to handle this is to do the opposite of what Rails was doing. You build the form yourself using button_to, but use unobtrusive JavaScript to replace the form with a link, by simply hiding the form, adding an observer to the newly created link which submits the form.

Add this to your application.js file to replace all of your button_to instances.

document.observe('dom:loaded', function(){
  $$('form.button-to').each(function(form){
      var link = new Element('a', {href:'#', 'class':'button-to'});
      link.update(form.down('input[type=submit]').value);
      link.observe('click', function(e){
        e.stop();
        form.submit();
      });
      form.insert({after:link});
      form.hide();
  });
});

Tore got it right, and the Rails team got it wrong. This solution is great because

  • It’s accessible. With JS disabled, the buttons will work and perform the appropriate actions.
  • It’s clean. The JS is unobtrusive. It’s not intermixed with your code, and it doesn’t use DOM Level 0 “onclick” which, in some instances, is considered deprecated or invalid markup.
  • It makes it look like a link without the need to resort to crazy CSS antics.
  • A single fix replaces all occurrances. You’re not generating duplicate JavaScript code all over your views like you would with link_to :method => :delete.

Replacing a single instance

You can replace button_to instances that contain a specific class if you simply wrap the JavaScript code in a simple if... block:

   <%=button_to "Dismiss", user_message_dismissals(:message_url => message.id), :class=>"dismissible" %>
    if(form.descendants().any(function(element){ return element.hasClassName("dismissible")})){
         var link = new Element('a', {href:'#', 'class':'button-to'});
         ...
    }

And I’m sure there are better ways to do that, too.

That’s it for now. I welcome your comments and suggestions on this topic and others.

lazy_developer gets some TLC

Posted by Brian in News, Projects, Rails (June 10th, 2009)

lazy_developer is a Ruby on Rails plugin I use on a lot of my projects to make my life easier as a developer. It’s a collection of Rake tasks that automate some common operations. Some of the more interesting features it provides are

  • the ability to dump a database to YAML format and then pull it back in again
  • a simple way to obliterate models, controllers, views, helpers, and related files easily (in the case of a refactor or a fat-fingered typo
  • a method to compact your migrations into a single migration file
  • and of course, automatically clone your test database whenever you migrate

Today, Kevin Gisi and I gave this plugin some much-needed love and attention after we discovered a few problems. Here’s what’s new:

Data exporting works with Rails versions prior to 2.0

Got an old database you’d like to pull in? This now works in Rails 1.2.3!

Data dumping works much better now!

We noticed some duplicate records sneaking into the output files, and it was due to a mistake I made when I implemented my own version of record pagination. It wasn’t limiting correctly, and Kevin quickly spotted the reason why. It also wasn’t storing records in the YAML file properly either, which I also resolved.

This is tested on Microsoft SQL Server, MySQL, and SQLite3.

Migration compacting works now

This was patched a few days ago and merged in, but I flip-flopped a couple of lines during a merge and it made it into the master branch that way. Kevin decided he’d like support for Subversion for this, so he added it. I’ll add in Git support very soon.

Interested in using this on your projects? Go get lazy_developer right now!

Slides from “Learning To Walk In Shoes” presentation

Posted by Brian in Howto, News (May 14th, 2009)

As promised, here’s the slide deck from my talk “Learning To Walk In Shoes” from April’s Twin Cities Code Camp. After the slides, we went over some demo applications, and you can get those from Github so you can play around with them yourself.

Learning To Walk In Shoes

« Previous PageNext Page »