How do I change notice & alert's class? - ruby-on-rails

I'm trying to adjust the standard application template in Rails to insert a class around the notice and alert messages, but I can't seem to find an elegant way of doing it.
At present, I have the scaffold:
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
I want it to only show the surrounding tags if a notice or alert is present.

Use an if statement.
<% if notice %>
<p class="notice"><%= notice %></p>
<% end %>

<% flash.each do |name, msg| %>
<%= content_tag :div, :id => "flash_#{name}", :class => "my_class" do %>
<%= msg %>
<% end %>
<% end %>
Define styling for the .my_class

Wrap the parts in if like this:
<% if alert %>
<p class="alert"><%= alert %></p>
<% end %>
You can also use unless if you like

Related

Syntax error in <%= if flash[:notice]%> Ruby on Rails

The probleming code:
<%= if flash[:notice] %>
<div class="notification is-primary global-notification">
<p class="notice"><%= notice %></p>
</div>
<% end %>
<%= if flash[:alert] %>
<div class="notification is-danger global-notification">
<p class="alert"><%= alert %></p>
</div>
<% end %>
And when running my server the following error drops:
Already changed the syntax to: if (flash[:notice]). But still, drop this. Any idea?
<%= if flash[:notice] %>
The above code should be:
<% if flash[:notice] %>
Note
<% %> - Executes the ruby code within the brackets.
<%= %> - Prints something into ERB file.

Show Rails errors, notices and devise messages in one place

I have my application.html.erb file where this code located:
<% if notice %>
<p class="notice"><%= notice %></p>
<% elsif alert %>
<p class="alert"><%= alert %></p>
<% end %>
<%= devise_error_messages! %>
All is great, but form validations are made by using (as usual), this:
<%= form_for #project do |f| %>
<% if #project.errors.any? %>
<h2><%= pluralize(#project.errors.count, "error") %> prevented this project from saving:</h2>
<ul>
<% #project.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
...
<% end %>
How to include them into main app page & show them always in top?
How to include them into main app page & show them always in top?
This is deeper than just adding a partial (as Umang Raghuvanshi suggested).
The problem is that the errors method is part of an #object, which means you have to make sure you're able to access this object whenever you want to output the errors in application.html.erb.
Partials should never be dependent on #instance_variables - they're meant to be loaded in any part of your app. You can pass local variables to them, allowing you to send predefined data as you need.
In your case, I would use a partial but populate it with a content_for:
--
This is what I'd do:
#app/views/layouts/application.html.erb
<%= render partial: "shared/errors" %>
#app/views/shared/_errors.html.erb
<%= content_tag :div, class: "errors" do %>
<% if errors.try?(:any?) %>
<% errors.full_messages.each do |msg| %>
<%= content_tag :li, msg %>
<% end %>
<% else %>
<% flash = %w(notice error alert) %>
<% flash.each do |f| %>
<%= content_tag :div, class: f, flash => [f.to_sym] if flash[f.to_sym] %>
<% end %>
<%= devise_error_messages! %>
<% end %>
<% end %>
#app/views/projects/new.html.erb
<%= form_for #project do |f| %>
<%= render "shared/errors", locals: {errors: #project.errors} %>
<% end %>
This will allow you to style the .errors div to be absolutely position at the top:
JSFiddle
#app/assets/stylesheets/application.css
.errors {
display: inline-block;
width: 50%;
position: absolute;
top: 5%;
}
Extract the code into a partial and include it into your application.html.erb.
_your_partial_name.erb
<% if #project.errors.any? %>
<h2><%= pluralize(#project.errors.count, "error") %> prevented this project from saving:</h2>
<ul>
<% #project.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
application.html.erb
<%= render partial: 'your-partial-name' %>
<% if notice %>
<p class="notice"><%= notice %></p>
<% elsif alert %>
<p class="alert"><%= alert %></p>
<% end %>
<%= devise_error_messages! %>
You could also try using flash.

Rendering a partial inside a block

I'm new to rails. I have this block in my view afrikaans.html.erb
<% #afrikaans.each do |course| %>
<div class="course">
<h3 class="course-name"><%= link_to course.name, course.url %></h3>
<% if I18n.locale == I18n.default_locale %>
<p class="course-description_en"><%= course.description_en %></p>
<% else %>
<p class="course-description_se"><%= course.description_se %></p>
<% end %>
<% if course.youtube_url.blank? == false %>
<p><%= raw ApplicationHelper.youtube_embed(course.youtube_url) %></p>
<% end %>
<% if course.language_id == 1 %>
<p> <%= image_tag("eng.png", :alt => "England", :class =>"round") %></p>
<% else %>
<p> <%= image_tag("swe.png", :alt => "Sweden", :class =>"round") %></p>
<% end %>
<% if ApplicationHelper.active_link?(course.url) == false %>
<td><%= I18n.t('home.broken_link') %></td>
<% end %>
<p><%= course.nbr_of_votes %> <%= I18n.t('home.votes') %></p>
</tr>
<% end %>
I also have another file swahili.html.erb with the same structure. I wanted to implement something like this
afrikaans.html.erb
<% #afrikaans.each do |course| %>
<%= render 'shared/partial' %>
<% end %>
So that I can also have
swahili.html.erb
<% #swahili.each do |course| %>
<%= render 'shared/partial' %>
<% end %>
The partial will contain the part of the block. I've tried this but it's not working. My question is this even possible in rails and if so what could be the problem. What options do I have if it isn't possible so that I can avoid the repetition since the two files have the same structure?
Update. This One worked out for me. I only needed to add :course => course on the block so that my views becomes something like
<% #afrikaans.each do |course| %>
<%= render 'shared/course_body', :course => course %>
<% end %>
Of course I've not named my partial "partial". This was just a matter of asking. Thanks to one #Alexander Panasyuk's answer.
Just create shared directory within your app/views path. And create file _partial.html.erb inside shared:
<div class="course">
<h3 class="course-name"><%= link_to course.name, course.url %></h3>
<% if I18n.locale == I18n.default_locale %>
<p class="course-description_en"><%= course.description_en %></p>
<% else %>
<p class="course-description_se"><%= course.description_se %></p>
<% end %>
<% if course.youtube_url.blank? == false %>
<p><%= raw ApplicationHelper.youtube_embed(course.youtube_url) %></p>
<% end %>
<% if course.language_id == 1 %>
<p> <%= image_tag("eng.png", :alt => "England", :class =>"round") %></p>
<% else %>
<p> <%= image_tag("swe.png", :alt => "Sweden", :class =>"round") %></p>
<% end %>
<% if ApplicationHelper.active_link?(course.url) == false %>
<td><%= I18n.t('home.broken_link') %></td>
<% end %>
<p><%= course.nbr_of_votes %> <%= I18n.t('home.votes') %></p>
</tr>
Then render your partial in afrikaans.html.erb like that:
<% #afrikaans.each do |course| %>
<%= render 'shared/partial', :course => course %>
<% end %>
or in swahili.html.erb:
<% #swahili.each do |course| %>
<%= render 'shared/partial', :course => course %>
<% end %>
It is most definitely possible, and usually a good idea.
In the future it would be nice if you could post the actual results and/or error messages you get, which would help a lot when trying to help you.
That said, I'm guessing you need to pass the course variable to your partial. Change
<%= render 'shared/partial' %>
to
<%= render 'shared/partial', :course => course %>
Partials do not have access to local variables in other partials. In that sense you can think of each partial as separate methods on the same object instance.
<%= render 'shared/partial', locale: 'swahili', course: course %>
You will have local vars 'locale' and 'course' in your partial set to 'swahili' and #course, respectively. Also, I'd advise to name your partials something more meaningful, like 'course'.

Best practice method of displaying flash messages

I'm wondering what's the best practice for displaying flash messages. The two main ways I've seen are using something like this scaffold generated code
<p id="notice"><%= notice %></p>
or placing code like this in your application header.
<% if !flash.empty? %>
<div id="flash">
<% flash.keys.each do |k| %>
<div class="<%= k %>">
<%= flash[k] %>
</div>
<% end %>
</div>
<% end %>
It appears to me that the first method adds more flexibility while the latter improves code readability and eliminates redundancy. Is there a method most rails developers prefer? As a side question how does scaffolding implement notice? Is it just a helper that accesses the flash hash? Why go through the trouble of using the helper when you can directly use the flash hash? Thanks
I'm doing it this way:
<% flash.each do |key, value| %>
<%= content_tag :div, value, class: "flash #{key}" %>
<% end %>
Calling a partial keeps your application.html.erb even cleaner..
<%= render 'shared/flash_messages' if !flash.empty? %>
.. and in the partial do something like what #zolter mentioned:
<div id="flash_messages">
<% flash.each do |key, value| %>
<%= content_tag(:div, value, :class => "flash #{key}") %>
<% end %>
</div>
Why not put the second method on a helper function so it doesn't affect code readability on layouts?
<% if flash[:notice] %>
<div class="notification is-primary global-notification">
<p class="notice"><%= notice %></p>
</div>
<% end %>
<% if flash[:alert] %>
<div class="notification is-danger global-notification">
<p class="alert"><%= alert %></p>
</div>
<% end %>

Only show non blank attributes for a model in views in Rails

Say I've a user model and there are bunch of user info, like email, birthdate, location, telephone number etc.
What's the simplest way of hiding the attributes that are blank?
I've doing something like
<% if blog.title.empty? -%>
<p>Body: <%=h blog.body %></p>
<p>Comments: <%=h blog.comments %></p>
<% elsif blog.body.empty? %>
<p>Title: <%=h blog.title %></p>
<p>Comments: <%=h blog.comments %></p>
<% else -%>
<p>Title: <%=h blog.title %></p>
<p>Body: <%=h blog.body %></p>
<% end -%>
Clearly that is one ugly child. Other than using partials to render, is there a trick to only show non blank fields?
I've been trying to write a helpher method to make the view cleaner, but that's even more ugly.
Any help is appreciated.
I would do it like this:
# blog_helper.rb
show_non_blank_field(label, value)
"<p>#{label}: #{h value}</p>" if !value.blank?
end
and then in view:
<%= show_non_blank_field "Body", blog.body %>
and so on...
Of course you can use shorter helper name.
If you want to do it in if-else way, try this:
<% if !blog.title.blank? -%>
<p>Title: <%=h blog.title %></p>
<% end %>
<% if !blog.body.blank? %>
<p>Body: <%=h blog.body %></p>
<% end %>
<p>Comments: <%=h blog.comments %></p>
show_field_unless_empty(blog, :body, 'Body')
then, in blog_helper.rb
def show_field_unless_empty(model, field, title)
render :partial => 'field', :locals => {:value => model.send(field), :title => title} if model.send(field)
end
then, in _field.html.erb
<p>
<%= title %>:
<%= value %>
</p>
This seems fairly clean to me.

Resources