I have a controller like this in my project:

class BriefcasesController < ApplicationController
  ...

  def update
    @super_power = SuperPower.find(params[:super_power_id])
    @briefcase.contents.delete(params[:super_power_id].to_s)
    flash[:notice] = "Successfully removed #{view_context.link_to(@super_power.title, super_power_path(@super_power)} from your briefcase."
    redirect_back(fallback_location: '/briefcase'
  end

end

The link_to helper is not rendering a link to the browser, rather it's printing the html: Successfully removed <a href=\"/powers/1\>flying</a> from your briefcase. I've also tried using the method #html_safe on the flash message to no avail. I'm wondering if there's a way to fix this using view_context or if there's a better way to include a link inside a Flash message.

2

There are 2 best solutions below

6
max On BEST ANSWER

You need to use html_safe when outputting the flash messages - not when storing them.

<% flash.each do |key, msg| -%>
  <%= content_tag :div, msg.html_safe, class: name %>
<% end -%>

.html_safe just sets a flag on the string object that its trusted and should not be escaped.

The flash works by storing flash messages in the session storage - by default this means a cookie in the browser.

So when you do:

flash[:notice] = "foo"

You're storing the raw string "foo" in a cookie* and its unpacked back into the session on the next request. But the string is not the same Ruby object - so the html_safe flag on the string object is not persistent.

9
Max On

Note: the following only works with relatively old versions of Rails (confirmed in 4.0 and before, possibly in 4.1). Rails used to allow custom objects to be passed in flash messages, but later changed it to only allow primitive objects (documented at https://github.com/rails/rails/issues/15522).

You need to call html_safe on the entire string. Using string interpolation ("#{some_ruby_code}") changes the "safe" link_to string back into a regular string that gets escaped.