Indyarocks
Indyarocks

Reputation: 643

Rails validation error per form field

I have a form to create product. A product has many fields with validations. For example:

Say user tried to save empty form. Now I want to show have following kind of error hash:

{
  general: 'Something went wrong, Please contact support team.'
  product: {
    name: 'Name can not be blank',
    description: 'Description can not be blank'
  }
}

So that I can show general error on top(if any) or I will be able to show error just above the corresponding field.

In products_controller,

  def create
    @product = Product.new(product_params) # Strong params
    if @product.save
      flash[:success] = "Welcome to the Sample App!"
      redirect_to @product
    else
      render 'new'
    end
  end

How do I show error corresponding to each field? I'm aware of the @product.errors will give me errors. But I want to keep a general error key as well. flash are one way to do it. But as far as I know, we can send only text message in a flash. What should be the right way to it in Rails?

Thanks,

Upvotes: 0

Views: 1573

Answers (2)

Abhilash Reddy
Abhilash Reddy

Reputation: 1549

Simply you can use <%=f.error_span(:name) %> in your html.erb file

Example:

<div class="form-group">
     <%= f.label(:name) %>
     <%= f.text_field(:name) %>
     <%=f.error_span(:name) %>
</div>

Note: You need twitter-bootstrap-rails gem for this to work and it will make validations easy for all the pages. Let me know if this is what you needed!!

Upvotes: 0

Justin
Justin

Reputation: 4940

Here is my solution for this problem. I've created a simple helper method that I use in the view per field. It's pretty extendable as well, so don't feel limited by it's current state. It can easily accept additional arguments/options to be able to add custom CSS classes, etc.

 # app/helpers/form_errors_helper.rb
 module FormErrorsHelper
   def error_message_on(object, method)
     return unless object.respond_to?(:errors) && object.errors.include?(method)
     errors = field_errors(object, method).join(', ')

     content_tag(:div, errors, class: 'form-group-error')
   end

   private

   def field_errors(object, method)
     object.errors[method]
   end
 end

 # css
 .form-group-error {
   # your styling here
 }

 # form
 <%= form_for(@product) do |f| %>
   <div class="form-group">
     <%= f.label(:name) %>
     <%= f.text_field(:name) %>
     <%= error_message_on(f.object, :name) %>
   </div>

   <div class="form-group">
     <%= f.label(:description) %>
     <%= f.text_area(:description) %>
     <%= error_message_on(f.object, :description) %>
   </div>
 <% end %>

With this, you can add another key, general to the messages hash.

Let's say you do that in your model.

errors.add(:general, 'This is my general error')

Then, in your view, you just use the same helper.

error_message_on(f.object, :general)

If you need different styling for the "general" error, you can pass in additional arguments to that helper, like additional CSS classes.

Upvotes: 1

Related Questions