[LRUG] Parameterising a Rails 3 controller mixin

Andrew Stewart boss at airbladesoftware.com
Tue Oct 4 05:27:02 PDT 2011


Hola El Rug,

I have a Rails 3 engine which mixes a module into ActionController::Base.  The module provides helper methods in the controller such as `current_foo`.

Now, however, I want to parameterise those methods based on a configuration value.  So if somebody has a Bar model instead of a Foo model, the controller will get a `current_bar` method.

I think I have a working solution but I can't figure out how to test it.  Here's what I've got:

    module ControllerMixin
      # original hard-coded method:
      # def current_foo
      #   @current_foo ||= Foo.find(session[:current_foo_id]) if session[:current_foo_id]
      # end

      # parameterisable method:
      class_eval <<-END
        def current_#{MyEngine.model} ||= #{MyEngine.model.classify.constantize}.find(session[:current_#{...}_id]) if ...
      END
    end

-- where MyEngine.model is set to 'foo' or 'bar' or whatever in an initializer (defaults to 'foo').

This appears to work when I use it in a Rails app, but I can't test the 'bar' case in the engine's gem because the Rails app has already initialised with the default value 'foo' before my test's setup method can set it to 'bar'.  I.e.:

    class BarTest < ActiveSupport::TestCase
      setup do
        MyEngine.model = 'bar'  # too late!  ActionController::Base already has default `current_foo` mixed in
      end

      test 'current_bar correctly defined' do
        ...  # fails because `current_foo` exists, not `current_bar`
      end
    end

Any ideas?  Maybe a lazy-loading alternative to the class_eval approach or somehow setting MyEnding.model before Rails spins up...?

Cheers,
Andy Stewart

-------
http://airbladesoftware.com


More information about the Chat mailing list