Client side validation is not working while applying conditional validation in rails 4 - validation

I am using client side validation gem. Client side validation is not working while applying conditions.
Here is my Model Class.
validates_uniqueness_of :project_code
**validates :price, numericality: true, :if => :project_type_fixed?**
def project_type_fixed?
project_type == 'Fixed'
end
In this code validation for project_code is working fine, but for price it is not working.
Thanks in advance.

Client_side_validations does not validate conditionals out-of-the-box. What you are observing is the intended behavior.
In order to validate conditionals, you need to force them in your form:
f.number_field :price, :validate => { :numericality => true}
In addition, according to the documentation, the value needs to evaluate to true at the time the form is being generated. However, there is a hack for this: The method that determines whether the condition evaluates to true is called run_conditional (source), so you can override that method in your model:
def run_conditional(method_name_value_or_proc)
(:project_type_fixed? == method_name_value_or_proc) || super
end

Related

How to conduct Rails model validation witih or condition?

I’m using Rails 4.2.3. I have three fields in my model — name, first_name, and last_name. would like to have a validation rule in my model that causes a save to fail if the “name” field is empty unless either the first_name or last_name field is not empty. SOoI tried
validates_presence_of :name, :unless => !:first_name.empty? or !:last_name.empty?
but this doesn’t work. I get the error below
undefined method `validate' for true:TrueClass
What is the proper way to write the validation rule above?
Everything you need to know is here.
You can write the rule by defining a separate method for it:
class Whatever < ActiveRecord::Base
validates :name, presence: true, unless: :firstname_or_surname?
def firstname_or_surname?
firstname.present? || surname.present?
end
end
Or you can use a Proc to define it inline:
class Whatever < ActiveRecord::Base
validates :name, presence: true,
unless: Proc.new { |a| a.firstname.present? || a.surname.present? }
end

Order of before_save callbacks in rails

I am trying to geocode an address and I am trying to geocode on a non-persistent attribute called full_address. Here is my code:
class Company < ActiveRecord::Base
include ActiveModel::Dirty
validates :name, :organization, :title, :state, :city, presence: true
validates :email, presence: true, length: { maximum: 255 },
format: { with: /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i, }
before_save :full_address
geocoded_by :full_address
before_save :geocode, if: ->(obj){obj.full_address.present? && (obj.city_changed? || obj.state_changed?)}
def full_address
"#{city}, #{state}"
end
end

I am not sure if my before_save callbacks are firing the in the right order. Basically, how do I make sure the
before_save :full_address
fires before the other?
I looked into the around_save documentation, but I am still unsure what it's doing.
Jwan --
AR callbacks are used for a lot of reasons, and they are particularly helpful for dealing with records in the DB, but you don't need one here for for 'full_address'. Why?
Because all it is it doing is returning a string, not performing an operation on the db or altering data in any way.
It's been awhile since I've worked with geocoder gem, but in your other before_save callback, you are passing a lambdha for conditional operation.
Couple things:
1.) You're checking for presence of an interpolated string, but validating presence of the two interpolated attributes, which fires before the callback, so obj.full_address.present? should always return true because it will blow up on the validations if both or even one of those attributes isn't present. Try
before_save :geocode, if: ->(obj){ obj.city_changed? || obj.state_changed? }
+1 though on ActiveModel::Dirty implementation!
2.) Unless you're using a much older version of Rails or explicitly configuring it otherwise, ActiveModel::Dirty is autoloaded; no need for line 2.
3.) I would also try using an after_validation callback instead of the before_save. Can't guarantee that will solve the problem, but it is earlier in the callback stack. Refer to http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

Rails 4: Active Record Validation error on: create

If I have some before create action like:
before_create :generate_token
private
def generate_token
self.auth_token = loop do
random_token = SecureRandom.urlsafe_base64(nil, false)
break random_token unless self.class.exists?(auth_token: random_token)
end
end
When writing validations I find validates :auth_token, presence: true, on: :create fails.
However, validates :auth_token, presence: true, on: :after_create works.
Why is this?
ref. Active Record Callback Order and Active Record Validations :on
edit: Curiously, on: :before_create passes validation, on: :create fails, and on: after_create succeeds. This is puzzling, could some please explain this?
Read the docs you linked, to:
(1) before_validation
(-) validate <======== This runs before before_create callbacks are run
(2) after_validation
(3) before_save
(4) before_create
I would consider generate the token when the object is initialized.
after_initialized :generate_token

Change priority of Custom validations in rails model

I have implemented validations in a dependent manner, like if start_date format is invalid so i don't want to run other validation on start_date.
validates_format_of :available_start_date, :with => /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}((((\-|\+){1}\d{2}:\d{2}){1})|(z{1}|Z{1}))$/, :message => "must be in the following format: 2011-08-25T00:00:00-04:00"
This checks for a specific format and then i have custom validation methods called from which should run later.
def validate
super
check_offer_dates
end
I have used self.errors["start_date"] to check if the error object contains errors, it should skip the other validations on same parameter if it's not empty.
But the problem is def validate is called first and then the validates_format_of. How can i change this so that the flow can be achieved.
I just ran into a similar problem; this is how I fixed it using a before_save callout:
Not working (validates in wrong order - I want custom validation last):
class Entry < ActiveRecord::Base
validates_uniqueness_of :event_id, :within => :student_id
validate :validate_max_entries_for_discipline
def validate_max_entries_for_discipline
# set validation_failed based on my criteria - you'd have your regex test here
if validation_failed
errors.add(:maximum_entries, "Too many entries here")
end
end
end
Working (using before_save callout):
class Entry < ActiveRecord::Base
before_save :validate_max_entries_for_discipline!
validates_uniqueness_of :event_id, :within => :student_id
def validate_max_entries_for_discipline!
# set validation_failed based on my criteria - you'd have your regex test here
if validation_failed
errors.add(:maximum_entries, "Too many entries here")
return false
end
end
end
Note the changes:
validate_max_entries_for_discipline becomes validate_max_entries_for_discipline!
validation method now returns false on failure
validate validate_max_entries_for_discipline becomes before_save validate_max_entries_for_discipline!

DataMapper has n with conditions

By any chance is it possible to create a conditional association with DataMapper?
For example:
I want the User have n Apps just if that user have the attribute :developer => true
something like this:
class User
include DataMapper::Resource
property :id, Serial
property :name, String, :nullable => false
property :screen_name, String, :nullable => false, :unique => true
property :email, String, :nullable => false, :unique => true, :format => :email_address
property :password, BCryptHash, :nullable => false
property :developer, Boolean, :default => false
#The user just gets apps if developer
has n :apps #,:conditions => "developer = 't'"
end
class App
include DataMapper::Resource
property :id, Serial
property :name, String, :nullable => false
belongs_to :user
end
I know that this would be possible by creating a subclass from User as a Developer::User and in that class, use the has n, but I really would like to know if its possible to make it directly on the association declaration.
Another way I also managed to do when using ARn was to extend the association and rewriting the methods for each action.
So on the extension module I could have something like this:
module PreventDeveloperActions
def new
if proxy_owner.developer?
super
else
raise NoMethodError, "Only Developers can create new applications"
end
end
# and so on for all the actions ...
end
But again, I really would like to avoid the use of this solutions if possible, but just if it's possible to perform a quick and direct method easily with DataMapper :)
Thanks in advance
At the moment, conditions that you include in the relationship declaration only apply to the target. So if the target model has an :active property, you can say things like has n, :apps, :active => true. Unfortunately you can't define relationships that are only active given the current state of the source (yet).
There are some proposals I'm considering to expand the Query logic in DM, but I'm unsure what the impact will be to the code, and what extra capabilities it will provide aside from this. It may be something we tackle after DM 1.0, since it also affects 50+ adapters and plugins.
STI is normally what I'd recommend for something like this, since it will allow you to define relationships that only exist for that type of object. Another approach would be to define the relationships as normal, mark the accessor/mutator methods as private, and then add a proxy method that does the equivalent of return apps if developer?.

Resources