44

I am learning Ruby and Rails.

I have a Ruby on Rails project that tracks jobs a server is running. Right now, when I manually create a new job, it announces:

flash[:notice] = "Created job job number #{update.id}."

I would like to turn the #{update.id} into a link to the job on the job list.

The URL for going to the job is jobs/list?job=1234 where 1234 is the update.id that is displayed in the flash notice.

Is it possible to put a link into a flash[:notice] statement? Or do I need to re-work how this message is being displayed in order to turn it into a link?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
David Oneill
  • 12,502
  • 16
  • 58
  • 70
  • If you've tried all the methods below and it's *still* not working... You need to mark the message as safe (with `html_safe`) when you render it, not when you store the message! – Dennis Feb 26 '16 at 15:06

8 Answers8

42

Don't forget to add .html_safe at the end of the notice, if you're using Rails3. So it would say flash[:notice] = "Your message".html_safe

Kirill
  • 3,667
  • 4
  • 30
  • 35
39

The @template instance variable is no longer available in Rails 3.

Instead you can use this in your controller:

flash[:notice] = "Successfully created #{view_context.link_to('product', @product)}.".html_safe

Hope this helps :)

Dorian
  • 2,571
  • 23
  • 33
  • 4
    This is great thanks - surely it's better to use link_to instead of typing out the HTML in a string! Also I think you still have to do Kirill's .html_safe at the end. – jackocnr Nov 16 '12 at 16:17
  • 11
    @user664833 you still need `.html_safe` at the end in Rails 4, just tried it out. – tirdadc Jul 07 '14 at 01:02
  • 4
    Works in Rails 5.0, but you must be `.html_safe` in the flash notice in the actual view in ADDITION to putting it in the controller. – the12 Jun 27 '17 at 04:27
35

I may be missing something obvious, but you should just be able to do

flash[:notice] = %Q[Created job number <a href="/jobs/list?job=#{update.id}">#{update.id}</a>]

and then just make sure you're not escaping the content of the flash when you display it in your view.

Emily
  • 17,813
  • 3
  • 43
  • 47
  • 9
    You can avoid unsightly backslash escape using `%Q[]` or other equivalent delimiters `()[]{}<>` to denote a string: `%Q[Created job number #{update.id}]` – fny Jul 29 '12 at 05:26
  • According to [this guy](https://groups.google.com/forum/#!topic/rubyonrails-core/z52zgDgUmbs) this will not work in rails 4.1. I haven't been able to get it working either. – kingsfoil Oct 23 '14 at 22:00
  • 6
    Got it working in Rails 4.1 here: http://stackoverflow.com/questions/26538891/flash-message-with-html-safe-from-the-controller-in-rails-4 – kingsfoil Nov 11 '14 at 21:41
16

As nas commented, link_to is not available from your controller unless you include the appropriate helper module, but url_for is. Therefore I'd do pretty much what Emily said except use url_for instead of hardcoding a URL.

e.g. if a job were defined as a resource in your routes:

link = "<a href=\"#{url_for(update)}\">#{update.id}</a>"    
flash[:notice] = "Created job number #{link}"
mikej
  • 65,295
  • 17
  • 152
  • 131
  • 1
    When I do this I get text that says instead of a hyperlink. – jcollum Dec 01 '11 at 00:51
  • 4
    @jcollum Am guessing you're using Rails 3.x where HTML is escaped by default so you need to either use the `raw` method e.g. `<%=raw(flash[:notice])%>` in your view or mark the message as `html_safe` as given in [Kirill's answer](http://stackoverflow.com/a/5542265/63034). – mikej Dec 01 '11 at 10:50
  • 1
    yes, I tried putting #{thing.html_safe} but learned that you have to put the html_safe at the end of the whole string, not in the #{} subst. – jcollum Dec 01 '11 at 15:39
  • @jcollum That's right. If you put a safe string as a substring inside a non-safe string then the resulting string is non-safe (which is what you'd expect). So it is the whole message that must be marked as safe to prevent your HTML being escaped. – mikej Dec 01 '11 at 17:13
  • ActionController url_for is deprecated or moved on the latest stable version. – Sean M May 30 '13 at 17:00
9

The selected answer didn't work for me. But the answer from this post worked. I'm using Rails 4.2.4 by the way. With guidance from the answer I linked, here's how I did it:

View

<% flash.each do |name, msg| %>
  <div class="alert alert-<%= name %>">
    <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
    <div id="flash_<%= name %>"><%= sanitize(msg) %></div>
  </div>
<% end %>

Controller

flash[:success] = "Blah blah. #{view_context.link_to('Click this link', '/url/here')}"

The magic is the sanitize method.

I didn't need to use .html_safe as well.

Community
  • 1
  • 1
SamuelDev
  • 1,112
  • 10
  • 14
5

Building on Dorian's answer, here's an internationalized flash with a link in it:

flash[:notice] = t('success', go: view_context.link_to(t('product'), @product)).html_safe

Where your translation (e.g. a YAML file) might contain:

en:
  success: "Successfully created a %{go}"
  product: "product"
it:
  success: "%{go} creato con successo"
  product: "Prodotto"
Giuseppe
  • 5,188
  • 4
  • 40
  • 37
4

You can use an alias in your controller to the link_to function, or the RailsCast recipe:

"Created job job number #{@template.link_to update.id, 
  :controller => 'jobs', :action => 'list', :job => update.id}."

http://railscasts.com/episodes/132-helpers-outside-views

nanda
  • 1,313
  • 9
  • 16
1

You can always use the Rails link_to helper:

flash[:notice] = "Created job job number #{link_to update.id, :controller => 'jobs', :action => 'list', :job => update.id}."
mattwindwer
  • 929
  • 9
  • 18
  • 7
    I dont think link_to is going to work in controller unless you include the helper modules in your controller but then that will be polluting namespace. – nas Feb 12 '10 at 06:39