December 09, 2005

Demagogues or Directors

Althouse:
"But I am tired of being overwhelmed. Why should I admire somebody for his ability to manipulate me? In other realms of life, this talent is known as demagoguery. There are better reasons to turn to art, better reasons to go to the movies, than to be blown away."—Leon Wieseltier on "Munich."

I remember a friend a few years ago saying that his favorite recreation was sitting with his daughter in a big armchair with a take-out Chinese dinner and a stack of videos. My response was horror: I realized that for me, a visit to a movie was excruciatingly painful.

A few weeks later, I sat waiting for Gladiator to start, waiting as in the dentist's chair for an unpleasant but necessary procedure. I find that I enjoy the experience—usually—but not the anticipation, because I know my emotions will be juggled by the director, and I will be &ldquot;overwhlemed&rdquot; or moved or toyed with.

Posted by ronlusk at 08:32 PM

December 06, 2005

list_for class method

In a Rails application, I often need to display the child objects belonging to a parent object. For instance, a Community may have a number of Locations within it. If my communities_controller produces a list of Communities, I'd like to have a Locations link for each entry which will ask the locations_controller to list only the Locations for that Community. Thus, I want the LocationsController to have a list_for_community method. Coding this for each level of a structure grows wearisome.

Therefore, I took advantage of the flexibility of Ruby to create a list_for class method, below:

class ApplicationController < ActionController::Base
  # Generate a controller method to list _children_ (of this class) for
  # a given _parent_ of some other class.  
  # @parent@::       name of parent entity, as string
  #                  or symbol: @:community@
  # @order_clause@:: order for listed children: defaults to 'id ASC'
  # @children@::     plural name for collection passed to 'list' view.
  #                  Will default to the prefix of the controller name,
  #                  thus, foo_bars_controller will
  #                  yield a collection named @foo_bars.  For
  #                  that matter, product_controller will yield
  #                  a collection named @products, because
  #                  we pluralize the name anyway.
  #
  def self.list_for(parent,order_clause='id ASC',children=nil)
    unless children
      children = self.name.underscore.gsub(/_controller$/,'').pluralize
    end
    parvar = parent.to_s.underscore
    parcls = parent.to_s.camelize.constantize
    child_qual = children.to_s.singularize.underscore
    child_var = children.to_s
    pages = "@#{child_qual}_pages"
    code = %Q{
    def list_for_#{parvar}
      #{parvar} = #{parcls}.find(params[:id])
      #{pages} = Paginator.new self,
        #{parvar}.#{children}.count, 10, @params['page']
      @#{children} = #{parvar}.#{children}.find(:all,
      :order => '#{order_clause}',
      :limit => #{pages}.items_per_page,
        :offset => #{pages}.current.offset)
        @title = "#{children.humanize} for #{parvar.humanize} '\#{#{parvar}}'"
      render :action => :list
    end
  }
    module_eval code
  end
end

So, if in my locations_controller.rb file I have the line

  ...
  list_for :community, 'Service_Location ASC'
  ...
the class method will generate a list_for_community method that expects the id parameter to identify a community. It will then pass to the default 'list' view an instance variable @locations (it takes the name from the controller class) which contains only the locations for the selected community.
Posted by ronlusk at 12:32 PM