How to define own routing helpers in rails 3? - ruby-on-rails

I use polimorphic_path and it some buggy. This method require some route helper that not defined. How can I define (like regular method) own route helper which will be used like "model_name_path, model_name_url etc"?

This solution worked for me.
Add this code to the end of config/routes.rb file. Make sure to replace MyApp with your application's name.
MyApp::Application.routes.named_routes.module.module_eval do
def model_name_path(*args)
# Your code here
end
def model_name_url(*args)
# Your code here
end
end
MyApp::Application.routes.named_routes.instance_eval do
#helpers += [:model_name_path, :model_name_url]
end
These custom methods will be available in controllers, views and tests.

I know one possible answer for _path, but the same isn't working for me for _url. Anybody know why?
# at the bottom of config/routes.rb
module ActionView::Helpers::UrlHelper
def model_name_path model, args={}
# your implementation
end
end

Related

Logic for Application Layout

I am trying to make an ActiveRecord call to get information for the application layout (the default application.html.haml layout). I know I am not supposed to put logic into the layout itself, but I am unsure of where to put it.
The line of code I need run in the layout is just a simple Model call:
Client.find_by(:id => current_user.client_id)
I would suggest throwing it in helpers/application_helper.rb. I've used this in the past for things such as title helpers and body class helpers.
# helpers/application_helper.rb
module ApplicationHelper
def body_class
[controller_name, action_name].join(' ')
end
end
# views/layouts/application.slim
body class=body_class
= yield
The ApplicationController isn't for such helpers. It's mainly as support for your controllers, not your views.
It's okay if you put it in ApplicationController. And you can put controller related code to controllers/concerns folder.
'concerns/concern.rb':
module Concern
def method
# Your code here
end
end
To use a module from concerns folder include it in the controller: include Concern

Rails - URL helpers not working in mailers

I tried:
class MyMailer
def routes
Rails.application.routes.url_helpers
end
def my_mail
#my_route = routes.my_helper
... code omitted
end
Also inside mailer:
include Rails.application.routes.url_helpers
def my_mail
#my_route = my_helper
Also, the simple way, in mailer template:
= link_to 'asd', my_helper
But then when I try to start console I get:
undefined method `my_helper' for #<Module:0x007f9252e39b80> (NoMethodError)
Update
I am using the _url form of the helper, i.e. my_helper_url
For Rails 5, I included the url helpers into the my mailer file:
# mailers/invoice_mailer.rb
include Rails.application.routes.url_helpers
class InvoiceMailer < ApplicationMailer
def send_mail(invoice)
#invoice = invoice
mail(to: #invoice.client.email, subject: "Invoice Test")
end
end
Doing this broke my other routes.
# mailers/invoice_mailer.rb
include Rails.application.routes.url_helpers
Doing this is not the right way, this will break application as routes are reloading and routes will not be available is those are reloading
module SimpleBackend
extend ActiveSupport::Concern
Rails.application.reload_routes!
Right answer is to use *_url and not *_path methods in email templates as explained below in Rails docs.
https://guides.rubyonrails.org/action_mailer_basics.html#generating-urls-in-action-mailer-views
I ran into the same issue but with a Concern, i was unable to use any of the url helpers in my code even using directly Rails.application.routes.url_helpers.administrator_beverages_url i was getting this error:
undefined method `administrator_beverages_url' for #<Module:0x00000002167158> (NoMethodError)
even unable to use the rails console because of this error the only way i found to solve this was to use this code in my Concern
module SimpleBackend
extend ActiveSupport::Concern
Rails.application.reload_routes! #this did the trick
.....
The problem was Rails.application.routes.url_helpers was empty at the moment of the initialization. I don't know the performance implication of using this but for my case this is a small application and i can take the bullet.
In the mailer add
helper :my
or the helper you need
and it will load app/helpers/my_helper.rb & includes MyHelper
Enjoy
The rails route helpers are in Rails.application.routes.url_helpers. You should just be able to put
include Rails.application.routes.url_helpers at the top of your class, though I haven't tested this
I came across this issue while working with a newly added route that seemed to be unavailable in my Mailer. My problem was I needed to restart all the workers, so they would pick up the newly added route. Just leaving this footnote in here in case someone runs into the same issue, it can be tricky to solve if you don't know this is happening.
Please take a look at this blog which explains how you can make use of Rails.application.routes.url_helpers in the right manner.
http://hawkins.io/2012/03/generating_urls_whenever_and_wherever_you_want/
You need to use the my_helper_url

How to use url helpers in lib modules, and set host for multiple environments

In a Rails 3.2 app I need to access url_helpers in a lib file. I'm using
Rails.application.routes.url_helpers.model_url(model)
but I'm getting
ArgumentError (Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true):
I've found a few things written about this, but nothing that really explains how to solve this for multiple environments.
i.e. I assume I need to add something to my development.rb and production.rb files, but what?
Closest I've seen to an answer suggested using config.action_mailer.default_url_option, but this does not work outside of action mailer.
What is the correct way to set the host for multiple environments?
This is a problem that I keep running into and has bugged me for a while.
I know many will say it goes against the MVC architecture to access url_helpers in models and modules, but there are times—such as when interfacing with an external API—where it does make sense.
After much searching I've found an answer!
#lib/routing.rb
module Routing
extend ActiveSupport::Concern
include Rails.application.routes.url_helpers
included do
def default_url_options
ActionMailer::Base.default_url_options
end
end
end
#lib/url_generator.rb
class UrlGenerator
include Routing
end
I can now call the following in any model, module, class, console, etc
UrlGenerator.new.models_url
Result!
A slight improvement (at least for me) on Andy's lovely answer
module UrlHelpers
extend ActiveSupport::Concern
class Base
include Rails.application.routes.url_helpers
def default_url_options
ActionMailer::Base.default_url_options
end
end
def url_helpers
#url_helpers ||= UrlHelpers::Base.new
end
def self.method_missing method, *args, &block
#url_helpers ||= UrlHelpers::Base.new
if #url_helpers.respond_to?(method)
#url_helpers.send(method, *args, &block)
else
super method, *args, &block
end
end
end
and the way you use it is:
include UrlHelpers
url_helpers.posts_url # returns https://blabla.com/posts
or simply
UrlHelpers.posts_url # returns https://blabla.com/posts
Thank you Andy! +1
Use this string in any module controller to get application URL-helpers works in any view or controller.
include Rails.application.routes.url_helpers
Please note, some internal module url-helpers should be namespaced.
Example:
root application
routes.rb
Rails.application.routes.draw do
get 'action' => "contr#action", :as => 'welcome'
mount Eb::Core::Engine => "/" , :as => 'eb'
end
Url helpers in module Eb:
users_path
Add include Rails.application.routes.url_helpers in controller contr
So after that helper should be
eb.users_path
So inside Eb module you can use welcome_path same as in root application!
Not sure if this works in Rails 3.2, but in later versions setting default url options for the routes can be done directly on the routes instance.
So for example, to set the same options as for ActionMailer:
Rails.application.routes.default_url_options = ActionMailer::Base.default_url_options

Trying to import my helpers into a custom lib/class and suddenly I need a config?

Real simple.
class Template
def stuff_i_want
stylesheet_link_tag('my_stylesheet')
end
class << self
include ActionView::Helpers::TagHelper
include ActionView::Helpers::AssetTagHelper
end
end
And this returns..
undefined local variable or method `config' for Template:Class
from /Users/elephanttrip/.rvm/gems/ruby-1.9.3-p385#shasta/gems/actionpack-3.1.12/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb:137:in `stylesheet_link_tag'
From the stylesheet_tag_helpers.rb in Railtie :
def stylesheet_link_tag(*sources)
#stylesheet_include ||= StylesheetIncludeTag.new(config, asset_paths)
#stylesheet_include.include_tag(*sources)
end
Config isn't instantiated in that file anywhere, so I'm assuming its' required from somewhere else.. I have no idea where, or how.
Anyone know how to inject/pass a config into my helper? I've never needed to do this before.
It looks like you're actually including your helpers into Object - and then defining your Template class. I've no idea why it's asking for config, but try putting the includes inside your class definition and see if the problem goes away.
You probably shouldn't be randomly including helpers into things over than your views though - that's not what they're for.
Why not use view_context instead.
So instead of including the helper modules you can do this:
class Template
def stuff_i_want
view_context.stylesheet_link_tag('my_stylesheet')
end
end
This should work fine.
And if you want to include you helpers then use the below code:
class Template
include ActionView::Helpers::TagHelper
include ActionView::Helpers::AssetTagHelper
def stuff_i_want
stylesheet_link_tag('my_stylesheet')
end
end
Ideally you should not include helpers in ur controllers as they are not intended for that.
Hope that helps

Routes, gems and generators

I have written a gem with an install generator. I would like to use this generator to add routes to the config/routes.rb file, much in the same way as the devise gem does by adding devise_for :model_name. Therefore, I need to know how to:
Make a method (like devise_for) available within the scope of routes?
Ok I've figured it out. To add to the routes file you can use the method route in the generator. I have accomplished this by adding the following to my install_generator.rb file:
def setup_routes
route("add_gem_routes")
end
Note that I am in fact calling a method, which can be added to the scope of routes by defining it in the following namespace:
module ActionDispatch::Routing
class Mapper
def add_gem_routes
#routing code...
end
end
end

Resources