Unsure How To Modify ActionController::Base

Hello,

I would like to add a couple of methods like url_for in such a way that I can call these other methods in my actions just as I might call url_for. However I keep getting undefined method errors when I execute those calls.

Here's what I did:

1. Generated a plugin: $ script/generate plugin UrlForRouter

2. Created the file RAILS_ROOT/vendor/plugins/url_for_router/lib/url_for_router.rb      This file looks like:

       module UrlForRouter          def internal_url_for(options = {})            host_url_for('0.0.0.0:3000', options)          end

         def external_url_for(options = {})            host_url_for('xxx.xxx.xxx.xxx', options) # anonymised          end

         private          def host_url_for(host, options = {})            ENV['RAILS_ENV'] == 'development' ? url_for(options.merge(:host => host)) : url_for(options)          end        end

3. Edited RAILS_ROOT/vendor/plugins/url_for_router/init.rb to look like this:

       require 'url_for_router'        ActionController::Base.include UrlForRouter

4. Restarted web server.

5. In my actions I call internal_url_for and external_url_for exactly as I would call url_for.      I get the error: undefined method `external_url_for' for ...etc

Is this even the right way to proceed? If so, what am I doing wrong?

Many thanks, Andy Stewart

Andrew Stewart wrote:

Hello,

I would like to add a couple of methods like url_for in such a way
that I can call these other methods in my actions just as I might
call url_for. However I keep getting undefined method errors when I
execute those calls.

Here's what I did:

1. Generated a plugin: $ script/generate plugin UrlForRouter

2. Created the file RAILS_ROOT/vendor/plugins/url_for_router/lib/ url_for_router.rb      This file looks like:

       module UrlForRouter          def internal_url_for(options = {})            host_url_for('0.0.0.0:3000', options)          end

         def external_url_for(options = {})            host_url_for('xxx.xxx.xxx.xxx', options) # anonymised          end

         private          def host_url_for(host, options = {})            ENV['RAILS_ENV'] == 'development' ? url_for(options.merge (:host => host)) : url_for(options)          end        end

3. Edited RAILS_ROOT/vendor/plugins/url_for_router/init.rb to look
like this:

       require 'url_for_router'        ActionController::Base.include UrlForRouter

4. Restarted web server.

5. In my actions I call internal_url_for and external_url_for
exactly as I would call url_for.      I get the error: undefined method `external_url_for' for ...etc

Is this even the right way to proceed? If so, what am I doing wrong?

Many thanks, Andy Stewart

>

Andrew,

I think that include method is private; not 100% sure, but I recall having similiar troubles like you described. So you would have to include it like:

ActionController::Base.send :include, UrlForRouter

Andy,

Unless you want to share these methods across multiple apps don't bother making a plugin. Just do the following:

1) Put url_for_router.rb in your lib/ 2) Include the module in application.rb

class ApplicationController < ActionController::Base   include UrlForRouter   ... end

3) That's it!

Also, if you want to use these methods in your views you can simply add the following to your module.

module UrlForRouter

    # --- [ ActionView helper methods ] ---     def self.included(base)       base.send :helper_method, :internal_url_for, :external_url_for     end

end

Hope this helps.

Unless you want to share these methods across multiple apps don't bother making a plugin. Just do the following:

I was thinking that I would reuse this code in future apps. Now that you mention it though, there's no need at the moment. So I'm going with your approach.

1) Put url_for_router.rb in your lib/ 2) Include the module in application.rb

class ApplicationController < ActionController::Base   include UrlForRouter   ... end

3) That's it!

That works wonderfully in my controller. Thanks!

However I also have a model (which doesn't subclass ActiveRecord) where I am trying to call my {internal, external}_url_for methods and I get this error:

   undefined method `url_for'    #{RAILS_ROOT}/lib/url_for_router.rb:16:in `host_url_for'    #{RAILS_ROOT}/lib/url_for_router.rb:10:in `external_url_for'

My model class finds and calls my methods but the UrlForRouter module can't resolve url_for in this context. What should I do here?

Also, if you want to use these methods in your views you can simply add the following to your module.

module UrlForRouter

    # --- [ ActionView helper methods ] ---     def self.included(base)       base.send :helper_method, :internal_url_for, :external_url_for     end

end

Very nice!

Hope this helps.

Yes it does, very much.

Thanks! Andy

Bojan, thanks for this. I tried it but unfortunately it didn't work for me. However that's probably down to some other flaw on my part rather than your suggestion.

Thanks, Andy

1) Put url_for_router.rb in your lib/ 2) Include the module in application.rb

class ApplicationController < ActionController::Base   include UrlForRouter   ... end

That works wonderfully in my controller. Thanks!

However I also have a model (which doesn't subclass ActiveRecord) where I am trying to call my {internal, external}_url_for methods and I get this error:

  undefined method `url_for'   #{RAILS_ROOT}/lib/url_for_router.rb:16:in `host_url_for'   #{RAILS_ROOT}/lib/url_for_router.rb:10:in `external_url_for'

My model class finds and calls my methods but the UrlForRouter module can't resolve url_for in this context. What should I do here?

Just for the record, I found this post[1] which argues persuasively for keeping knowledge of URLs out of models (as well as showing a good way to generate URLs within ActionMailer). So I moved the URL knowledge out of my model. Simple, really, when I thought about it.

Regards, Andy

[1] http://www.ryandaigle.com/articles/2006/08/23/whats-new-in-edge-rails-form-urls-in-your-actionmailers-and-elsewhere