Flash message from controller: its html-code is displayed as text - html

In my controller, as part of the create method, I have a flash message:
flash[:success] = "An email was sent to #{#user.email}. Please check your inbox. <br> If you find this email in your junk mail folder, please mark the email as 'Not Junk'.".html_safe
The <br> in the middle however is displayed as text instead of that it processes it as html code and continues the text on a new line. This despite the use of html_safe at the end. Does anyone know what could be causing this and what to do about it?
Update: I tried it in other controller flash messages also. Just added <br> and html_safe to see how it would display and each time it caused problems. While in view pages, it doesn't generate any problems.
As requested the code that displays the flash messages (but even if I reduce this to just <%= message %> the problem still persists):
<% flash.each do |message_type, message| %>
<%= content_tag :div, class: "alert alert-#{message_type}" do -%>
<%= message %>
<button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<% end -%>
<% end %>

<%= message.html_safe %>
This will silently put all notices straight into html, so you don't really want to do this. You can do this if, and only if you are 100% sure, that your app never ever puts any user content in notices, or your app will be vulnerable to js injection attack. Instead try:
Flash message with html_safe from the controller in Rails 4 (safe version)
So yes, add before_filter -> { flash.now[:success] = flash[:success].html_safe if flash[:html_safe] && flash[:success] } to your ApplicationController, and than, any time you set html safe flash[:success] also set flash[:html_safe] to true, like
flash[:success] = "An email was sent to #{#user.email}. Please check your inbox. <br> If you find this email in your junk mail folder, please mark the email as 'Not Junk'.".html_safe
flash[:html_safe] = true
Edit: Yes, you can skip .html_safe at the end. You can make it more generic and remove unnecesary message like
before_filter -> {
if flash[:html_safe]
flash.delete(:html_safe)
flash.each do |k, message|
flash[k] = message.try(:html_safe)
end
end
}

Hopefully #nextstep reads this an undeletes his answer because he was spot on.
You need to do the .html_safe in the display of your flash message, not when you set them because in between those things the message will be serialized to the session and so will lose the html_safe flag.
I screwed up in my testing because I was setting and displaying the flash message in the same request (and so it hadn't been serialized/deserialized in between being set and displayed).
So, as #nextstep originally said (basically), change your view to:
<%= message.html_safe %>

Related

How can I display the action of a database-linked form with sinatra?

I have been working on a project in Ruby's Sinatra with ActiveRecord and MySQL and have ran into an error: part of my site is adding a link to the database and I want to show all of the links on the next page but for some reason I can not seem to find out how to express this.
This is what I have so far:
get '/dashboard' do
#site = Site.find_by text: params[:text]
#sites= Site.all
#newsite = Site.new ({:text => :text})
#user = User.find_by_id session[:user_id]
erb :dashboard
end
This is what ERB page looks like:
<% #sites.each do |site| %>
<h4><%=site.text.to_s%></h4>
<% end %>
How would I solve this? Now my form works but it does not show anything after
Your ERB code references a #sites attribute which you don't set in the controller.
If you set #sites in your ruby code to be an array of the Site records you want to show, then you should see something.

Rails div not rendering?

I have a simple app I'm following from a textbook. It's a store app and on the oft side of the page a shopping cart is shown. However, when the cart is empty it is supposed to be hidden. So I wrote a helper function to hide the cart whenever it is empty. This would have been east enough just to do in the html but it's how the book shows it. It works mostly. If I empty the cart it stops being displayed, but when I first open the page the cart will be invisible even if its not empty! Adding an item to it will then reveal it.
Here's the code:
application.html.erb
<div id="cart">
<% if #cart %>
<% hidden_div_if( #cart.line_items.empty?, id:"cart" ) do %>
<%= render #cart %>
<% end %>
<%end%>
</div>
application_helper.rb
module ApplicationHelper
def hidden_div_if(condition, attributes = {}, &block)
debugger
if(condition)
attributes["style"] = "display: none"
end
content_tag("div", attributes, &block)
end
end
Where I put the debugger statement, I checked the condition and it says it's false. So, I thin it's an issue with the html file. The controller sets the cart before hand with this code at the top.
include CurrentCart
before_action :set_cart
So, I'm not sure why it would show after a button is pressed but not on the initial page load. Any ideas?
thanks
You need to start with <%= in erb if you want to output the return value of a helper method. Change the line in which you call your helper method to:
<%= hidden_div_if(#cart.line_items.empty?, id: "cart") do %>

Using one '_form.html.erb' partial but have different elements appear for certain views

Is it possible to display certain elements within a partial for a particular view in Rails? For example I'd like the submit button's text to change depending on the view: so if I'm in the new.html.erb I'd like the submit button to appear as, <%= f.submit 'Create Account' %> and <%= f.submit 'Update Account' %> for edit.html.erb. The unconventional way would be to manually add the custom code into the each view but is there a clever way to do this in my _form.html.erb partial?
First of all, I would recommend putting it into the new and edit views. However, you can switch off of params[:action] if you want to. As in
<%= f.submit(((params[:action] == 'new') ? 'Create' : 'Update') + ' Account') %>
Use simple_form with i18n for that. SimpleForm make it automatically.
Example:
<%= simple_form_for(#message) do |f| %>
<%= f.error_notification %>
<%= f.input :title %>
<%= f.input :description %>
<%= f.button :submit, class: "btn btn-primary" %>
<% end %>
I second kdeisz's answer if your intention is to use a single partial. The line he wrote will not be necessary if you use two separate views - You can just use different names on the same button in each view without any need for conditional logic.
To answer your supplemental questions: There is a tradeoff here between future changeability and DRY code. If your new and edit needs will start to differ significantly, you will have a lot of bloated, difficult-to-change conditional logic in your partial if you use it to render major features.
If you keep the views separated, this may repeat a significant amount of code, but it will also make the individual pages easier to change; the functions of each view will be tailored very specifically to the needs of each HTTP verb.
The answer isn't to conform completely to REST or to DRY "just because", but to ask yourself what will result in more work down the road. If your new and edit pages will be basically the same but for a few very minor features, the single partial (DRY) is more practical. If you see them diverging significantly in the future, keep them separated into two views (less DRY but more changeable).
Params. Each request made to Rails will automatically include an action and a controller based on the route the user requests; for example, navigating to /foo/bar might trigger action bar for controller foo, depending on how you've set up config/routes.rb. Rails fills in params[:action] and params[:controller] with these automatically. A good explanation of how this works, and how to access path and request params, can be found here.

What is the difference between using rails form_tag and html form code in an erb file?

I had a problem with a rails app I am making. It is an e-commerce site, and on the page where the user enters their billing info, posting the form causing the cart information to be lost.
I solved the problem by changing the markup in the erb file. The first code for the form was:
<form method="post" id="checkout" action="<%= url_for :action => :place_order %>" >
<%= submit_tag "Place Order" %>
</form>
This didn't work, so I tried the following:
<% form_tag :method => 'post', :controller => 'checkout', :action => 'place_order' do %>
<%= submit_tag 'Place Order 2' %>
<% end %>
Does anyone know why the second piece of code does not cause the cart information to be discarded?
I was going to write this as a comment, but it's too long
Helpers
As a rule, you generally need to use the Rails helpers (of which form_tag is one) wherever possible.
The reason being that as Rails (& HTML) develops, you'll find that the helpers will adapt to keep up with current syntax, whereas using "naked" HTML will not. This not only keeps your application conventional, but DRY
By manually typing out an HTML form, you not only open yourself up to syntax change issues, but also you won't get any of the benefits that Rails-integration provides, such as CSRF protection
form_tag
A quick note on your form_tag
You've defined the route for the form_tag by using :controller & :action. You'd be much better using one of the route_helpers that will be defined in your Rails routes file:
#config/routes.rb
resources :checkout, path_names: { create: "place_order" }
This will allow you to use the following:
<%= form_tag checkout_place_order_path do %>
It must also be noted that the form_for tag will actually employ the :post method by default
--
Params
You mention the params for your item are not being passed using your standard form.
The reason for this is actually quite simple - Rails builds a params hash whenever you send data to the controller via an HTML form.
The issue you have is that if you define your form with "naked" HTML, those params will not be generated correctly (they are built from your form element names). This means if you want to send the correct data through to your application, you'll be much better suited to using one of the helpers, such as form_for (which is what you've now discovered)
form_for
As mentioned by DMKE, you may wish to use form_for. This is different than form_tag, as it relies on having an ActiveRecord object to work with. You'd have to do it like this:
#app/controllers/checkout_controller.rb
Class CheckoutController < ApplicationController
def new
#checkout = Checkout.new
end
def create
#checkout = Checkout.new(checkout_params)
#checkout.save
end
end
You can then populate a form_for with the following:
#app/views/checkout/new.html.erb
<%= form_for #checkout do |f| %>
Rails usually adds CSRF protection token in form of hidden fields into your HTML form, but only if you use the Rails helper methods. Compare this view
<% form_tag method: 'post', controller: 'checkout', action: 'place_order' do %>
<%= submit_tag 'Place Order 2' %>
<% end %>
with this rendered output:
<form accept-charset="UTF-8" action="/checkout/place_order" method="post">
<div style="display:none">
<input name="utf8" type="hidden" value="✓">
<input name="authenticity_token" type="hidden" value="q5PYT8i+XTlnoKeVqCoz8VMtKKSJP+CXQb/E+G0Vxlk=">
</div>
<input type="submit" name="submit" value="Place Order 2">
</form>
Now, to get your orginal form up and running, you can either insert this snippet into your <form> tag:
<%= hidden_field request_forgery_protection_token, value: form_authenticity_token %>
or you can disable CSRF protection (not recommended at all!):
# in your app/controllers/application_controller.rb
skip_before_action :verify_authenticity_token
You should at least read the Rails Security Guide on why disabling the CSRF protection is a bad thing.
N.B. Is there a reason why you don't use form_for?

Rails page has wrong html

I have a link to a page in the same folder as this page on my rails site:
<%= link_to 'Special Access', 'followers/special_access' %>
However, when I go to this page it shows a different page on that url.
<p id="notice"><%= notice %></p>
<div id="sent">
<p>Your request has been sent</p>
<%= link_to 'Home', followers_path %>
</div>
I tried deleting the page that the html is from, but first of all I need that page and it also gives me an error.
I edited the controller to contain:
def special_access
format.html { redirect_to followers/special_access }
format.json { render :json => #post }
end
instead of
def show
but that still didn't solve the problem.
How do I get the right html to show up on the right page?
If you do not define a route for special_access, rails will just assume the the special_acces part in the path is the :id of the route for the show page (as the urls look like followers/:id).
So first off, in your routes.rb, find the resources :followers and replace with the following:
resources :followers do
collection do
get :special_access
end
end
And now you should best always use the rails path helpers, so your link would become
<% link_to 'Special Access', special_access_followers_path %>
Here I was assuming the special access is on the collection of the followers, if it should be on a specific follower (which seems more logical to me, but I have no idea of course), you should write
resources :followers do
member do
get :special_access
end
end
And your link would become
<% link_to 'Special Access', special_access_followers_path(#follower) %>
I am not quite sure what you want to do in your controller action, I hope you just want to render an html page (because redirecting to the same url seems silly, and your syntax is wrong there too).
Hope this helps.