2
\$\begingroup\$

I got tired of doing (more or less) this in my rails controllers :

class ThingsController < ApplicationController

  def index
    @category = Category.find( params[:category_id] ) if params[:category_id].present?
    scope = @category ? @category.things : Thing.scoped
    @things = scope.order( :title )
  end
end

...wich also leads to a lot of conditionals in the template if @category is absent.

I had this idea (a variation on the NullObject pattern) :

class Category < ActiveRecord::Base

  def self.one_or_any( id )
    where( id: id ).first || any_category
  end

  def self.any_category
    @any_category ||= begin
      new( title: "Any category" ) do |generic|
        generic.instance_eval{ def things ; Thing.scoped end }
        generic.readonly!
        generic.freeze
      end
    end
  end
end

Which would in turn allow me to do :

class ThingsController < ApplicationController
  def index
    @category = Category.one_or_any( params[:category_id] )
    @things   = @category.things.order( :title )
  end
end

... and to get rid of category-related conditionals in the template.

I Just wonder if this is a good idea, and if it has drawbacks i don't see yet. Thoughts ?

Note : Of course the actual implementation can be different (use a specific subclass of Category instead of extending an instance, for example - or even using a decorator).

\$\endgroup\$
1
\$\begingroup\$

I'd try to keep it as simple as possible. Instead of multiple in-line conditionals or a weird abstraction, I think a single full-fledged indented conditional makes things very clear. There are two scenarios, write two branches:

class ThingsController < ApplicationController
  def index
    if params[:category_id].present? 
      @category = Category.find(params[:category_id])
      @things = @category.things
    else
      @category = nil
      @things = Thing.scoped
    end
  end
end
\$\endgroup\$
  • 1
    \$\begingroup\$ ok, but the question was more about the "generic object" idea. I'd like to avoid that @category = nil because it involves a view riddled with conditionals - if i had an object that quacks like a category, it would be better \$\endgroup\$ – m_x Sep 25 '13 at 6:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.