views:

261

answers:

1

As much I would like to I still don't know how to implement metaprogramming.

For views rendered from my Admin::Base controller I would like override the Rails compute_public_path located under ActionView::Helpers::AssetTagHelper, so that all my admin's layout files will be under public/admin.

There is probably a better way to this, but at this point I want to learn how to do it this way.

In my mind I put this in Admin::Base controller

module ActionView::Helpers::AssetTagHelper
  def compute_public_path(source, dir, ext = nil, include_host = true)
    super(source, "admin/#{dir}", ext = nil, include_host = true)
  end
end

but it gives me this

super: no superclass method `compute_public_path' for #<ActionView::Base:0x1032240a8>

Which doesn't surprise me.

Any help would be great!


Edit Feb 12, 2010 8:00am

If I try this in my admin helper

def compute_public_path_with_admin(source, dir, ext = nil, include_host = true)
  compute_public_path_without_admin(source, "admin/#{dir}", ext, include_host)
end

alias_method_chain :compute_public_path, :admin

I get undefined method compute_public_path' for moduleAdminHelper', which I am guessing happens because 'compute_public_path' is a private method.

I found this works works

ActionView::Helpers::AssetTagHelper.class_eval do
  def compute_public_path_with_admin(source, dir, ext = nil, include_host = true)
    compute_public_path_without_admin(source, "admin/#{dir}", ext, include_host)
  end

  alias_method_chain :compute_public_path, :admin
end

As long as I set config.cache_classes to false, otherwise I get a stack level too deep error

Thanks to Squeegy for pointing me in the right direction.

How can I make this work with disabling class caching?

A: 
def compute_public_path_with_admin(source, dir, ext = nil, include_host = true)
  compute_public_path_without_admin(source, "admin/#{dir}", ext, include_host)
end

alias_method_chain :compute_public_path, :admin

compute_public_path will now call your implementation, which then calls the original implementation.

See: http://stackoverflow.com/questions/1034586/is-alias-method-chain-synonymous-with-alias-method

Squeegy
But where do I place this code? Does it go in the controller, or into an initializer?
ToreyHeinz
Place it the class or module that has the method you want to override. Like perhaps a helper that all your admin views share in common? Not actually where this method would get called from so you may have to play around a little.
Squeegy
What if the method is private? I can't seem to override it.
ToreyHeinz
Thanks for your input Squeegy, I still need to figure out how to make it work with class caching on, but I am so close now thanks to you.
ToreyHeinz