Editing simpleform locales to enable custom error messages - ruby-on-rails

I have a form within my app that I build using simple_form. What I am trying to do is edit my error messages to something a little different than the default. I am working on my simple_form.en.yml file and I think that may be where my problems are happening.
With what I have, i'm not sure I understand what exactly goes in the settings file, and I am hoping someone can go over what I have and advise me on where to go.
My model is like so (this is my entire model)
class FormSubmission < ActiveRecord::Base
after_create :email_sales
validates :first_name, :last_name, :organization, :email, :phone, :recognition, :inquiry, presence: true
private
def email_sales
FormSubmissionMailer.update_sales(self).deliver_now
end
end
Here is one of the areas of my view
= simple_form_for #form_submission do |f|
.fieldSet.span8
.field.reco
= f.input :first_name, input_html: { class: "formStyling" }, label: "First name", required: false
Finally, in my simple_form.en.yml file I have this here
en:
activerecord:
errors:
models:
formsubmission:
attributes:
email:
blank: "cannot be empty"

Simple_form does nothing special for validation error messages I18n and leaves all work to the default Rails I18n processing. The simple_form.en.yml localization file only deals with the various options to display the form and its elements (labels, hints, etc., see the docs) and has nothing to do with error messages.
So, if you need to set the error messages localization, have a look at the official Rails guide on I18n instead. Actually, I think that your simple_form.en.yml example might work, if you moved the error message localizations to the default Rails locale file for English: config/locales/en.yml.

Related

Do form validation that does not use database

I have a form and I have made some inputs required. After submitting the form that value will be sent to an API. I know that the validations are put into model file but since I do not have a database, how can I use the rails validation?
Right now I am validating the code inside a controller using if else.
if !params[:groups][:name].blank? && !params[:groups][:make].blank? && !params[:groups][:model].blank? && !params[:groups][:firmware].blank?
This does the work but it is not very elegant.
Take a look at ActiveModel, it lets you do "model things" without the database. There were some limitations that made me not use it in the end (I think related to associations) but for simple stuff it's great (and it's a part of how ActiveRecord works.
Example code from docs
class Person
include ActiveModel::Model
attr_accessor :name, :age
validates :name, :age, presence: true
end
this is easy. On the form input fields that you NEED, add required: true For example:
<%= form.for #something do |f| %>
<%= f.text_field :title, placeholder: 'Title', required: true %>
<% end %>
The user gets an error if the required fields are not filled out correctlty.
Is this what you mean?
Justin
EDIT
I guess I would look at using the gem
client_side_validations
Let us know how you go

How can I pass an translation interpolation variable to a failed form validation message?

So, I'm basically trying to show Devise's confirm_within time in the error message that comes when clicking the confirmation email link after the required time.
I am using YAML translation files.
The interpolation variable is called devise_confirm_within
My YAML is like this:
en:
activerecord:
errors:
models:
user:
attributes:
email:
confirmation_period_expired: "some text %{devise_confirm_within}"
Normally, I would find the appropriate view, and then pass the interpolation variable as a parameter to the translate or t method. Like this:
<p><%= t("devise.mailer.confirmation_instructions.please_click_the_below_link_to_confirm_your_new_email", :devise_confirm_within => distance_of_time_in_words(0, User.confirm_within, :locale => I18n.locale)) %></p>
However, there is no view that has the confirmation_period_expired translation key, so I can't do it in this same manner.
I have a view with:
<div class="form-inputs">
<%= f.input :email, :required => true %>
</div>
And a user model with:
validates :email, uniqueness: true
I want to keep all the translation text in the YAML file, so adding :message to the validates field won't do.
So how can I get the devise_confirm_within time into that confirmation_period_expired error message?
PS: I am using the simple_form gem for forms, and also the dotiw gem for overriding the default distance_of_time_in_words method (this doesn't influence this problem I'm having).
The problem was circumvented when I added this to devise.en.yml and similar to the other devise..yml files:
en:
errors:
messages:
confirmation_period_expired: "some text %{period}"
I however wasn't able to pass a translation interpolation variable to a failed form validation (i.e. add a variable to a devise message), of which I am still curious.

How to simply validate a checkbox in rails

How do you simply validate that a checkbox is checked in rails?
The checkbox is for a end user agreement. And it is located in a modal window.
Lets say i have the checkbox:
<%= check_box_tag '' %>
Where and how should i validate this?
I have seen most posts about checkbox validation in rails here, but none of them suit my needs.
Adding
validates :terms_of_service, :acceptance => true
to your model should do it. Look here for more details and options.
However, if accepting the terms is not part of a form for your model, you should use client-side validations, i.e. JavaScript, like this (in jQuery):
function validateCheckbox()
{
if( $('#checkbox').attr('checked')){
alert("you have to accept the terms first");
}
}
You can add a script file to your view like this:
<%= javascript_include_tag "my_javascipt_file" %>
and trigger the function on click:
<%= submit_tag "Submit", :onclick: "validateCheckbox();" %>
EDIT: you can assign an id to your checkbox like this: check_box_tag :checkbox. The HTML will look like this: <input id="checkbox" See these examples for more options.
I was able to skip the jQuery portion and get it validation to work with this questions help. My method is below, I'm on Rails 5.1.2 & Ruby 2.4.2.
Put this code in your slim, erb or haml; note syntax may differ slightly in each.
The line below was specifically for slim.
f.check_box :terms_of_service, required: true
I used a portion of kostja's code suggestion in the model.
validates :terms_of_service, :acceptance => true
Adding on to what has been said already, if you want to add a custom error message, you can add the following to your form:
f.input :terms_of_service, as: :boolean
and then add the following to your model:
validates :terms_of_service, acceptance: { message: "must be accepted"}
Error messages will start with the field name by default followed by your custom message (e.g. Terms of service [CUSTOM MESSAGE]). Something I also found useful was to include a link to the terms of service in the label so users can easily access it to see what they are agreeing to:
f.input :terms_of_service, as: :boolean, label: "I agree to the #{link_to "terms of service", [TERMS AND CONDITIONS PATH]}".html_safe

Error Messages should Match Labels

I have a form. Many of the labels need to have a different name than they are given in the model.
attr_accessible :pin
Simpleform view:
= f.input :pin, :label => "Secret Code"
When validation fails, the error uses the model's name for the field ("Pin"), rather than the label I set in the view ("Secret Code"). The user will be confused on what field has the error.
Currently I have a helper that changes the label:
def fix_pin_errors(msg)
msg.gsub!('Pin', 'Secret Code')
end
If I am doing this for many fields, however, it becomes tedious and not DRY.
What is the best way to have errors match labels that differ from the names the model gives them?
I18n is your friend. Read this guide. It will explain how to globally convert these so they get picked up everywhere you need.
For your example, it might look something like this:
In en.yml:
en:
activerecord:
attributes:
your_model_name:
pin: 'Secret Code'

Customize error message with simple_form

I'm using the simple_form gem. I want to customize the error message displayed when a user fails validations. How can I accomplish this?
You can declare the content of the
error message in your model:
validates_length_of :name, :minimum => 5, :message => "blah blah blah"
You can set id or class for your
error tag:
<%= f.input :name, :error_html => { :id => "name_error"} %>
Then you can use CSS for the styling.
And you can use
<%= f.error :name, :id => "name_error" %>
and you'll get
<span class="error" id="name_error">is too short (minimum is 5 characters)</span>
I dont know if it is any different for simple_form gem.
For content of error messages to be changed, you can use the :message attribute in the model.
class User < ActiveRecord::Base
validates :email, {:presence => true, :message => "is not filled up."}
end
Now the validation message will be Email is not filled up. If you want the field name also to be changed(Email to E-mail address something like that ), the approach now is to define it in locales.rb file like this
# config/locales/en.yml
en:
activerecord:
attributes:
user:
email: "E-mail address"
See link for details on locales. Another approach is to define in the model, humanized attributes like this:
class User < ActiveRecord::Base
validates :email, {:presence => true, :message => "is not filled up."}
HUMANIZED_ATTRIBUTES = {
:email => "E-mail address",
...(other fields and their humanized names)
...
}
def self.human_attribute_name(attr, options={})
HUMANIZED_ATTRIBUTES[attr.to_sym] || super
end
end
For customizing style of validation message we will have to edit the style for
#errorExplanation and .fieldWithErrors,in the scaffold.css stylesheet.
You can easily change the default error message comes in the translation file, which is found in config/locales/simple_form.en.yml.
In the specific initializer, config/initializers/simple_form.rb you can overrule the default options how the html is generated.
Hope this helps.
For completeness, I would like to add that formtastic is an easier choice to start with, because it has a default layout. I like simple_form a lot, but it does not offer any formatting out of the box, but that is their intention. With Formtastic it is very hard (impossible) to change the generated html, and with simple_form can you can completely mold the generated html to your liking. This is especially useful if you have a designer, and the forms you generate have to generate the same html. So if you are getting started, formtastic will give you nicer-looking results quicker. Also note that it is quite easy to switch, because the syntax is almost identical.
There is another solution explained here that wasn't mentioned in the answers. You can directly override the error messages from the views, in the form itself. For example:
<%= f.input :last_name,
placeholder: 'last_name',
error: 'This is a custom error message',
required: true,
class: 'form-field',
autofocus: true,
input_html: { autocomplete: "last_name" } %>
It is however not advised as it is not DRY, you would need to override it in every field.

Resources