How can I skip validations of superclass in Rails 4? - ruby-on-rails

I have pretty big RoR app.
There is superclass named User.
class User < ActiveRecord::Base
validates :email, presence: true
end
Also I have class Client which inherited by User
class Client < User
with_options(on: [:personal_info]) do |pi|
pi.validates :first_name,
:last_name,
:email,
:mobile_phone,
:landline_phone,
presence: true
pi.validates :primary_email,
email_format: {
message: "doesn't look like an email address"
}
end
end
When I create Client's object I got 2 errors that "Email can't be blank."
How can I disable or skip validates of superclass??
Remove validations in superclass is impossible.

Related

How can I do conditional validation in a Ruby on Rails Model?

I have a study that can have participants. I have a simple_form where the user can add participants. It looks a bit like a table:
name | company | email OR mobile | timezone
name | company | email OR mobile | timezone
name | company | email OR mobile | timezone
By default, the screen has three fieldset rows, and the user can add more rows if needed. Each row is one participant.
I would like my participant model to validate only the rows that have been filled out, and ignore rows that are blank because even though we are showing three by default to the user, not all three are required fields.
Here's the relevant portion of app/models/participants.rb.
class Participant < ApplicationRecord
belongs_to :study
validates :name, presence: true
validates :company, presence: true
validates :time_zone, presence: true
if :channel == 'sms'
validates :mobile_number, presence: true
elsif :channel == 'email'
validates :email, presence: true
end
end
In participants_controller.rb I have:
def index
3.times { #study.participants.build } if #study.participants.length.zero?
end
The problem is that I get an error because simple_form thinks that all three fields are required, and not just the first row.
Rails' validators accept conditions:
validates :mobile_number, presence: true, if: Proc.new { |p| p.study.channel == 'sms' }
validates :email, presence: true, if: Proc.new { |p| p.study.channel == 'email' }
By default all inputs are required. When the form object includes
ActiveModel::Validations (which, for example, happens with Active
Record models), fields are required only when there is presence
validation. Otherwise, Simple Form will mark fields as optional. For
performance reasons, this detection is skipped on validations that
make use of conditional options, such as :if and :unless.
And of course, the required property of any input can be overwritten
as needed:
<%= simple_form_for #user do |f| %>
<%= f.input :name, required: false %>
<%= f.input :username %>
<%= f.input :password %>
<%= f.button :submit %>
<% end %>
Try to put all the inputs as required: false. That should allow skip simple_form validations and the data came into the controller and the model can be filtered or/and validated and every other things you want to do before persist.
In the model class you can use several ways of validations for example:
you also can use the :if and :unless options with a symbol corresponding to the name of a method that will get called right before validation happens. This is the most commonly used option.
for example
class Participant < ApplicationRecord
belongs_to :study
validates :name, presence: true
validates :company, presence: true
validates :time_zone, presence: true
validates :mobile_number, presence: true if: :channel_is_sms?
validates :email, presence: true if: :channel_is_email?
def channel_is_sms?
channel == "sms"
end
def channel_is_email?
channel == "email"
end
end
or also you can use custom validator where you do all that you need validate. for example
class MyValidator < ActiveModel::Validator
def validate(record)
unless record.channel == 'sms'
...
... actions here
...
end
end
end
class Person
include ActiveModel::Validations
validates_with MyValidator
end

AngularJS and Rails live validation

In my Ruby on Rails application i've set up a user registration / login system that have some validations in the class ( for register a User).
class User < ActiveRecord::Base
# Put the email downcase before save the User
before_save {self.email = email.downcase}
# Confirmation of the password before save
validates_confirmation_of :password
has_secure_password
validates :first_name, :last_name,
presence: true,
format:{ without: /\s/ }
validates :email, uniqueness: true,
format:{
with: /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
}
def to_s
"#{first_name} #{last_name}"
end
end
In this application i also use AngularJS and the question is, can i use AngularJS for the live validation of the user during the registration?
If you want to validate live your fields you'll have to use AngularJS validators. Those ruby validators will be called when you'll submit the form.

how to include a class which is not a model in controller

I have added class ContactRequest in home_helper.rb
module HomeHelper
class ContactRequest
include ActiveModel::Model
attr_accessor :name, :email, :phone, :message, :captcha
validates :name, presence: true,length: {in:2..255}
validates :email, presence: true, length: {in:6..255}
validates :message, presence: true
validates :phone, presence: true
validates :captcha, presence: true
end
end
This class basically is to be used to bind dat from a JSON POST to an object which then I can use for
Verifying Captcha
Sending the contact information from this object as an email via SendGrid
hence, I do not have any needs to persist the information.
However I get an error when the relevant method of the controller is called
def contact
#contactReq = ContactRequest.new(JSON.parse(params[:json]))
logger.debug "ContactRequest: #{#contactReq.attributes.inspect}"
for this line I see in the logs
NameError (uninitialized constant HomeController::ContactRequest):
app/controllers/home_controller.rb:6:in `contact'
isn't the home_helper available to the view and this controller? Or should I put this class in concerns directory?
You need to add the module name in front of the classname HomeHelper:
def contact
#contactReq = HomeHelper::ContactRequest.new(JSON.parse(params[:json]))
...
end

Overriding presence true in User model

I have the following in my models/user.rb:
validates :company, presence: true
validates :title, presence: true
I have a secondary view where I want to create a user but not require this user to enter a company and a title. How would I do that without modifying the main user.rb?
This is for Rails 3.2
You can do by declaring custom validations the way #BroiSatse has answered or when saving the user you can pass validate: false as argument, do this way
#user.save(:validate => false)
I usually do sth like:
class User < AR::Base
validates :company, :title, presence: true, if: :validate_company_and_title?
def validate_company_and_title?
#validate_company_and_title.nil? || #validate_company_and_title
end
def skip_company_and_title_validation!
#validate_company_and_title = false
end
end
Then in your controller create action for given view you can do:
#user.skip_company_and_title_validation!

Rails - How to disallow specific inputs in model validations?

My User model has an attribute called :profile_name which is used in routing profile page url's - domain.com/:profile_name . In order to prevent collision with my other views I want to make sure a User can't choose something like "friends" or "feed" as their profile name. How can I set this in validations?
/models/user.rb (currently):
...
validates :email, presence: true, uniqueness: true
validates :profile_name, presence: true,
uniqueness: true,
format: {
with: /^[a-zA-Z0-9_-]+$/,
message: 'Must be formatted correctly.'
}
...
The exclusion validation helper:
validates :profile_name, presence: true,
...,
exclusion: {
in: ["friends", "feed"],
message: "Profile name %{value} is reserved."
}
Use a custom validation method. You'd probably want to separate out the forbidden list, but I kept this extra concise.
class User < ActiveRecord::Base
validates :profile_not_forbidden
protected
def profile_not_forbidden
if ['friends','feed'].include?(profile_name)
errors.add(:profile_name, 'Forbidden profile name.')
end
end
end

Resources