Displaying articles with tag

Filtering, sorting, paging... oh, my!

Posted by andy, Thu Aug 13 15:00:00 UTC 2009

The Problem

What do you do when your end user needs to filter? In some cases the answer is easy: provide a custom method for the sort criteria. For example, when you know that your end user wants to know "my jobs" as distinct from "all jobs" a custom 'mine' method might work just fine. Don't worry that the custom routes are not RESTful; they are, they are just not the default Rails notion of REST. That's okay; Rails is not necessarily right.

The filtering that I run into is rarely that simple. Right or wrong end users tend to think more options is better. In the context of filtering that means they often want to filter by a combination of ad-hoc attribute values. Clearly a single custom method won't work there because you can't out guess the combination and permutations that a given user might want to use.

Sorting and paging further complicate the issue. Even when you can pick the 'right' values the user may want them back in the 'right' order. Paging is just a small wrinkle on top of that but yet another piece to layer in.

The Context

The most frequent context for the type of filtering/sorting/paging that I'm talking about is when the user is presented with a list of things that needs to be pared down and organized before the user can make any sense out of it. Maybe they're looking at a list of members in a club or a set of subscriptions or a bunch of invoices. Whatever the case, you've given them a set of things to review in the order you thought best but it doesn't make sense to them. Rather than haggle over who's right (you... of course!), you decide to give them a filtering pane and some click-to-sort headers in the grid. Great. The UI is done. But where does it all go? Where do you send the values?

More often than not, this context leads me right back to where it started. You began presenting the user a list that naturally flowed through the #index action of your controller. Why should the filtered or sorted or paged list be any different? It's still just a list, isn't it?

The Solution

In my mind the answer to that question is yes. A filtered list is still just a list so if the original list came from the index action of my controller then the filtered version of it should come that way, too.

The way that I've settled on implementing most of these scenarios lately is through a combination of named scopes, anonymous scopes, and some recommendations from Uncle Bob's Clean Code.

Scopes

Named scopes and anonymous scopes are hardly new territory. Named scopes came into Rails at version 2.1 courtesy of a very popular plugin. The idea behind named scopes, if you're not familiar with them, is that you create a method that 'scopes' a query against your ActiveRecord-based model. This is really handy if you have a scope like 'current' or 'active' that you can use over and over in your application; you just declare it once on the class and use it wherever you need it.

class Order < ActiveRecord::Base
  named_scope :recent, {:limit=>10, :order=>'id DESC'}
  named_scope :since, lambda{|date| {:conditions=>['created_at > ?', date]}}
end

Order.recent
#=> [...up to 10 orders]

Order.since(1.month.ago)
#=> [... all orders created in the last month ...]

Just as a quick refresher in case you're not using named scopes (as you should be!), you create a named scope on a class by calling the named_scope method in the class definition. The first parameter to the method is the name of the 'scope' and the second argument is either a hash of find options or a lambda that returns a hash of find options.

Anonymous scopes are pretty much the same thing. Really, the only difference is that named scopes are not saved against the model. You create them only where you need them and let the Garbage Collector have them when you are done with them.

Order.scoped( {:limit=>10, :order=>'id DESC'} )
#=> same results as Order.recent

What makes named and anonymous scopes so useful for the type of ad hoc filtering and sorting that we're considering is that you can chain them. By chaining named and anonymous scope calls you build up the query conditions. Thus you do not have to worry too much about the what combination of filering, sorting, and paging the user might want, you simply accumulate them. The query is not actually run against the database until you first try to use the data.

Order.recent.since(1.week.ago)
#=> Up to ten orders from the last week

Clean code

So what does clean code have to do with this? In the third chapter of his 2009 book by the same name, Bob Martin makes an excellent case for code that's organized into a series of very tiny, top-down methods. This, again, is not really new territory for most developers. Martin just pushes it to an end that I'd not really considered before and the discussion of the top-down organization somehow clicked with me in a way that it had not before.

The clean code approach to the filtering/sorting/paging problem would look at the demonstration in Ryan Bates' Railscast* and say it's too big. The filtering should be refactored into it's own method, so that the index can focus solely on getting the right type of view to render out the values. That filtering method should be broken down into a series of smaller methods, each of which performs one specific type of filtering/sorting/paging.

class ProductsController < ApplicationController
  def index
    filter_products
    sort_products

    respond_to do |format|
      format.html # render index.html.erb
      format.xml { render :xml=>@products.to_xml }
    end
  end

  private
  def filter_products
    initialize_scope
    filter_by_name 
    filter_by_category
    filter_by_price
  end

  def initialize_scope
    @products = Product.scoped {}
  end

  def filter_by_name
    return if params[:name].blank?
    @products = @products.scoped :conditions=>[ 'name LIKE ?', "#{params[:name]}%" ]
  end

  def filter_by_price
    filter_by_minimum_price unless params[:minimum_price].blank?
    filter_by_maximum_price unless params[:maximum_price].blank?
  end

  def filter_by_minimum_price
    return if params[:minimum_price].blank?
    @products = @products.scoped :conditions=>['price < ?', params[:minimum_price]]
  end

  def filter_by_maximum_price
    return if params[:maximum_price].blank?
    @products = @products.scoped :conditions=>['price < ?', params[:maxiumum_price]]
  end

  def filter_by_category
    return if params[:category_id].blank?
    @products = @products.scoped, :conditions=>{:category_id=>params[:category_id]}
  end
end

Conclusion

Okay, so nothing too earth-shattering if you've been deep into Rails for a while but hopefully a help if you're a relative novice. Have we gained anything? Sure, we've gained a few things. The use of named and anonymous scopes has greatly simplified our ability to respond to the user who desires to do ad hoc filtering against our data. They also make sorting and paging relatively simple -- just add an appropriate scope that users :order, :limit, and :offset appropriately and you can sort or page any of the target result sets the user could dream up. Just as importantly the top-down organization of very tiny (generally private) methods makes the top-most levels of the program (the index and initial filter method) read somewhat like a newspaper article: the headline (index) describes the main event, the first paragraph (#filter) provides the most important details, and the subsequent 'paragraphs' (lower methods in the chain) progressively reveal the implementation details. We have a simple solution to a problem with many combinations that should be easy to read and maintain in the future.

A side benefit

This approach saved me a lot of work earlier today. I had a rather inelegant solution to a particular problem in which I needed to filter and sort a list of members. The twist was that I needed the exact same sorting and filtering for two completely different contexts with very different views representing the results. The initial approach was to send the filtering request to the #index method of the MembersController; it seemed like a natural place to organize the member-specific logic. The method chose the view for rendering the results based on the 'commit' value (the name of the submit button). Unfortunately, a certain "non-modern browser" was not supplying the commit value. Ugh!

How did we keep it DRY? Simple. Since the code was organized with this top-down approach I simply extracted the methods from the controller class into a module and included the module in the two controllers that needed the search logic. The big benefit was that I only needed to move the lower-level functions; the higher functions (e.g., #index) remained in place. Actually the #index method was simplified since it could now focus on rendering the list of Members in only one way; the other controller picked up the single call to filter and rendered the results as it needed to. Simple code, simple refactoring, DRY solution.

Anyone have a glass of water?


* No offense intended to Ryan or his Railscast, which was focused on the mechanics of using anonymous scopes and immensely helpful in helping me get a handle on how to use them.

0 comments | Filed Under: Rails Ruby | Tags:

June Meeting: Writing a DSL in Ruby

Posted by ryan, Fri Jun 12 11:41:00 UTC 2009

This month I will be reviewing Slither, an open source DSL I wrote in Ruby for parsing and building fixed-width text files. I’ll walk through the use case for the project and demo it’s use. I also plan to talk about my approach to building and testing the DSL.

In the meantime, feel free to fork or clone the project on Github and take a look. I’d love for you guys to come with questions, suggestions and even patches. I’m looking forward to it.

Presenter: Ryan Wood, sourcescape.com

Date: Tuesday, June 23, 2009

Doors are open at 11:45am so we can chat before the presentation begins at 12:00pm. If you’re pressed for time at lunch, feel free to come right at 12:00pm.

Location

Immedion will be graciously hosting our group. Click here for directions.

2 comments | Filed Under: Meetings Ruby | Tags:

If it quacks like a duck...

Posted by andy, Wed Feb 20 09:00:00 UTC 2008

If it quacks like a duck...

duck-typing is the Way of Ruby and Rails programming. The phrase attributed to James Whitcomb Riley refers to the preference in Ruby and Rails to be concerned with what an object does (methods and attributes) rather than what an object is (it's class). That makes a lot of sense from a modeling perspective. We create classes as representations of like things, but we really deal with them in terms of the way we get to the distinguishing attributes and the kinds of things that it can do because it is a member of that group.

It makes even more sense from a Rails perspective. One of the great mantras of Rails programming is the DRY principle: Don't Repeat Yourself. A primary means of not repeating yourself is to capture reusable functionality in modules and mix those modules into the classes that need to be able to do those kinds of things. Modules are, first and foremost, abstractly written collections of methods... ways of describing how a duck quacks...

Duck typing is more than just an interface implementation. In most static languages the emphasis is on grabbing a particular interface on an object and then making use of that interface as a contract for interaction. With duck typing you really could not care less whether or not you have an interface. You really only care about whether or not the duck can quack. So you ask it:

duck.respond_to?(:quack)

How I learned to love ducks

Okay, so all the duck typing talk may be old hat to you by now. No matter. It was old hat to me, too. I just forgot to do it. Call it old habits dying hard but my code was littered with type-checking.

A particularly bad area of my largest application is designed to allow the end user to set up their own business processes. The code is full of subclasses that each perform one business function and the user hooks them up to design their larger processes. Where it begins to suffer is from the "all roads lead to Rome" problem. For our customers there is a central object with which they deal, but different users will typically get a handle on it through a different association. Rather than force the user to navigate up the object graph we decided to let the process step do the navigation for them. Falling back on old habits I'd have code looking like this

def apply(target_object, attributes={})
  case
    when target_object.is_a?(Widget)
      return target_object.foo.bar! attributes
    when target_object.is_a?(Cog)
      return target_object.foo.bar! attributes
    when target_object.is_a?(Foo)
      return target_object.bar! attributes
  end
  raise(ArgumentError, "No, foo on you!") 
end

The basic idea is to call the bar! method on a Foo class object, but allow the user to apply the process in any context that knows how to navigate up to the Foo class object (including a Foo instance itself). Obviously the repetition was screaming for some refactoring. Enter duck typing.

def apply(target_object,  attributes)
  foo = target_object.respond_to?(:foo) ? target_object.foo : target_object
  raise(ArgumentError, "Duck foo on you") unless foo.respond_to?("bar!")
  foo.bar! attributes
end

Duck typing brings a lot of advantages to that code. Obviously it eliminates the repetition. An important corollary is that it reduces the code base so there is less to maintain and less to break. Duck typing in this scenario also decouples the method from the classes that might need to use it. This is important in two regards. First, it means that I can eliminate one of those classes like the Widget class and not have to modify all the places that refer to the Widget class to eliminate 'undefined constant' errors. Second, it means that I can now introduce new objects that have a handle on the Foo class and automatically gain the ability to use this process step without modification. A less obvious point is that the code now fails more quickly if it's passed a target object that doesn't know Foo; it does not have to wait until all the branches of the case statement fail.

In my opinion, the nicest part of the duck-typing focused refactoring is that it makes the intentions of the method much clearer. Like a really good joke or a really bad pun, the punch is in the final line. What's the objective? To call 'bar!' with the appropriate attributes on a Foo instance.

0 comments | Filed Under: Ruby | Tags:

Objective fun: Even methods can be objects

Posted by andy, Thu Feb 14 13:00:00 UTC 2008

Even Methods Can Be Objects

One of the great things about Ruby is the extent to which everything is an object. There are significantly fewer 'primitives' in Ruby than in any other language with which I've worked. Even numbers are objects. Even methods are objects. Well, at least they can be.

Say Hello to My Little Friend Proc

Methods, at least code blocks, can become objects through the Proc class. As the second edition of Programming Ruby says it:

Proc objects are blocks of code that have been bound to a set of local variables. Once bound, the code may be called in different contexts and still access those variables.
Huh? Basically, the Proc class lets you wrap up a block of code in an object, call it some place, and when it's called it's aware of the context from which it was called. GoF fans will probably recognize this as a form of the command pattern.

Okay, let's get down to brass tacks. As you'd expect, you create a new Proc instance by calling new. This method accepts a block with an arbitrary number of block parameters. Why an arbitrary number of them? Because those block parameters are going to become the parameters you use when you invoke the method you're wrapping up. Again, let's defer to Programming Ruby and look at their example:

def genTimes(factor)
  return Proc.new {|n| n*factor }
end

times3 = genTimes(3) 

times3.call(12)  ยป 36

So what's going on here... the genTimes method accepts an argument called 'factor' and creates a Proc instance (a wrapped up method) with it. The wrapped up method accepts a single parameter it calls 'n' and returns the result of multiplying n and factor. Since this is a closure, the Proc is aware of the surrounding context and it pulls in 'factor' from genTimes. In the call 'genTimes(3)', factor is assigned the value 3 (duh), so the result of the call is to hand back an object-wrapped method that calculates n * 3.

As the Proc basically implements the command pattern you can use this object by invoking the command -- sending the 'call' message. In the example above the method expects one parameter (n) which is why the next-to-last line says, 'times3.call(12)'... the time3 object has a method that multiplies an argument by 3, and when called with the argument 12 you get 12 * 3 = 36. That's not quite so painful.

So Where's the Fun?

The 'fun' obviously lies in the way you can use the procs. In his brilliant book The Rails Way early adopter Obie Fernandez provides a great example that really struck a chord with me (I won't spoil the ending... buy the book!). At the end of his chapter on helpers Fernandez refactors a very specific partial into a very general custom helper. What struck a chord was that the partial essentially needed a 'description' method for the objects that it rendered. Obviously that was not a problem in the very specific original implementation, but it became one when trying to generalize the code. Enter Proc, stage right.

def cool_helper(collection, opts={})
...
opts[:description] ||= Proc.new{|item| itemd.description}
...
render :partial => 'shared/cool_partial',
  :locals => {:description => opts[:description], ... }
end

In line 3 the refactored helper method creates a default Proc instance to handle the initial need for the description. All the proc does is call the 'description' method on the object that it's passed. The nice thing about this is that the default functionality matches what was being done in the original implementation. More importantly, though, this proc is being created as one of the optional parameters that can be supplied by the caller. That means if you would like to reuse the helper with an object that does not have a 'description' method (accessor or otherwise) then you can supply your own 'description' method to the renderer not in your object. For example, what if you now wanted to use this helper to display a list of sports teams and you wanted the description to be the 'name' attribute?

cool_helper my_teams, :description=>Proc.new{|item| item.name}

And there is where it gets fun. Since the proc is an object you can pass it between other objects, but what you're really passing is the ability to perform some custom functionality. The beauty, of course, is that the partial gets to remain blissfully ignorant of the implementation. It does not know or care whether it's invoking the description or name or any other attribute or method. It simply issues the 'call' method and the wrapped up function handles the rest. Something like this:

<div class="description"><br/>
  <%= description.call(item) %><br/>
</div>

In the snippet above, just remember that 'description' is the name of the local variable passed into the partial through the :locals hash... and that variable is the object-wrapped method (Proc) that calls the description on your item.

0 comments | Filed Under: Ruby | Tags:

Static thinking about a dynamic language

Posted by andy, Tue Feb 05 09:00:00 UTC 2008

Static thinking about a dynamic language

If you've approached Ruby from a background in programming with static (compiled) languages it's easy to get a lot of "static" in your thinking about Ruby. One of the most common places to lose sight of t dynamic nature of the Ruby language is in class definitions. A class definition is really a call to a method in Kernel that creates a global constant with a reference to the object that represents the class, but Ruby has so faithfully repeated the class-definition language of static languages that we forget that we're actually executing code.

Who cares if class definitions are dynamic?

The dynamic nature of class definitions in Ruby can be a big deal if you take advantage of it. Mike Clark points out a nice use of the dynamic nature of Ruby in the forthcoming Advanced Rails Recipes. The basic scenario is that you've got an ActiveRecord model that contains data that is primarily intended to be constant for the life of the application -- something like a table of states and provinces (so Clark) or menu items. Rather than look for performance improvements through caching, you could instead create a constant array on the ActiveRecord class that is populated as the class is created.

class MenuItem < ActiveRecord::Base
  MENUS = { :start_menu=>1, ... }
  START_MENU_ITEMS = find(:all, :order=>"position, name", :conditions=>{:menu_id=>MENUS[:start_menu]})
end

The MenuItem class above has already inherited the class-level find() method from ActiveRecord::Base we we make use of it during the class creation process. By doing this the constant data stays in memory and need not be cached. Of course, care should be taken to make sure that the amount of data stored in this constant array is not so large as to reduce performance elsewhere.

The dynamic nature of Ruby class definitions can also help to keep your class-definitions DRY. I've recently been working on a project in which a Person may have many Addresses. Simple enough. But the Addresses need to be subclassed, using single table inheritance, so that I can distinguish a home address from a work address. Oh, yeah, the Addresses also have a date range associated with them so that we can track when you plan on moving to a new Address, which in turn leads me to a need to know the current home address and work address and ... This could get very messy. But it's not if we take advantage of the dynamic nature of Ruby.

class Address &lt; ActiveRecord::Base
  self.inheritance_column = 'address_type'
  ADDRESS_TYPES = %w(HomeAddress WorkAddress SchoolAddress TemporaryAddress)
  belongs_to  :addressable, :polymorphic=&gt;true
end

Address::ADDRESS_TYPES.each do |address_type| 
  eval "class #{address_type} &lt; Address; end"
end

class Person < ActiveRecord::Base
  has_many  :addresses, :as=&gt;:addressable
  Address.subclass_names.each do |address_type| 
    self.send(:has_one, "current_#{address_type.underscore}", 
                      :as=&gt;:addressable, 
                      :class_name =&gt; address_type,
                      :conditions=&gt;['activated_on &lt;= ? AND deactivated_on IS NULL OR deactivated_on&gt;?', Date.today, Date.today])
  end
end

In the code above I'm actually taking advantage of Ruby's dynamics twice. In lines 7-9 I'm iterating through each of the ADDRESS_TYPES declared in the Address class above and declaring a new subclass for each entry in the array. This may not work in every situation; certainly in most instances of subclassing you'll want to add code to the subclass. It works here, though, because the subclass name will be used in rendering (e.g., putting a nice home or work image next to the address with css).

Lines 14-18 is where I've used the dynamic nature of Ruby class declarations to keep things DRY. The Address.subclass_names method simply iterates over the subclassess of Address and returns an array of the names. This might seem overkill since ADDRESS_TYPES already has this information but it will allow me to know if classes are created in some way other than through the loop in lines 7-9. That said, lines 14-18 simply iterate over all the names of the subclasses and creates an association between person and one member of the addresses collection. Specifically, it creates an Address#current_home_address for the HomeAddress class and so on.

0 comments | Filed Under: Ruby | Tags: