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