Rails 5: How to implement a conditional validation for an ActiveModel? - ruby-on-rails

As the code below shows, I am trying to validate an form value of an ActiveModel object based on the value of a checkbox of the same form.
If the box is checked (I made sure it will return true not 1) the validation on order_number should be deactivated, as the field is being deactivated as well (by JS). The naive approach shown below, using the attribute that is connected to the checkbox not_a_customer as conditional for the validation of order_number didn't work.
What else can I try?
I have an ActiveModel class:
class SupportCase
include ActiveModel::Model
include ActiveModel::Validations
attr_accessor(:email, :os, :inquiry_type, :order_number, :first_name, :last_name, :message, :not_a_customer)
validates :order_number, presence: true,
numericality: { only_integer: true },
length: { in: (4..5), message: 'doh' },
unless: :not_a_customer
end
And a form for creating support cases:
= simple_form_for #support_case, html: { class: 'form inset' } do |f|
.row
.col.sm-6
.row{ id: 'order-row' }
.col.sm-6
= f.input :order_number, input_html: { class: 'icon-field hash-icon' }
.col.sm-6
.label-title{ title: t("simple_form.labels.support_case.hint") }
= f.input :not_a_customer, as: :boolean do
= f.check_box :not_a_customer, {}, "true", "false"
.col.sm-6
= f.input :email, input_html: { type: 'email', required: 'true' }
= f.input :first_name, input_html: { type: 'text' }
= f.input :last_name, input_html: { type: 'text' }
.col.sm-12
~ f.input :message, as: 'text', input_html: { required: 'true' }
%button.btn.btn-action
= t('views.contact.form.submit')

Check the value of not_a_customer. You are just getting a string instead of a boolean value, which is always truthy ("true", "false" are both truthy value).
In Rails, you can do not_a_customer.to_bool to convert it into boolean.
The checkbox does not convert your value into boolean, because params is parsed as if they are all strings (including int, string, boolean values).

Related

How to check input right in template

Can I access the input value and check his value?
I want to disable the ability to change the key if it's equal to 'foo'.
.email-template-param-nested-fields
- if :key == 'foo'
= f.input :key, placeholder: 'foo', readonly: true
- else
= f.input :key, placeholder: 'key'
= f.input :value, placeholder: 'example'
You can assign variable as
- args = f.object.key == 'foo' ? { placeholder: 'foo', readonly: true } : { placeholder: 'key' }
And then
= f.input :key, **args

custom error field combining 2 error fields in rails

In my form, which is a credit card validation form, I have 2 fields expiry_year and expiry_month.
validates :expiry_month,
length: { is: 2, allow_blank: true },
numericality: { only_integer: true, allow_blank: true }
validates :expiry_year,
length: { is: 4, allow_blank: true },
numericality: { only_integer: true, allow_blank: true }
However I want to have a hidden Expiry field which shows as red in the form if the 2 fields above are not valid.
So the form will look something like this, but I need the Expiry label to be red in the validation, How can I do this?
Here is how the fields look in the form.html.haml for the view.
= f.label 'Expiry'
= f.text_field :expiry_month, placeholder: 'MM', maxlength: 2
= f.text_field :expiry_year, placeholder: 'YYYY', maxlength: 4
It seems you can do it like this:
If you have an error class you can check for any errors and display the class in the view.
.error { color: #9d1d20; }
- if #donation.errors.messages.keys.any? { |k| k.match(/expiry/) }
= f.label 'Expiry', class: "form-label-expiry error"
- else
= f.label 'Expiry', class: "form-label-expiry"
= f.text_field :expiry_month, autocomplete: "off"
= f.text_field :expiry_year, autocomplete: "off"

Unpermitted parameter error whereas parameter specified in params in controller

I have a product model which has a many to many association with a category model through join model category_product
I have a product/new.html.slim
=simple_form_for #product, html: { multipart: true } do |t|
= t.error_notification
div class="form-group"
= t.input :name, label: 'Nom',equired: true, input_html: { class: 'form-control' }
div class="form-group"
= t.input :description, label: 'Description', required: true, input_html: { class: 'form-control' }
div class="form-group"
= t.input :price, label: 'Prix', required: true, input_html: { class: 'form-control' }
div class="form-group"
= t.input :weight, label: 'Poids', required: true, input_html: { class: 'form-control' }
div class="form-group"
= t.association :categories, as: :check_boxes, label: "Catégories"
= t.button :submit, value: "Valider", class: "btn-success marge-bas"
when I submit my form I get the following error :
found unpermitted parameter: category_ids
though in my ProductController I have permitted category_ids :
def product_params
params.require(:product).permit(
:category_ids,
:name,
:price,
:description,
:weight,
:picture,
:picture1,
:picture2,
:picture3,
)
end
When I check my params category_ids is an array of strings
"category_ids"=>["1", "2", "5", ""]
What am I doing wrong ?
Try rewriting product_params to:
def product_params
params.require(:product).permit(:name, ... :picture3, :category_ids => [])
end
Setting the category_ids to be an array at the end of your list of permitted params should resolve this error.
Hope it helps!
I ran into this "Unpermitted parameter: category_ids" error when working through the book, "Rails, Up And Running" and adding category_ids => [] fixed it. Thank you, Zoran!

Separate model date fields and validation rails

I'm using this gem for my forms :
https://github.com/plataformatec/simple_form
I have 3 input fields each for day, month, year :
= f.input :dob_day, label_html: {style: 'display:none'}, placeholder: 'DD'
= f.input :dob_month, label_html: {style: 'display:none'}, placeholder: 'MM'
= f.input :dob_year, label_html: {style: 'display:none'}, placeholder: 'YYYY'
In my model (important bit) I'm trying to build a validations for the date of birth :
class User < ActiveRecord::Base
attr_writer :dob_day, :dob_month, :dob_year
def dob_day
#dob_day
end
def dob_month
#dob_month
end
def dob_year
#dob_year
end
user.validates :dob_day, presence: true
user.validates :dob_month, presence: true
user.validates :dob_year, presence: true
user.validates :dob, presence: true,
date: { before: Proc.new { Time.now - 18.years }, message: ": You must be over 18 to join" }
Right now I get the error :
Can't mass-assign protected attributes: dob_day, dob_month, dob_year
I'd like to inject dob field with values from dob_day, dob_month, dob_year. I'd do it in model if possible rather than in controller
Am I doing this the wrong way? This should be fairly simple, but turns out its not
you can remove
as: :date, start_year: Date.today.year - 90, end_year: Date.today.year - 18, order: [:month, :year, :day]
and then you can use jquery date picker for showing calendar to choose a dob

Ruby on Rails form validation: default field value

How do I make Rails treat the "http://" value as blank: if the value is "http://", do not validate website field and insert an empty string (not "http://") into database?
In view:
<%= f.text_field :website, value: "http://" %>
In model:
validates :website, format: { with: /^https?:\/\/\S+/i }, allow_blank: true
You can use :if or :unless to conditionally validate (untested):
validates :website, format: { with: /^https?:\/\/\S+/i }, allow_blank: true, :unless => ['http://', 'https://'].include?(params[:website]) }
Use a before_save callback to convert the string to blank:
def before_save
self.website = "" if ['http://', 'https://'].include?(self.website)
true
end

Resources