More on form_for(@non_arb)

My previous post talked about how to make form_for(@non_arb) work. When we need it for multiple classes, we came up with a little bit meta-programming so that classes that needs such ability can simply say:

polymorphic_routes_for :person,
:update_path => :admin_person_path,
:create_path => :admin_people_path

As you can see, it also takes options, update_path and create_path, if you don’t specify the paths, it will infer from the first param, which would make update path to person_path and create path to people_path.

The magic behind the scene is in the following, it can be in a module that you can mix in, or in our situation, in a superclass, Presenter where all presenters inherit from.

class Presenter
  class << self
    def polymorphic_routes_for(symbol, options = {})
      self.class_eval "def id; #{symbol}.id; end"
      self.class_eval "def to_param; #{symbol}.to_param; end"
      self.class_eval "def new_record?; #{symbol}.new_record?; end"
      update_path = options&#91;:update_path&#93; || "#{symbol}_path"
      ActionView::Base.send :alias_method, "#{self.name.underscore}_path", update_path

      create_path = options&#91;:create_path&#93; || "#{symbol.to_s.pluralize}_path"
      ActionView::Base.send :alias_method, "#{self.name.underscore.pluralize}_path", create_path
    end

  end

&#91;/sourcecode&#93;

and here is the specs for it:
&#91;sourcecode language="ruby"&#93;
describe Presenter, "when specifying the polymorphic routes for a model" do
  before :each do
    ActionView::Base.class_eval("def test_model_path;end")
    ActionView::Base.class_eval("def test_models_path;end")
    class A < Presenter
      polymorphic_routes_for :test_model
      attr_reader :test_model
    end

    @presenter = A.new :test_model => mock("Model")
  end

  it "should generate id method" do
    @presenter.test_model.should_receive(:id).and_return "id"
    @presenter.id.should == "id"
  end

  it "should generate to_param method" do
    @presenter.test_model.should_receive(:to_param).and_return "to param"
    @presenter.to_param.should == "to param"
  end

  it "should generate new_record? method" do
    @presenter.test_model.should_receive(:new_record?).and_return "new record"
    @presenter.new_record?.should == "new record"
  end

  it "should alias update named route method to ActionView::Base" do
    ActionView::Base.new.should respond_to(:a_path)
  end

  it "should alias create named route method to ActionView::Base" do
    ActionView::Base.new.should respond_to(:as_path)
  end
end

describe Presenter, "when specifying the polymorphic routes for a model and specifying update_path option" do
  before :each do
    ActionView::Base.class_eval("def test_update_path; 'customized update path'; end")
    ActionView::Base.class_eval("def test_models_path;end")
    
    class A < Presenter
      polymorphic_routes_for :test_model, :update_path => :test_update_path
      attr_reader :test_model
    end

    @presenter = A.new :test_model => mock("Model")
  end

  it "should alias update named route method given by update_path option to ActionView::Base" do
    ActionView::Base.new.a_path.should == 'customized update path'
  end

end

describe Presenter, "when specifying the polymorphic routes for a model and specifying create_path option" do
  before :each do
    ActionView::Base.class_eval("def test_model_path; end")
    ActionView::Base.class_eval("def test_create_path; 'customized create path'; end")

    class A < Presenter
      polymorphic_routes_for :test_model, :create_path => :test_create_path
      attr_reader :test_model
    end

    @presenter = A.new :test_model => mock("Model")
  end

  it "should alias create named route method given by update_path option to ActionView::Base" do
    ActionView::Base.new.as_path.should == 'customized create path'
  end

end
Advertisements

~ by Yi Wen on March 14, 2008.

One Response to “More on form_for(@non_arb)”

  1. […] my previous post More on form_for(@non_arb), I showed a trick to get polymorphic routes working so that the form can be […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: