module ActionView::Helpers::UrlHelper
def add_confirm_to_attributes!(html_options, confirm)
def add_confirm_to_attributes!(html_options, confirm) html_options["data-confirm"] = confirm if confirm end
def add_method_to_attributes!(html_options, method)
def add_method_to_attributes!(html_options, method) html_options["rel"] = "nofollow" if method && method.to_s.downcase != "get" html_options["data-method"] = method if method end
def array_or_string_for_javascript(option)
def array_or_string_for_javascript(option) if option.kind_of?(Array) "['#{option.join('\',\'')}']" elsif !option.nil? "'#{option}'" end end
def button_to(name, options = {}, html_options = {})
# "
#
#
#
#
# => ""
#
#
#
#
# => ""
#
# => "
def button_to(name, options = {}, html_options = {}) html_options = html_options.stringify_keys convert_boolean_attributes!(html_options, %w( disabled )) method_tag = '' if (method = html_options.delete('method')) && %w{put delete}.include?(method.to_s) method_tag = tag('input', :type => 'hidden', :name => '_method', :value => method.to_s) end form_method = method.to_s == 'get' ? 'get' : 'post' remote = html_options.delete('remote') request_token_tag = '' if form_method == 'post' && protect_against_forgery? request_token_tag = tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token) end url = options.is_a?(String) ? options : self.url_for(options) name ||= url html_options = convert_options_to_data_attributes(options, html_options) html_options.merge!("type" => "submit", "value" => name) ("<form method=\"#{form_method}\" action=\"#{html_escape(url)}\" #{"data-remote=\"true\"" if remote} class=\"button_to\"><div>" + method_tag + tag("input", html_options) + request_token_tag + "</div></form>").html_safe end
def convert_boolean_attributes!(html_options, bool_attrs)
convert_boolean_attributes!( html_options,
Example:
in place.
Returns the updated +html_options+ hash, which is also modified
http://www.w3.org/TR/xhtml1/#h-4.5)
section 4.5 "Attribute Minimization" for more:
removed from the +html_options+ hash. (See the XHTML 1.0 spec,
replaced with the attribute's name; otherwise the attribute is
if the associated +bool_value+ evaluates to true, it is
"attr" => bool_value
given as:
More specifically, for each boolean attribute in +html_options+
its name is listed in the given +bool_attrs+ array.)
HTML/XHTML. (An attribute is considered to be boolean if
attributes from true/false form into the form required by
Processes the +html_options+ hash, converting the boolean
def convert_boolean_attributes!(html_options, bool_attrs) bool_attrs.each { |x| html_options[x] = x if html_options.delete(x) } html_options end
def convert_options_to_data_attributes(options, html_options)
def convert_options_to_data_attributes(options, html_options) html_options = {} if html_options.nil? html_options = html_options.stringify_keys if (options.is_a?(Hash) && options.key?('remote') && options.delete('remote')) || (html_options.is_a?(Hash) && html_options.key?('remote') && html_options.delete('remote')) html_options['data-remote'] = 'true' end confirm = html_options.delete("confirm") if html_options.key?("popup") ActiveSupport::Deprecation.warn(":popup has been deprecated", caller) end method, href = html_options.delete("method"), html_options['href'] add_confirm_to_attributes!(html_options, confirm) if confirm add_method_to_attributes!(html_options, method) if method html_options end
def current_page?(options)
current_page?(:controller => 'library', :action => 'checkout')
# => true
current_page?(:action => 'checkout')
# => false
current_page?(:controller => 'shop', :action => 'checkout', :order => 'desc')
# => false
current_page?(:controller => 'shop', :action => 'checkout', :order => 'desc', :page=>'2')
# => true
current_page?(:controller => 'shop', :action => 'checkout', :order => 'desc', :page=>'1')
# => true
current_page?(:controller => 'shop', :action => 'checkout')
# => false
current_page?(:action => 'process')
Let's say we're in the /shop/checkout?order=desc&page=1 action.
# => false
current_page?(:controller => 'library', :action => 'checkout')
# => true
current_page?(:action => 'checkout')
# => false
current_page?(:controller => 'shop', :action => 'checkout', :order => 'asc')
# => true
current_page?(:controller => 'shop', :action => 'checkout')
# => false
current_page?(:action => 'process')
Let's say we're in the /shop/checkout?order=desc action.
==== Examples
True if the current request URI was generated by the given +options+.
def current_page?(options) unless request raise "You cannot use helpers that need to determine the current " \ "page unless your view context provides a Request object " \ "in a #request method" end url_string = url_for(options) # We ignore any extra parameters in the request_uri if the # submitted url doesn't have any either. This lets the function # work with things like ?order=asc if url_string.index("?") request_uri = request.fullpath else request_uri = request.path end if url_string =~ /^\w+:\/\// url_string == "#{request.protocol}#{request.host_with_port}#{request_uri}" else url_string == request_uri end end
def link_to(*args, &block)
link_to("Destroy", "http://www.example.com", :method => :delete, :confirm => "Are you sure?")
# => Visit Other Site
link_to "Visit Other Site", "http://www.rubyonrails.org/", :confirm => "Are you sure?"
The two options specific to +link_to+ (:confirm and :method) are used as follows:
# => Nonsense search
link_to "Nonsense search", searches_path(:foo => "bar", :baz => "quux")
# => Ruby on Rails search
link_to "Ruby on Rails search", :controller => "searches", :query => "ruby on rails"
# => Comment wall
link_to "Comment wall", profile_path(@profile, :anchor => "wall")
+link_to+ can also produce links with anchors or query strings:
# => WRONG!
link_to "WRONG!", :controller => "articles", :id => "news", :class => "article"
Leaving the hash off gives the wrong link:
# => Articles
link_to "Articles", { :controller => "articles" }, :id => "news", :class => "article"
Be careful when using the older argument style, as an extra literal hash is needed:
# => Articles
link_to "Articles", articles_path, :id => "news", :class => "article"
Classes and ids for CSS are easy to produce:
David -- Check it out!
# =>
<% end %>
<%= @profile.name %> -- Check it out!
<%= link_to(@profile) do %>
You can use a block as well if your link target is hard to fit into the name parameter. ERb example:
# => Profiles
link_to "Profiles", :controller => "profiles"
is better than
# => Profiles
link_to "Profiles", profiles_path
Similarly,
# => Profile
link_to "Profile", :controller => "profiles", :action => "show", :id => @profile
in place of the older more verbose, non-resource-oriented
# => Profile
link_to "Profile", @profile
or the even pithier
# => Profile
link_to "Profile", profile_path(@profile)
your application on resources and use
and newer RESTful routes. Current Rails style favors RESTful routes whenever possible, so base
Because it relies on +url_for+, +link_to+ supports both older-style controller/action/id arguments
==== Examples
they're complete
completion of the Ajax request and performing JavaScript operations once
the link. The drivers each provide mechanisms for listening for the
driver to make an Ajax request to the URL in question instead of following
* :remote => true - This will allow the unobtrusive JavaScript
the request object's methods for post?, delete? or put?.
POST behavior, you should check for it in your controller's action by using
disabled clicking the link will have no effect. If you are relying on the
to using GET. If :href => '#' is used and the user has JavaScript
Note that if the user has JavaScript disabled, the request will fall back
while spidering your site). Supported verbs are :post, :delete and :put.
in dangerous actions like deleting a record (which search bots can follow
the HTTP verb specified. Useful for having links perform a POST operation
create an HTML form and immediately submit the form for processing using
* :method => symbol of HTTP verb - This modifier will dynamically
processed normally, otherwise no action is taken.
driver to prompt with the question specified. If the user accepts, the link is
* :confirm => 'question?' - This will allow the unobtrusive JavaScript
==== Options
end
# name
link_to(url, html_options = {}) do
end
# name
link_to(options = {}, html_options = {}) do
# is passed to url_for
# url_options, except :confirm or :method,
link_to(body, url_options = {}, html_options = {})
# posts_path
# url is a String; you can use URL helpers like
link_to(body, url, html_options = {})
==== Signatures
a name, the link itself will become the name.
link will be used in place of a referrer if none exists. If +nil+ is passed as
href for the link, or use :back to link to the referrer - a JavaScript back
of an options hash to get a link tag that uses the value of the string as the
+url_for+. It's also possible to pass a string instead
of +options+. See the valid options in the documentation for
Creates a link tag of the given +name+ using a URL created by the set
def link_to(*args, &block) if block_given? options = args.first || {} html_options = args.second link_to(capture(&block), options, html_options) else name = args[0] options = args[1] || {} html_options = args[2] html_options = convert_options_to_data_attributes(options, html_options) url = url_for(options) if html_options html_options = html_options.stringify_keys href = html_options['href'] tag_options = tag_options(html_options) else tag_options = nil end href_attr = "href=\"#{html_escape(url)}\"" unless href "<a #{href_attr}#{tag_options}>#{html_escape(name || url)}</a>".html_safe end end
def link_to_if(condition, name, options = {}, html_options = {}, &block)
# If they are logged in...
# => Login
# If the user isn't logged in...
%>
end
link_to(@current_user.login, { :controller => "accounts", :action => "show", :id => @current_user })
link_to_if(@current_user.nil?, "Login", { :controller => "sessions", :action => "new" }) do
<%=
# => Login
# If the user isn't logged in...
<%= link_to_if(@current_user.nil?, "Login", { :controller => "sessions", :action => "new" }) %>
==== Examples
in +link_to_unless+).
accepts the name or the full argument list for +link_to_unless+ (see the examples
returned. To specialize the default behavior, you can pass a block that
+options+ if +condition+ is true, in which case only the name is
Creates a link tag of the given +name+ using a URL created by the set of
def link_to_if(condition, name, options = {}, html_options = {}, &block) link_to_unless !condition, name, options, html_options, &block end
def link_to_unless(condition, name, options = {}, html_options = {}, &block)
# If not...
# => Reply
# If the user is logged in...
%>
end
link_to(name, { :controller => "accounts", :action => "signup" })
link_to_unless(@current_user.nil?, "Reply", { :action => "reply" }) do |name|
<%=
# => Reply
# If the user is logged in...
<%= link_to_unless(@current_user.nil?, "Reply", { :action => "reply" }) %>
==== Examples
accepts the name or the full argument list for +link_to_unless+.
than just the plaintext link text), you can pass a block that
returned. To specialize the default behavior (i.e., show a login link rather
+options+ unless +condition+ is true, in which case only the name is
Creates a link tag of the given +name+ using a URL created by the set of
def link_to_unless(condition, name, options = {}, html_options = {}, &block) if condition if block_given? block.arity <= 1 ? capture(name, &block) : capture(name, options, html_options, &block) else name end else link_to(name, options, html_options) end end
def link_to_unless_current(name, options = {}, html_options = {}, &block)
end
link_to("Go back", { :controller => "posts", :action => "index" })
link_to_unless_current("Comment", { :controller => "comments", :action => "new" }) do
<%=
"Go Back" link instead of a link to the comments page, we could do something like this...
action is the action given. So, if we had a comments page and wanted to render a
The implicit block given to +link_to_unless_current+ is evaluated if the current
def link_to_unless_current(name, options = {}, html_options = {}, &block) link_to_unless current_page?(options), name, options, html_options, &block end
def mail_to(email_address, name = nil, html_options = {})
:subject => "This is an example email"
mail_to "me@domain.com", "My email", :cc => "ccaddress@domain.com",
# => me_at_domain_dot_com
mail_to "me@domain.com", nil, :replace_at => "_at_", :replace_dot => "_dot_", :class => "email"
# => My email
mail_to "me@domain.com", "My email", :encode => "hex"
# =>
mail_to "me@domain.com", "My email", :encode => "javascript"
# => me@domain.com
mail_to "me@domain.com"
==== Examples
* :bcc - Blind Carbon Copy additional recipients on the email.
* :cc - Carbon Copy addition recipients on the email.
* :body - Preset the body of the email.
* :subject - Preset the subject line of the email.
string given as the value.
obfuscate the +email_address+ by substituting the . in the email with the
+email_address+ is used for the link label. You can use this option to
* :replace_dot - When the link +name+ isn't provided, the
given as the value.
obfuscate the +email_address+ by substituting the @ sign with the string
+email_address+ is used for the link label. You can use this option to
* :replace_at - When the link +name+ isn't provided, the
encode the +email_address+ before outputting the mailto link.
the page if the user has JavaScript disabled. Passing "hex" will hex
eval it into the DOM of the page. This method will not show the link on
Passing "javascript" will dynamically create and encode the mailto link then
* :encode - This key will accept the strings "javascript" or "hex".
==== Options
the email itself by passing special keys to +html_options+.
+mail_to+ has several methods for hindering email harvesters and customizing
HTML attributes for the link can be passed in +html_options+.
also used as the name of the link unless +name+ is specified. Additional
Creates a mailto link tag to the specified +email_address+, which is
def mail_to(email_address, name = nil, html_options = {}) email_address = html_escape(email_address) html_options = html_options.stringify_keys encode = html_options.delete("encode").to_s cc, bcc, subject, body = html_options.delete("cc"), html_options.delete("bcc"), html_options.delete("subject"), html_options.delete("body") extras = [] extras << "cc=#{Rack::Utils.escape(cc).gsub("+", "%20")}" unless cc.nil? extras << "bcc=#{Rack::Utils.escape(bcc).gsub("+", "%20")}" unless bcc.nil? extras << "body=#{Rack::Utils.escape(body).gsub("+", "%20")}" unless body.nil? extras << "subject=#{Rack::Utils.escape(subject).gsub("+", "%20")}" unless subject.nil? extras = extras.empty? ? '' : '?' + html_escape(extras.join('&')) email_address_obfuscated = email_address.dup email_address_obfuscated.gsub!(/@/, html_options.delete("replace_at")) if html_options.has_key?("replace_at") email_address_obfuscated.gsub!(/\./, html_options.delete("replace_dot")) if html_options.has_key?("replace_dot") string = '' if encode == "javascript" "document.write('#{content_tag("a", name || email_address_obfuscated.html_safe, html_options.merge("href" => "mailto:#{email_address}#{extras}".html_safe))}');".each_byte do |c| string << sprintf("%%%x", c) end "<script type=\"#{Mime::JS}\">eval(decodeURIComponent('#{string}'))</script>".html_safe elsif encode == "hex" email_address_encoded = '' email_address_obfuscated.each_byte do |c| email_address_encoded << sprintf("&#%d;", c) end protocol = 'mailto:' protocol.each_byte { |c| string << sprintf("&#%d;", c) } email_address.each_byte do |c| char = c.chr string << (char =~ /\w/ ? sprintf("%%%x", c) : char) end content_tag "a", name || email_address_encoded.html_safe, html_options.merge("href" => "#{string}#{extras}".html_safe) else content_tag "a", name || email_address_obfuscated.html_safe, html_options.merge("href" => "mailto:#{email_address}#{extras}".html_safe) end end
def options_for_javascript(options)
def options_for_javascript(options) if options.empty? '{}' else "{#{options.keys.map { |k| "#{k}:#{options[k]}" }.sort.join(', ')}}" end end
def url_for(options = {})
# if request.env["HTTP_REFERER"] is not set or is blank
<%= url_for(:back) %>
# => http://www.example.com
# if request.env["HTTP_REFERER"] is set to "http://www.example.com"
<%= url_for(:back) %>
# => http://www.example.com
<%= url_for("http://www.example.com") %>
# => /workshops/5
# calls @workshop.to_s
<%= url_for(@workshop) %>
# => /workshops
# relies on Workshop answering a persisted? call (and in this case returning false)
<%= url_for(Workshop.new) %>
# => /testing/jump/#tax&ship
<%= url_for(:action => 'jump', :anchor => 'tax&ship') %>
# => /messages/play/#player
<%= url_for(:action => 'play', :anchor => 'player') %>
# => https://www.railsapplication.com/members/login/
<%= url_for(:action => 'login', :controller => 'members', :only_path => false, :protocol => 'https') %>
# => /books/find
<%= url_for(:action => 'find', :controller => 'books') %>
# => /blog/
<%= url_for(:action => 'index') %>
==== Examples
+admin_workshop_path+ you'll have to call that explicitly (it's impossible for +url_for+ to guess that route).
a Workshop object will attempt to use the +workshop_path+ route. If you have a nested route, such as
you'll trigger the named route for that record. The lookup will happen on the name of the class. So passing
If you instead of a hash pass a record (like an Active Record or Active Resource) as the options parameter,
==== Relying on named routes
* :password - Inline HTTP authentication (only plucked out if :user is also present).
* :user - Inline HTTP authentication (only plucked out if :password is also present).
* :protocol - Overrides the default (current) protocol if provided.
* :host - Overrides the default (current) host if provided.
is currently not recommended since it breaks caching.
* :trailing_slash - If true, adds a trailing slash, as in "/archive/2005/". Note that this
* :only_path - If true, returns the relative URL (omitting the protocol, host name, and port) (true by default unless :host is specified).
* :anchor - Specifies the anchor name to be appended to the path.
==== Options
instead of the fully qualified URL like "http://example.com/controller/action".
:only_path is true so you'll get the relative "/controller/action"
documentation for ActionController::Base#url_for). Note that by default
same options as +url_for+ in Action Controller (see the
Returns the URL for the set of +options+ provided. This takes the
def url_for(options = {}) options ||= {} url = case options when String options when Hash options = options.symbolize_keys.reverse_merge!(:only_path => options[:host].nil?) super when :back controller.request.env["HTTP_REFERER"] || 'javascript:history.back()' else polymorphic_path(options) end url end
def url_options
end
controller.send(:default_url_options, *args)
def default_url_options(*args) #:nodoc:
Need to map default url options to controller one.
def url_options return super unless controller.respond_to?(:url_options) controller.url_options end