Rails 3 Validation on a group of fields - ruby-on-rails

I have a model with a whole bunch of fields. Not all fields are used based on the user selecting a certain type of form. I have around 6 different types of forms so a field may be used on 4 of them.
Is there a way to group validation based on a element ie?
case xxx
when "form1"
validates :field1, :presence => true
when "form2"
validates :field1, :presence => true
when "form3"
validates :fiel2, :presence => true
end
I will be doing client side validation but I obviously will need server side as well to make sure they have submitted good data.
Any suggestions how this can be done ?
I'm using Rails3 with Mongoid 2.0
Thanks in advance!

Something like this?
validates :field1, :presence => true, :if => Proc.new { |foo| %w{form1 form2}.include?(foo.xxx) }
validates :field2, :presence => true, :if => Proc.new { |foo| %w{form1 form3}.include?(foo.xxx) }
validates :field3, :presence => true, :if => Proc.new { |foo| %w{form2 form3}.include?(foo.xxx) }

I see a problem with the model class having to have intimate knowledge of the views involved. If the forms in the views were named differently, the solution won't work. You will want to use "validation groups" like that used in ASP.NET. You could do some search on that and either find a similar solution for Rails or roll your own. Maybe this one will help: https://github.com/akira/validationgroup

Related

Rails model validation: How to make sure a attribute is in a list

Hi I have a job model which has an string attribute called category. In the front end, I have a form with a dropbox where a user can fill out the category attribute with the selected value from the list. This is good enough front end validation for me, but now how will I do backend validation for the model?
I have dont other validations in the past for example:
validates :name, :presence => true
But is there anyway I can do something like
validates :category, :in => {"Food", "Drink", "Rental"}
You can do it like this:
validates :category, :inclusion => { :in => %w(Food Drink Rental) }
Or shorter:
validates :category, :inclusion => %w(Food Drink Rental)
Everything is in the documentation.

Form validation - if something is false, require this validation

In my form validation of my model, I'm trying to say that if the params of a column called :virtual is false, then the :location field should validate for :presence => true.
My current code is:
validates :location, if :virtual => false, :presence => true
But that's giving me a syntax error. What's the correct way to format this?
Something like:
attr_accessor :virtual # sets up a "virtual attribute" called "virtual" to which you can read/write a value
# this step isn't necessary if you already have an attribute on the model called "virtual"
validates :location, :presence => true, :unless => :virtual?
The use of virtual? should check whether the attribute virtual is true or false. Using unless means this validation is only performed if virtual is false (or is a value that is considered false).
More detail on virtual attributes and validation: Rails: Using form fields that are unassociated with a model in validations
validates :location, presence: true, if: Proc.new { |p| p.virtual == false }

Which of these rails 3.1 validations are better?

(A) Like this:
validates :network_id, :numericality => true
validates :direct_url, :presence => true
validates :domain_name, :presence => true
validates :merchant_id, :numericality => true
validates :is_paid_merchant, :presence => true
validates :is_top_merchant, :presence => true
validates :last_months_revenue, :presence => true,
:numericality => true
validates :name, :presence => true,
:length => { :maximum => 50 }
validates :primary_category_id, :numericality => true
validates :url, :presence => true
validates :url_tag, :presence => true,
:length => { :maximum => 45 }
-OR-
(B) like this:
validates :network_id,
:merchant_id,
:last_months_revenue,
:primary_category_id, :numericality => true
validates :direct_url,
:domain_name,
:is_paid_merchant,
:is_top_merchant,
:last_months_revenue,
:name,
:url,
:url_tag, :presence => true
validates :name, :length => { :maximum => 50 }
validates :url_tag, :length => { :maximum => 45 }
In the first case each field has it's own validates clause and in the second it's based on what is being validated (fields that have multiple validations appear multiple times). The first case is also in alphabetical order so is a little more helpful to jump right to a specific field.
-OR-
(C) Am I just too anal retentive about how my code reads and looks?
I think the first style is better for the following reason:
It's most likely that you have a specific field name 'in mind' when working on a validation - or editing one - or adding a new validation for that field. So a system that lists each field and then all the validations for each one works well to read.
The other style - group validations together tends to lead to seeing a field in one spot but then having to search and scroll around for other validations for that field - and there's a good chance that you will not see or know about the other validations for that field which may be 'off-screen' and thus missed.
This also may not be that big a deal when initially building the application (when the first style might actually seem easier) but going forward when you are adding or removing or changing fields and validations (i.e. 'application building in the real world!') it will be easier and less error-prone if all the validations for a given field are together.
Another example of why B) is bad...
Imagine this:
validates :network_id,
:merchant_id,
:last_months_revenue,
:primary_category_id, :numericality => true
validates :network_id,
:direct_url,
:domain_name,
:merchant_id,
:url,
:url_tag, :presence => true
validates :network_id :uniqueness => true
See how field are repeated all over the place?
Now imagine removing network_id - yuch!
Now imagine adding another _id field that needs numericality, uniqueness and presence - yuch!
Another example - one might think (ok, I've done long ago), i'll group all the 'required's together and then put a nice comment for them and then all the uniquesness of's, with a comment header label for all of them, etc. So there is a 'standard' for developers to follow. The problem with an approach like this (apart from the previous comments) is that this is a 'local' standard that other programmers (both current and future) will need to understand and then... hopefully... follow. Much as I love them myself, personal standards like this often contribute to technical debt unless clearly thought out.
Personally I'd prefer the first style. Because I'd kick you for having to read through 30 lines of code to find out what validations are set on a single field.
For me better is A. One declaration for one attribute is not redundant but clear.

Best way to check if a username exists in a model

I'm quite new to ruby/rails. I was wondering what is the best way to ensure that two people don't choose the same username. Here is my model at the moment:
class User < ActiveRecord::Base
validates :username, :presence => true
validates :password, :presence => true, :length => { :minimum => 7}
end
Note: I'm assuming it is best to place this type of code in the model. Correct me if I'm wrong.
There's a validation to make sure a field is unique. Just change your username validation to:
validates :username, :presence => true, :uniqueness => true
You should also add an index to your usertable, with uniqueness. This way, if people quickly press the username register button twice, you will also be protected at the database level
add_index :users, :username, :unique => true
This question has already been correctly answered but for future reference, APIDock has excellent Rails documentation here: http://apidock.com/rails. The search's autocomplete is fantastic.
The documentation for the validates method is here: http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates where you can find the :uniqueness => true option.

How can one Validate presence of only one?

I have a user model that has_one signup.
I'm having a recurring bug where users will click multiple times and create many unnecessary signups. How can I validate the user only gets one? Is there a way to do that from the model?
Not sure about your model, but validates_uniqueness_of might be what you are looking for.
In rails 3 you could do like this.
validates :field, :uniqueness => true
If you want your custom message then
validates :field, :uniqueness => {:message => 'your message'}

Resources