Return render partial and show flashes - ruby-on-rails

I have a partial with the functionality of "tell a friend about something".
And I want to let the user know if everything went ok so I return in my controller to show the flashes.
The problem is I can see the flashes via pry (debugger) but on screen nothing is shown.
As shown below:
Pry Results:
**IMPORTANT:**Tell a friend is a page that is opened when clicking on a link. The link opens an index page which opens a partial.
I've tried different things:
return render :index
render :index
redirect
...
The index.html.erb file:
<!doctype html>
<html lang="nl">
<head>
<meta charset="utf-8" />
<title><%= t("share.index.header") %></title>
<!--[if lt IE 9]><script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
<%= javascript_include_tag "application" %>
<%= stylesheet_link_tag "application", :media => "all" %>
<style>
body {
margin: 2em;
font: 14px/1em 'open-sans', sans-serif;
color: #333;
background: #eee;
}
h1 {
font-weight: normal;
color: #666;
}
p {
color: #666;
font-size: 12px;
margin: 0 0 3em 0;
}
p a {
color: #333;
text-decoration: none;
border-bottom: 1px dotted #666;
}
form {
position: relative;
}
.col-2 {
position: absolute;
top: 0; left: 25em;
}
label {
display: block;
margin: 0 0 2em 0;
}
strong {
font-weight: normal;
display: block;
margin: 0 0 .5em 0;
}
input[type=text] {
padding: 6px;
width: 25em;
border: 1px solid #ccc;
background: #fff;
}
input[type=submit] {
color: white;
font-size: 14px;
padding: .75em;
}
</style>
</head>
<body>
<div id="wrap">
<% if current_user %>
<%= render :partial => "signed_in_user" %>
<% else %>
<%= render :partial => "anonymous_user" %>
<% end %>
</div>
<script>
</script>
</body>
</html>
The signed_in_user partial:
<script type="text/javascript"charset="UTF-8">
$(document).ready(function() {
$( "#submitBtn" ).click(function() {
// Simple input Validation
var emailaddress = $( "#email").val();
if( !validateEmail(emailaddress)) {
$( "#validationerror").show();
return false;
};
});
function validateEmail($email) {
var emailReg = /^([\w-\.]+#([\w-]+\.)+[\w-]{2,4})?$/;
if ($email == '' ){
return false;
} else {
if( !emailReg.test( $email ) ) {
return false;
} else {
return true;
}
};
};
});
</script>
<!-- Why is this code not showing after return render -->
<!-- Why is this code not showing after return render -->
<!-- Why is this code not showing after return render -->
<p><%= flash[:notice] %></p>
<!-- Why is this code not showing after return render -->
<!-- Why is this code not showing after return render -->
<!-- Why is this code not showing after return render -->
<h1><%= t :header, :scope => [:share, :index] %></h1>
<p><%= t :link_to_page_html, :scope => [:share, :index], :link => link_to(truncate(job_url(params[:job_id]),length: 50, omission: '...'), job_path(params[:job_id])) %></p>
<%= form_tag(job_share_index_path(params[:job_id]), :method => "post", :id => "myform", :remote => true) do %>
<%= hidden_field_tag "guid", params[:job_id] %>
<div class="col-1">
<label>
<strong><%= t("share.index.name") %></strong>
<%= text_field_tag "fullname", "", :autofocus => "autofocus" %>
</label>
<label>
<strong><%= t("share.index.email") %></strong>
<%= content_tag(:p, t("share.index.valid_email") , :id => "validationerror", :class => 'small_label' , :style => "display: none;color: red; font-weight: bold;") %>
<%= text_field_tag "email", "", :placeholder => t("share.index.email_placeholder"), :id => "email" %>
</label>
</div> <!-- /.col-1 -->
<div class="col-2">
<label>
<strong><%= t("share.index.message") %></strong>
<%= text_area_tag "message", "", :style => "width: 370px; height: 175px;"%>
</label>
</div> <!-- /.col-1 -->
<%= submit_tag t("share.index.button"), :class => "medium button", :id => "submitBtn" %>
<% end %>
The share controller
class ShareController < ApplicationController
def index
render :layout => false
end
def create
Sap.tell_a_friend(params[:fullname], params[:message], params[:guid], params[:email], api_params_for_user)
# respond_to do |format|
# format.html { redirect_to(job_share_index_path) }
# format.js
# end
flash[:notice] ="test"
return render :index
end
end

flash is intended for messages that should be visible on the next action/page view/request. You are attempting to render the flash in the same action as you set it, that's not going to work.
You need to use flash.now to set the flash messages:
This method enables you to use the flash as a central messaging system in your app. When you need to pass an object to the next action, you use the standard flash assign ([]=). When you need to pass an object to the current action, you use now, and your object will vanish when the current action is done.
ie:
flash.now[:notice] ="test" # or flash.now.notice = "test"

Fetch your Flash like this:
<%= content_tag :div, flash[:notice] %>

So for starters I want to thank Zendist(Andreas Bjørn) and Jakob S.
I was thinking since it's only tell a friend function the only real validation that needs to happen is check email.
So instead of returning a flash message via rails I just return a message to the user via javascript if his email address is valid.
As shown here:
$( "#submitBtn" ).click(function() {
// Simple input Validation
var emailaddress = $( "#email").val();
if( !validateEmail(emailaddress)) {
$( "#validationerror").show();
return false;
} else {
$( "#validationnotice").text("hello world");
};
});
Thanks again for your input and help #greatcommunity!

Related

Rails 7 signup form doesn't show error messages

I am following a rails tutorial, in the signup form, if invalid user info is submitted, the signup page is supposed to be re-rendered with error messages, but actually it doesn't. It seems that even if the signup page is rendered by "render 'new'", the #user passed to it is empty. How to fix this?
Please note that the tutorial uses Rails 6 but I'm actually using Rails 7.0.2.3 with Ruby 3.1.1. Not sure if this is the cause.
app/controllers/users_controller.rb
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
else
render 'new'
end
end
def show
#user = User.find(params[:id])
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
end
app/views/users/new.html.erb
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_with(model: #user, local: true) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
<%= f.submit "Create my account", class: "btn btn-primary" %>
<% end %>
</div>
</div>
app/views/shared/_error_messages.html.erb
<% if #user.errors.any? %>
<div id="error_explanation">
<div class="alert alert-danger">
The form contains <%= pluralize(#user.errors.count, "error") %>.
</div>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
app/assets/stylesheets/custom.scss
#import "bootstrap-sprockets";
#import "bootstrap";
/* variables */
$gray-medium-light: #eaeaea;
/* mixins */
#mixin box_sizing {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
/* miscellaneous */
.debug_dump {
clear: both;
float: left;
width: 100%;
margin-top: 45px;
#include box_sizing;
}
/* universal */
body {
padding-top: 60px;
}
section {
overflow: auto;
}
textarea {
resize: vertical;
}
.center {
text-align: center;
h1 {
margin-bottom: 10px;
}
}
/* typography */
h1, h2, h3, h4, h5, h6 {
line-height: 1;
}
h1 {
font-size: 3em;
letter-spacing: -2px;
margin-bottom: 30px;
text-align: center;
}
h2 {
font-size: 1.2em;
letter-spacing: -1px;
margin-bottom: 30px;
text-align: center;
font-weight: normal;
color: $gray-light;
}
p {
font-size: 1.1em;
line-height: 1.7em;
}
/* header */
#logo {
float: left;
margin-right: 10px;
font-size: 1.7em;
color: white;
text-transform: uppercase;
letter-spacing: -1px;
padding-top: 9px;
font-weight: bold;
&:hover {
color: white;
text-decoration: none;
}
}
/* footer */
footer {
margin-top: 45px;
padding-top: 5px;
border-top: 1px solid $gray-medium-light;
color: $gray-light;
a {
color: $gray;
&:hover {
color: $gray-darker;
}
}
small {
float: left;
}
ul {
float: right;
list-style: none;
li {
float: left;
margin-left: 15px;
}
}
}
/* sidebar */
aside {
section.user_info {
margin-top: 20px;
}
section {
padding: 10px 0;
margin-top: 20px;
&:first-child {
border: 0;
padding-top: 0;
}
span {
display: block;
margin-bottom: 3px;
line-height: 1;
}
h1 {
font-size: 1.4em;
text-align: left;
letter-spacing: -1px;
margin-bottom: 3px;
margin-top: 0px;
}
}
}
.gravatar {
float: left;
margin-right: 10px;
}
.gravatar_edit {
margin-top: 15px;
}
/* forms */
input, textarea, select, .uneditable-input {
border: 1px solid #bbb;
width: 100%;
margin-bottom: 15px;
#include box_sizing;
}
input {
height: auto !important;
}
#error_explanation {
color: red;
ul {
color: red;
margin: 0 0 30px 0;
}
}
.field_with_errors {
#extend .has-error;
.form-control {
color: $state-danger-text;
}
}
Debug info of rails server when form submit button is clicked with invalid
Started POST "/users" for ::1 at 2022-04-06 00:55:04
Processing by UsersController#create as TURBO_STREAM
Parameters: {"authenticity_token"=>"[FILTERED]", "user"=>{"name"=>"foo123", "email"=>"foo123#asdf", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Create my account"}
TRANSACTION (0.0ms) begin transaction
↳ app/controllers/users_controller.rb:8:in `create'
User Exists? (0.1ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "foo123#asdf"], ["LIMIT", 1]]
↳ app/controllers/users_controller.rb:8:in `create'
TRANSACTION (0.0ms) rollback transaction
↳ app/controllers/users_controller.rb:8:in `create'
Rendering layout layouts/application.html.erb
Rendering users/new.html.erb within layouts/application
Rendered shared/_error_messages.html.erb (Duration: 0.4ms | Allocations: 403)
Rendered users/new.html.erb within layouts/application (Duration: 1.9ms | Allocations: 1891)
Rendered layouts/_shim.html.erb (Duration: 0.0ms | Allocations: 15)
Rendered layouts/_header.html.erb (Duration: 0.1ms | Allocations: 78)
Rendered layouts/_footer.html.erb (Duration: 0.1ms | Allocations: 51)
Rendered layout layouts/application.html.erb (Duration: 9.5ms | Allocations: 8695)
Completed 200 OK in 213ms (Views: 9.8ms | ActiveRecord: 0.2ms | Allocations: 11628)
In rails 7 forms are submitting as TURBO_STREAM by default. After submitting a form Turbo expects a redirect unless response status is in 400-599 range.
render :new # default status is 200
With status code 200 Turbo shows an error in the browser console and page doesn't re-render.
To make Turbo accept rendered html, change the response status. Default seems to be :unprocessable_entity (status code 422)
render :new, status: :unprocessable_entity
https://turbo.hotwired.dev/handbook/drive#redirecting-after-a-form-submission
https://github.com/hotwired/turbo/commit/4670f2b57c5d0246dfc0f6d10ff7d9a52a63fdca
Update: a note on "Content-Type". This applies to default form submission with turbo.
In this set up turbo is expecting an html response with Content-Type: text/html;. #puerile noted that omitting .html extension in your views also breaks the response.
Rails uses .html extension to set response content type to text/html. When extension is omitted content type is set to text/vnd.turbo-stream.html because the form is submitted as TURBO_STREAM, since our response doesn't have a <turbo-stream> it is the wrong content type.
>> Mime[:turbo_stream].to_str
=> "text/vnd.turbo-stream.html"
If we have a view views/users/new.erb, this will not work:
if #user.save
redirect_to #user
else
# NOTE: this will render `new.erb` and set
# `Content-Type: text/vnd.turbo-stream.html` header;
# turbo is not happy.
render :new, status: :unprocessable_entity
end
To fix it, use respond_to method:
respond_to do |format|
if #user.save
format.html { redirect_to #user }
else
# NOTE: this will render `new.erb` and set
# `Content-Type: text/html` header;
# turbo is happy.
format.html { render(:new, status: :unprocessable_entity) }
end
end
or set content type manually:
if #user.save
redirect_to #user
else
render :new, status: :unprocessable_entity, content_type: "text/html"
# NOTE: you can also set headers like this
headers["Content-Type"] = "text/html"
end
One caveat with the last set up is that the layout has to be without .html extension as well, otherwise, render :new will render new.erb without a layout and turbo won't be happy again. This is not an issue when using respond_to method.
https://api.rubyonrails.org/classes/ActionController/MimeResponds.html#method-i-respond_to
If you look at the logs you can see that Rails is getting an AJAX request in the form of a turbo stream:
Processing by UsersController#create as TURBO_STREAM
Where it should read:
Processing by UsersController#create as HTML
To disable turbo you want need to set a data-turbo="false" attribute on the form:
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_with(model: #user, data: { turbo: false }) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
<%= f.submit "Create my account", class: "btn btn-primary" %>
<% end %>
</div>
</div>
The local: false option only works with the old Rails UJS javascript library which was the default prior to Rails 7. You can also disable Turbo by default with:
import { Turbo } from "#hotwired/turbo-rails"
Turbo.session.drive = false
See:
https://turbo.hotwired.dev/handbook/drive#disabling-turbo-drive-on-specific-links-or-forms

Random text after rails loop

I created a loop to show all blog posts. I am getting an error that displays random text after the loop:
It looks like there's a stack of texts with all the post information listed at the end of the loop, I have no idea how it happened and how to fix it.
I checked my HTML and CSS, but couldn't figure out what caused the issue.
Below is the HTML and CSS code:
<section id="posts" class="wrapper">
<h2>My Latest Articles</h2>
<hr>
<div class="post_container">
<%= #posts.each do |p| %>
<div class="article">
<h3 class="post_title"><%= link_to p.title, p %></h3>
<p class="post_date"><%= p.created_at.strftime("%A,%b %d") %></p>
<p class="content"><%= truncate(p.content, length: 400) %></p>
</div>
<% end %>
</div>
<div class="button_wrapper">
More Articles
</div>
</section>
CSS
#posts {
padding: 6.5em 0 10em 0;
h2 {
text-align: center;
color: $text;
margin-bottom: 1.25rem;
}
.post_container {
padding: 6em 0 6em 0;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: flex-start;
.article {
max-width: 28%;
}
.post_title {
color: $text;
font-size: 1.6em;
}
.post_date {
padding: .75rem 0;
color: $accent;
font-size: 1.2em;
}
.content {
color: $grey;
}
}
}
<%= #posts.each do |p| %>
Should be
<% #posts.each do |p| %>
Do not output the result of .each.
Its because your using <%= at the beginning of your loop. You would use <% instead
Change the post_container div to this:
<div class="post_container">
<% #posts.each do |p| %>
<div class="article">
<h3 class="post_title"><%= link_to p.title, p %></h3>
<p class="post_date"><%= p.created_at.strftime("%A,%b %d") %></p>
<p class="content"><%= truncate(p.content, length: 400) %></p>
</div>
<% end %>
</div>
Use
<% #posts.each do |p| %>
because <= %> use for print the value in your case it'll print the whole loop

will paginate coming out reversed

I'm using will paginate on my ruby on rails app..I've used this before on other apps and it was working fine however when i used it on this one for some reason it looks like the tabs for the pagination are reversed.
Here's the html
<div class="container">
<br />
<br />
<h2 class="black">
Recent News
<div class="line_section"><div>
</h2>
<div class="row">
<div class="span12">
<ul class="recent-news">
<% #news_all.each do |news| %>
<li style="font-size: 16px; line-height: 19px; letter-spacing: 1px; font-size: 14px; color: #555; text-align: left;">
<%= image_tag news.photo.url, class: 'pull-left', style: 'margin-right:40px; margin-top: 2px; width: 300px;' %>
<div style=" width: 600px; float: right;">
<%= link_to news.title, news %>
<br />
<%= link_to news.date, news, style: 'font-size: 10px; color: black; position: relative; top: 15px;' %>
<br /><br />
<%= truncate news.content, length: 500 %>
<br />
<%= link_to 'Read More...', news, style: 'font-size: 12px !important;' %>
</div>
</li>
<% end %>
<%= will_paginate #news_all %>
</div><!-- end span12 -->
</div><!-- end row -->
</div><!-- end container -->
here's the controller
def batnews
#article = Article.first
#news_all = News.all
#news_all = News.paginate(page: params[:page]).limit(4)
#comments = Comment.all
end
here's the link to the site so you can see what's actually going on.
http://www.batman-fansite.com/batnews
if you scroll to the way bottom you will see the pagination.
Fix you css:
.recent-news li {
float: right;
}
add something like
.recent-news .pagination li {
float: left;
}
There are two problems here:
Display order is incorrect due to CSS float:right, causing elements to go right in order rendered, which results in backwards order left-to-right.
Using limit(4) on paginated set vs. per_page: 4 option in pagination.
Check your CSS, you'll find:
.recent-news li {
float: right;
}
...and your controller code should be:
#news_all = News.paginate(page: params[:page], per_page: 4)
Try something like this:
def index
#posts = Post.paginate :page => params[:page], **:order => "created_at ASC"**
end

Wicked_pdf working fine in development, but not in production

I've been working with wicked_pdf to generate some PDFs in Rails, and it's been working fine in my dev environment, but I get a 500 error (but no specific errors in my log) when I try and generate one on my production environment. The first thing I noticed was that the wkhtmltopdf binary was in a different location on my production box, so I've added the following to my wicked_pdf.rb initializer:
if Rails.env == "production"
WickedPdf.config = {
:exe_path => '/usr/bin/wkhtmltopdf'
}
end
Here's how I'm calling it in my controller:
def certificate
#inspection = Inspection.find(params[:id])
#council = Council.find(#inspection.councilid)
respond_to do |format|
format.pdf do
render :pdf => #inspection.slug,
:show_as_html => params[:debug].present?,
:margin => {:top => 0,
:bottom => 0,
:left => 0,
:right => 0}
end
end
end
And here's the contents of my view:
# certificate.pdf.erb
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style type="text/css">
body {
margin: 0;
padding: 0;
font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif;
}
img#bg {
width: 800px;
height: 1130px;
position: absolute;
}
#date p, #council p {
line-height: 17px;
font-size: 12px;
}
#council {
position: absolute;
top: 650px;
left: 445px;
}
#logo {
position: absolute;
top: 965px;
left: 98px;
}
#logo img {
height: 65px;
}
#address {
position: absolute;
top: 425px;
left: 300px;
}
#address p {
font-size: 22px;
line-height: 27px;
}
#date {
position: absolute;
top: 650px;
left: 98px;
}
</style>
</head>
<body>
<%= wicked_pdf_image_tag "certificate#{#inspection.rating}.jpg", :id => "bg" %>
<div id="address">
<p><%= #inspection.name %><br />
<%= #inspection.address("<br />").html_safe %> </p>
</div>
<div id="date">
<p><%= #inspection.date.strftime("%B %d %Y") %></p>
</div>
<div id="council">
<p><%= #council.address.html_safe %><br /><br />
<strong>Tel: </strong><%= #council.tel %></p>
</div>
<div id="logo">
<%= wicked_pdf_image_tag "certificates/#{#council.logo}.png" %>
</div>
</body>
</html>
When I add debug=true to the query string it seems to generate OK (and the wicked_pdf_image_tag helper seems to generate the correct location, which seemed to be a gotcha in Rails 3.1). Any ideas? I am pretty new to Ruby / Rails, so please be gentle!
Its much much much easier to do this if you let bundler worry about sourcing the dependency to wkthmltopdf. You can do that by installing this:
gem "wkhtmltopdf-binary"
and then running bundle install. After that you should be able to remove your custom exe_path specification and it should work correctly. If that doesn't work let me know.
Joe
If still image not showing in production environment then please try
image_tag wicked_pdf_asset_base64('image.png')
I'm using wicked-pdf as an attachment to the email. In development, it is working fine but in production, it shows
ActionView::Template::Error: uninitialized constant AssetCdnHosts
attachments["purchase_order.pdf"] = WickedPdf.new.pdf_from_string(
render_to_string(pdf: 'purchase_order', template: "device_orders/_preview_purchase_order.html.erb",locals: {vendor_info: vendor_info,device_order: device_order})
)

Rails help pre-populate data - Token input field

I am trying to pre-populate data to a token input field.
But nothing gets pre-populated in my edit view.
I have followed this railscast: http://railscasts.com/episodes/258-token-fields
My controller:
class Admin::TagsController < Admin::AdminController
layout 'admin'
def index
#title = 'asdsadas'
#kategoris = Tag.where("name like ?", "%#{params[:q]}%")
respond_to do |format|
format.html
format.json { render :json => #kategoris.map(&:attributes) }
end
end
end
My application.js:
// Place your application-specific JavaScript functions and classes here
// This file is automatically included by javascript_include_tag :defaults
$(function() {
$("#konkurrancer_tag_tokens").tokenInput("http://localhost:3000/admin/tags.json", {
crossDomain: false,
prePopulate: $("#konkurrancer_tag_tokens").data("pre"),
theme: "facebook"
});
});
My edit view:
<h1>Editing kategori</h1>
<%= simple_form_for(#konkurrancer, :url => {:action => 'update', :id => #konkurrancer.id }) do |f| %>
<%= f.input :tag_tokens, :label => 'Tags', "data-pre" => #konkurrancer.tags.map(&:attributes).to_json %>
<%= f.button :submit, :value => 'Edit konkurrence' %>
<% end %>
Token field output:
<div class="input string optional">
<label for="konkurrancer_tag_tokens" class="string optional"> Tags</label>
<ul class="token-input-list-facebook"><li class="token-input-input-token-facebook">
<input type="text" autocomplete="off" style="outline: medium none; width: 30px;">
<tester style="position: absolute; top: -9999px; left: -9999px; width: auto; font-size: 13.3333px; font-family: MS Shell Dlg; font-weight: 400; letter-spacing: normal; white-space: nowrap;"></tester></li></ul>
<input type="text" size="50" name="konkurrancer[tag_tokens]" id="konkurrancer_tag_tokens" class="string optional" style="display: none;"></div>
Try wrapping your data-pre with input_html in your edit view:
:input_html => {"data-pre" => #konkurrancer.tags.map(&:attributes).to_json }
* You're using simple_form while the railscasts isn't.

Resources