Rails.application.routes.draw do
resources :carts
...
end
Now in controller, I can
cart_url(@cart)
or in view, I can
<%= link_to 'New Cart', new_cart_path %>
In which context are cart_url and new_cart_path defined? (how to see those in rails console)
In rails console, I tried:
irb(main):053:0> ApplicationController.new.rails_postmark_inbound_emails_path
Traceback (most recent call last):
2: from (irb):53
1: from (irb):53:in `rescue in irb_binding'
NoMethodError (undefined method `host' for nil:NilClass)
irb(main):058:0> CartsController.new.carts_url
Traceback (most recent call last):
2: from (irb):58
1: from (irb):58:in `rescue in irb_binding'
NoMethodError (undefined method `host' for nil:NilClass)
irb(main):056:0> CartsController.new_line_item_url
Traceback (most recent call last):
2: from (irb):56
1: from (irb):56:in `rescue in irb_binding'
NoMethodError (undefined method `new_line_item_url' for CartsController:Class)
CodePudding user response:
The context for the route helpers is actually an anomynous module.
# This code was abbreviated for StackOverflow
module ActionDispatch
# A NamedRouteCollection instance is a collection of named routes, and also
# maintains an anonymous module that can be used to install helpers for the
# named routes.
class NamedRouteCollection
include Enumerable
attr_reader :routes, :url_helpers_module, :path_helpers_module
private :routes
def initialize
@routes = {}
@path_helpers = Set.new
@url_helpers = Set.new
@url_helpers_module = Module.new
@path_helpers_module = Module.new
end
def add(name, route)
key = name.to_sym
path_name = :"#{name}_path"
url_name = :"#{name}_url"
if routes.key? key
@path_helpers_module.undef_method path_name
@url_helpers_module.undef_method url_name
end
routes[key] = route
helper = UrlHelper.create(route, route.defaults, name)
define_url_helper @path_helpers_module, path_name, helper, PATH
define_url_helper @url_helpers_module, url_name, helper, UNKNOWN
@path_helpers << path_name
@url_helpers << url_name
end
def get(name)
routes[name.to_sym]
end
def key?(name)
return unless name
routes.key? name.to_sym
end
alias []= add
alias [] get
alias clear clear!
def each(&block)
routes.each(&block)
self
end
def names
routes.keys
end
def length
routes.length
end
# Given a name , defines name_path and name_url helpers.
# Used by 'direct', 'resolve', and 'polymorphic' route helpers.
def add_url_helper(name, defaults, &block)
helper = CustomUrlHelper.new(name, defaults, &block)
path_name = :"#{name}_path"
url_name = :"#{name}_url"
@path_helpers_module.module_eval do
redefine_method(path_name) do |*args|
helper.call(self, args, true)
end
end
@url_helpers_module.module_eval do
redefine_method(url_name) do |*args|
helper.call(self, args, false)
end
end
@path_helpers << path_name
@url_helpers << url_name
self
end
end
# ...
end
This module is created before the request is passed to a controller when ActionDispatch reads the route file and builds a routes collection.
And the controller then includes both the url_helpers
and path_helpers
modules. How this method ends up in the view is a topic upon itself but the gist is that ActionView::Context provides the methods and instance variables of the controller as the context (self) to the templating engine (ERB, Slim, Haml, jBuilder etc).
You can call the route helpers in the console via app
. Thats because the console session is actually an integration test (