Validation error message without brackets - ruby-on-rails

On my view, I want to show an error message for each field of my form, below each form field. So Im doing something like this:
<% if #event.errors.full_message(:date, #event.errors[:date]) %>
<div class="alert alert-danger alert-dismissible fade in" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Fechar"><span aria-hidden="true">×</span></button>
<%= #event.errors.full_message(:date, #event.errors[:date]) %>
</div>
<% end %>
But the message is coming with brackets and the name of the attribute. I don't want to do an each at the top of the form to show all error messages at the same time. I want to show each error for each input on the form. How do I do that, without brackets and the name of the attribute on the message?

Use brackets [] to retrieve related errors for a field:
In your case:
<% if #event.errors[:date] %>
<div class="alert alert-danger alert-dismissible fade in" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Fechar"><span aria-hidden="true">×</span></button>
<%= #event.errors[:date].join('. ') %>
</div>
<% end %>

#event.errors and is an instance of ActiveModel::Errors, which allows you to use [] to retrieve errors for an attribute. You can also use get in the same way, e.g. #event.errors.get(:some_attribute).
#event.errors[:some_attribute] returns an array of errors on the attribute passed. If you want the full messages, you can use #event.errors.full_messages_for(:some_attribute), which will also return an array.
Your view should check for errors on the attribute like this:
#event.errors.has_key?(:some_attribute)
And you should either iterate over the errors to display them one by one:
#event.errors[:some_attribute].each do |error|
content_tag :span, error, class: 'error'
end
Or join them into a single string or sentence:
#event.errors[:some_attribute].to_sentence
Or show just the first/last of them:
#event.errors[:some_attribute].first

Related

Rails Helper create unintended Array ouput

I have created a rails helper method, So far so good the only problem is it created an unexpected array ouput.
I did try the key value pair using the each method but the array still there.
I'm trying to figure it out how to remove the unexpected array
My application_helper.rb
def bid_items(origin, destination)
item = Item.where(item_deliver_from: origin).where(item_deliver_to: destination).where(shopper_id: current_user)
end
My search_results.html.rb
<%= bid_items(trip.origin, trip.destination).each do |item| %>
<div class="card border-0">
<%= image_tag item.cover_image_url(:cover_image_medium), class: "card-img-top" %>
<div class="card-body">
<h5 class="card-title"><%= item.name %></h5>
</div>
</div>
<% end %>
Though I got the intended results still, there's an unexpected array
check the image
I just want to remove this area
See Red X
Remove = sign from <%= bid_items(trip.origin, trip.destination).each do |item| %>
So, make it <% bid_items(trip.origin, trip.destination).each do |item| %>

dynamic bootstrap tabs with rails

I am trying to get rails to generate dynamic navigation tabs that refer to groups user is enrolled at. Basically, what I want to achieve is to dynamically have tabs named after groups that user is enrolled at (which is working fine) and then showing the content of each group by clicking on its tab (which is not working properly for some reason). The page loads data correctly but toggling between tabs doesn't work
Here is the code in the view
<div class="tabbable tabs-left">
<div class="row">
<div class="col-md-4">
<ul class="nav nav-pills nav-stacked">
<% current_user.group.each do |group| %>
<li><a href="#<%= group.name %>" data-toggle="tab">
<%=group.name %></a></li>
<% end %>
</ul>
</div>
<div class="col-md-8">
<div class="tab-content">
<% current_user.group.each do |group| %>
<div class="tab-pane fade <%= 'in active' if current_user.group.first == group %>" id="<%=group.name%>">
<% if current_user.group_feed(group.id).any? %>
<ol class="microposts">
<%= render current_user.group_feed(group.id) %>
<%= group.name %>
</ol>
<% end %>
</div>
<% end %>
</div>
</div>
</div>
</div>
Is there something that I am missing?
The problem is group.name producing an invalid html id attribute.
html ids should not start with a number(numbers anywhere else are ok), and have no spaces. Example:
Invalid:
1foo
aaa b
Valid:
foo1
aaa-b
group.name.parameterize will remove any odd chars(#£$ etc) and replace spaces with "-" so use that.
You also want to make this unique as things with names like: "foo" and "foo!" will parameterize to the same thing: "foo".
I'd go with:
id="<%=(group.name.gsub(/[0-9]+/, "")+group.id.to_s).parameterize%>"
This code, removes any number from the name(it only really applies at the start of the id) then adds the id on the end making it unique.

how to customize devise error messages with classes

im using twitters bootstrap alert messages. in my application.html.erb I have...
<% flash.each do |key, value| %>
<div class="alert alert-<%=key%>">
<a class="close" data-dismiss="alert">×</a>
<%= value %>
</div>
<% end %>
normally when I want to do a flash message, I would write something like
flash[:success] = "Profile updated"
however im not sure how I can give the devise error messages a key and value pair. I looked into the devise.en.yml but can't seem to associate the message with a key ie :success, :error etc.
could someone help? thanks!
For anyone coming across this that does not know how to override the devise error messages with bootstrap.
Create file named:
/app/helpers/devise_helper.rb
Add the following code:
module DeviseHelper
def devise_error_messages!
return '' if resource.errors.empty?
messages = resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
sentence = I18n.t('errors.messages.not_saved',
count: resource.errors.count,
resource: resource.class.model_name.human.downcase)
html = <<-HTML
<div class="alert alert-error alert-block"> <button type="button"
class="close" data-dismiss="alert">x</button>
<h4>#{sentence}</h4>
#{messages}
</div>
HTML
html.html_safe
end
end
This is how i do it
<% flash.each do |key, value| %>
<div class="message">
<div class="alert-message <%= key %> fade in">
<a class="close" href="#">&times</a>
<center><strong><%= value %></strong></center>
</div>
</div>
<% end %>
The simplest solution I've found is to use a common partial for all flash messages while checking for :notice and :alert to replace with the necessary bootstrap class.
So make /views/shared/_alerts.html.erb like this -
<% flash.each do |message_type, message| %>
<div class="alert alert-<%= flash_class_name(message_type) %> alert-dismissable">
<span><%= message %></span>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<% end %>
Add a helper method (I've added it to the application helper) like this -
def flash_class_name(name)
case name
when "notice" then "success"
when "alert" then "danger"
else name
end
end
Include _alerts.html.erb in the application layout (or the parent layout for your application).
That's it!
Thing is that devise_error_messages! by itself wraps the data into div with class='alert', so the form will have 2 nested divs with the same class. Pressing the x button will close nested div, leaving empty div styled as alert. To avoid this you can omit the div inside helper return value as following:
module DeviseHelper
def devise_error_messages!
return '' if resource.errors.empty?
messages = resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
html = <<-HTML
<button type="button" class="close" data-dismiss="alert">x</button>
#{messages}
HTML
html.html_safe
end
end

Flash msg optional param

How can I pass an optional parameter to the flash message?
I'm using Twitter Bootstrap alert messages, and I want to add the ".alert-block" css class to the message, based on a parameter or something I set in the controller.
Thanks.
This is my solution:
flash[:success_block] = "<h4>Bla blah.</h4> <p>Blah blah.</p>"
<% flash.each do |name, msg| %>
<% block = true if name.to_s.split('_').last == 'block' %>
<% name = name.to_s.split('_').first if block %>
<div class="alert fade in alert-<%= name %> <%= 'alert-block' if block %>">
<a class="close" data-dismiss="alert">×</a>
<%= msg.html_safe %>
</div>
<% end %>
The best practice is to map the flash message on the different alert types that twitter bootstrap provides (ie flash[:info] to .alert-info, flash[:success to alert-success]...)
You can't pass parameters to flash variables, but you can access instance variables of a controller, or even methods by using helper_method from your views/layouts.

devise gem flash messages

if i am using the devise gem with rails, how do i make the flash messages appear only when theres content inside of it.
does rails have an easy way to do this or do i manually need to do it in jquery?
currently im using twitter bootstrap v2 and it has them built in by default. here is the best jquery i could come up with by the way, im not sure how this could be refactored better (although i definitely know it could be). I had to do it like this because i have an 'x' inside the <p> flash
if($('.alert-success').clone().children().remove().end().text() != "") {
$('.alert-success').fadeIn();
}
if($('.alert-error').clone().children().remove().end().text() != "") {
$('.alert-error').fadeIn();
}
EDIT:
My layout contains:
<p class="alert alert-success"><a class="close" data-dismiss="alert">×</a><%= notice %></p>
<p class="alert alert-error"><a class="close" data-dismiss="alert">×</a><%= alert %></p>
No special methods here, I'd simply control how those tags are output with a surrounding if:
<% if notice %><p class="alert alert-success"><a class="close" data-dismiss="alert">×</a><%= notice %></p><% end %>
<% if alert %><p class="alert alert-error"><a class="close" data-dismiss="alert">×</a><%= alert %></p><% end %>

Resources