ruby on rails flash notice always appears - ruby-on-rails

I have a controller (not model related) which searches for stuff on YouTube via API. What I'm trying to achieve is simple enough...if someone clicks the search button when no string was entered then a flash notice will appear saying 'please enter search string'.
The 'main' view is as follows:
<%= form_tag({:controller => 'main', :action => 'index'}, :method => 'get') do %>
<%= label_tag(:text, 'Search:') %>
<%= text_field_tag(:text) %>
<%= submit_tag('Search') %>
<% end %>
<div id="flash">
<% if flash.now[:notice] %>
<p id="notice"><%= flash.now[:notice] %></p>
<% end %>
</div>
My index action in my 'main' controller looks like this:
def index
if params[:text].blank?
flash.now[:notice] = 'Please enter a search string'
render 'index'
else
#do searches on YouTube
end
I've looked at other question similar to this on stackoverflow as well and tried a few thing and still doesn't work. I've played around with using flash[] versus flash.now[] and still the notice message just sticks even when I first load the page. I might be missing something quite trivial here but I've spent a while figuring it out and still stuck. Anyway help would be appreciated.
UPDATE:
Ok, I have found an answer. I simply added the following in my form in the view:
<%= hidden_field_tag :searching, true %>
then i changed my controller to:
flash.now[:notice] = 'Please enter a search string' if params[:searching]
This worked fine. This is courtesy of the answer here:
How do I stop a flash error message from showing on page load until after button is clicked in ruby on rails?
FOLLOW UP QUESTION: in the link above, it suggested a cleaner answer which is to use:
params[:search].blank? && !params[:search].nil?
However, this doesn't work for me. I get the error:
undefined method `gsub' for nil:NilClass
I'm a newbie in Ruby so is this a syntactical error?

This may help, worth a try. In my case, my flash message was not shown because I was using
flash.now[:notice]
When changed to
flash[:notice]
started showing it.
Full code, controller:
def create
user_data = user_params
user_data[:password] = SecureRandom.uuid
#user = User.new(user_data)
#user.save
flash[:notice] = 'An email was sent for the user to confirm their account.'
respond_with(#user)
end
aaplication.html.erb
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= full_title(yield(:title)) %></title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
<%= render 'layouts/shim' %>
</head>
<body>
<%= render 'layouts/header' %>
<div class="container">
<% flash.each do |message_type, message| %>
<div id=<%= message_type %> class="alert"><%= message %></div>
<% end %>
<%= yield %>
<%= render 'layouts/footer' %>
</div>
</body>
</html>

Related

Display a string variable in view and change it when a view is rendered

I am trying to store a variable which will be changed when a view is rendered. It's a text in my header which tells me what page I am on (Home, register, login, etc). Here's an example:
Home (root of the website):
Register (/authentication/register)
I tried storing the variable in my base (root) view with <%= $header_title = "AppName" %> Like this:
My code (application.html.erb):
<%= $header_title = "AppName" %>
<!DOCTYPE html>
<html>
<head>
<title><%= t('app') %></title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
</head>
<body>
<header>
<%= render 'layouts/header.html.erb'%>
</header>
<main>
<%= yield %>
</main>
</body>
</html>
But when I do this, this happens to the document (AppName is just a placeholder):
I don't want it to put the string above the header in the document like that, instead I am just trying to store that variable and then use it in the header text.
Here's the "layouts/_header.html.erb"
<div id="header-body">
<div id="title-body" class="header-item-padding">
<p><%= $header_title %></p>
</div>
<div id="navigation-body" class="header-item-padding">
<%= isloggedin = false
if isloggedin == false
render 'layouts/header/navigationRegister.html.erb'
else
if userIsAdmin = false
render 'layouts/header/navigationUser.html.erb'
else
render 'layouts/header/navigationAdmin.html.erb'
end
end %>
</div>
</div>
Remove the entire line
<% headerTitle = "AppName" %>
and in layouts/header.html.erb
<div id="header-body">
<div id="title-body" class="header-item-padding">
<p><%= action_name.titleize %></p>
</div>
<div id="navigation-body" class="header-item-padding">
The variable action_name is available to you and you interpolate it here into something like "register". The .titleize action makes it more human readable like "Register". In the case of multi word controllers it will change something like "user_registration" into "User Registration" where .capitalize will give you "User_Registration".
Delete the <%= headerTitle = "AppName" %> and concentrate on the <%= render 'layouts/header.html.erb'%> instead.
Rails allows local variables, like so:
<%= render 'layouts/header.html.erb', locals: { x: :value_of_x } %>
So there is a nice global variable which is controller_name which resembles the name of the controller. You only need to capitalize it but rails has a method for this either, so in your case it would be:
<%= render 'layouts/header.html.erb', locals: { app_name: controller_name.capitalize } %>
And in your partial you can use app_name then. Like <span><%= app_name %></span> or whereever you need the name of the Controller.
I hope this helps.
Just remove the =.
<% headerTitle = "AppName" %>
Then the headerTitle won't be rendered in your page.
BTW by Ruby convention you should use camel case for variable names. So in your case header_title.
Happy coding :)

How to access data in rails from a view that was created in the controller?

I am trying to pass an instance variable from the controller to the view. Not sure what I am doing wrong since the view can create an instance and get data. I can also get data in the console. When I inspect the instance instantiated in the controller it is nil. I can't even pass a string. Can anyone spot my error?
Controller tries to set Test. I know its being called because if I delete the line
"render :layout => false" I can see the effects.
class ViewviewerimageController < ApplicationController
def index
render :layout => false
#Test = 'XXX'
end
end
And the view:
<!DOCTYPE HTML>
<html>
<head>
<%= stylesheet_link_tag "ERP" %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
<title>Image Data</title>
</head>
<body>
<%= render template: "layouts/header" %>
<%= render template: "layouts/sidebar" %>
<div id="content">
Test = <%= #Test %><br>
inspect = <%= #Test.inspect %><br>
</div>
<%= render template: "layouts/footer" %>
</body>
</html>
And what I get back is:
Test =
inspect = nil
I followed a few different tutorials but it seems they left out something and I can't seem to puzzle it out. I even deleted the CSS and javascript to see if they are interfering but just as I suspected, it wasn't them.
It is because you have the instance variable created after the render is called.
Try doing this
def index
#Test = 'XXX'
render layout: false
end

Using meta tags gem, how to render metas in content_for?

I'm having problems with this Gem, when using content for.
In my application.html.erb, I have the following:
<head>
<% if current_page?(root_path) %>
<meta name="description" content="My page">
<% else %>
<%= yield :description_meta %>
<% end %>
</head>
And then, in my views, I do the following:
<% content_for :description_meta do %>
<% set_meta_tags :description => "My description" %>
<% end %>
It wont paint any metas, and if I render it with <%=, it will show in the body of the page as normal text.
Any ideas? Thanks
Read MetaTags Usage.
Seems like set_meta_tags just configure meta tags and display_meta_tags render them.

Set a browser and page title for Devise pages?

I have methods that set a title for the browser and for the page itself. On my Devise pages I would like to set these two methods but am not sure how to.
My Code:
helpers/application_helper
def title # for entire application
base_title = "Testing"
if #title.nil?
base_title
else
"#{base_title} - #{#title}"
end
end
def page_title # for page header partial
"#{#page_title}"
end
views/layouts/application
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<%= csrf_meta_tag %>
<%= favicon_link_tag %>
<%= stylesheet_link_tag "application" %>
<%= javascript_include_tag "application" %>
</head>
<body>
<div id="container">
<%= render "shared/page_header" %>
<%= render "shared/flash_message" %>
<%= yield %>
</div>
</body>
</html>
views/shared/_page_header
<% unless #page_title.blank? %>
<div id="page-header">
<span><%= #page_title %></span>
</div>
<% end %>
Now I have a RegistrationsController to override the functionality whenever I need to but as it inherits to the DeviseController, I don't think it can get to the Application Helper? I also tried to put this same code in the Registration Helper but that didn't work either. What should I do?
Maybe you can use;
application_helper.rb
module ApplicationHelper
def title(page_title)
content_for(:title) { page_title }
end
end
application.html.erb
<title><%= yield :title %></title>
view
<%= title "Your page title here" %>

Rails render partial without entire html layout

Ok so I have a problem with rails and rendering partials. I have a layout called profile and inside of the profile layout I have all my js, stylesheets, etc included.
<html>
<head>
<title>Profile</title>
<%= javascript_include_tag "https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" %>
<%= javascript_include_tag "https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.10/jquery-ui.min.js" %>
<%= javascript_include_tag "application" %>
<%= stylesheet_link_tag "main" %>
<%= stylesheet_link_tag "reset" %>
<%= csrf_meta_tag %>
</head>
<body>
<%= yield %>
</body>
</html>
Inside of the yield tag(profile/index.html.erb) above is the following
<%= render :partial => 'pages/page', :layout => "layouts/default", :locals => {:page => #page } %>
Now in the pages/page view there are the same default tags such as css and js files. When i remove the css styles then I lose the styling for the pages/page view. Is there a way I can render a partial without recalling the same css and js files or what is a better way to go about doing something like so?
I always create the option to overwrite the stylesheets as follows:
<%= stylesheet_link_tag content_for?(:stylesheets) ? yield(:stylesheets) : "application", :debug => Rails.env.development? %>
Then inside a view
<% content_for :stylesheets %> some stuff or nothing in here <% end %>
That will let you specify in a view rendered in a layout you want no stylesheets and the same principle applies for javascripts.
That having been said if you are rendering a partial inside a layout that has an html tag and head etc. you should probably investigate if there is a better way to do what you are doing.
You need to pick one or the other: layout the original method call, or pass a layout to the partials. Doing both would be illogical.
There is a more thorough discussion here:
http://www.mikemayo.org/2012/rendering-a-collection-of-partials-with-content_for
I rarely see the usage of( or I am wondering if Rails support this usage... )
<!-- confirmed, this usage will cause error in Rails 3.2 -->
<%= render :partial => "some_partial", :layout => "some_layout" ... %>
I prefer to choose the specific layout in the controller:
def some_action
# some code
render :layout => "some_layout"
end
A partial is basically just a "slice of page" (like slice of cake... but in code form). It's designed to populate a small part of the page; typically one which will by dynamically updated depending on page variables.
Seems like you're confusing the purpose of layouts, views & partials in my opinion. If you want to dynamically load CSS / JS, put a "content_for" block in the profile views with a default layout, like this:
Layout
#layouts/default.rb
<html>
<head>
<title>Site Title</title>
<%= javascript_include_tag "https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" %>
<%= javascript_include_tag "https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.10/jquery-ui.min.js" %>
<%= javascript_include_tag "application" %>
<%= stylesheet_link_tag "main" %>
<%= stylesheet_link_tag "reset" %>
<%= yield :header_includes %>
<%= csrf_meta_tag %>
</head>
<body>
<%= yield %>
</body>
</html>
Views
#views/profiles/index.html.erb
<% content_for :header_includes do %>
<%= stylesheet "profile_custom_css" %>
<% end %>
Partial
Partials could be used to keep your code DRY & give the output of specific header files, like this:
Partial
#views/elements/_custom_header.rb
<% content_for :header_includes do %>
<% headers.each do |type, value| %>
<% if type == "java" %>
<%= javascript_include_tag value %>
<% else %>
<%= stylesheet_link_tag value %>
<% end %>
<% end %>
<% end %>
View
#views/profiles/index.html.erb
<%= render :partial => 'elements/custom_header', locals: { :headers => [["java", "profile_custom"], ["stylsheeet", "profile_custom"]] } %>
#Resume standard view code here
Layout
#layouts/default.rb
<html>
<head>
<title>Site Title</title>
<%= javascript_include_tag "https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" %>
<%= javascript_include_tag "https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.10/jquery-ui.min.js" %>
<%= javascript_include_tag "application" %>
<%= stylesheet_link_tag "main" %>
<%= stylesheet_link_tag "reset" %>
<%= yield :header_includes %>
<%= csrf_meta_tag %>
</head>
<body>
<%= yield %>
</body>
</html>
I've not tested passing the partial locals as a hash, so the syntax may be incorrect, but this is what we'd do to load up the required code. The added benefit is that content_for only yields content that has been defined (I.E you just have to include yield :custom_headers and it will only show if the content block is present)

Resources