Sexy validator for uniqueness with :scope constraint - ruby-on-rails

In a Ruby on Rails 3 application, I have invitations. Here is the model:
class TeamInvitation < ActiveRecord::Base
belongs_to :team
validates :email, :presence => true, :format => RFC822::EMAIL
validates_uniqueness_of :email, :scope => :team_id
end
How can I refactor the uniqueness validation to include it into the validates method?
According to the documentation, the key :uniqueness should be a boolean, but in my case i want specify the scope. How can I do that (if possible)?

Have you tried this?
:uniqueness => { :scope => :team_id }
I haven't, but I know other ones can accept a hash. Might be worth a shot.

you can try :uniqueness => true

Related

Rails: How to set different validation rules on creation and update

I have a text field that can be empty when created, but not when updated.
How can I do that in rails: Different validation rules depending on action?
The idea behind this, is to allow an admin to create a blank issue ticket, to be filled by a user.
Here is my original model (issue.rb):
class Issue < ActiveRecord::Base
attr_accessible :content, :status
validates :content, :presence => true, :length => { :maximum => 2048 }
validates :status, :inclusion => { :in => %w(WAITING REJECTED ON OFF) }
belongs_to :user
end
How can I set :presence => true of :content only when updating, but not when creating?
Thanks in advance.
You can use :on => :create in your validation statement.
Like in this question.

Certain validations only in Rails.env.production?

I would like to only allow certain validations within production vs other environments for an app.
For example, I have tried to add:
if Rails.env.production?
validates :email, :uniqueness => true
validates :phone, :uniqueness => true
end
However this will not work. How can one add validations only to specific environment modes?
Try this -
validates :email, :uniqueness => true, :if => lambda{ Rails.env.production?}
validates :phone, :uniqueness => true, :if => lambda{ Rails.env.production?}
Totally agree with the comments, but if you really want to do this, try the :if option
validates_uniqueness_of :email, :if => Rails.env.production?

validates_uniqueness_of can't check on unsaved data?

I have a model called Science Subject Choice
class ScienceSubjectChoice < SubjectChoice
belongs_to :subject
belongs_to :subject_preference
validates_associated :subject
validates_associated :subject_preference
#TODO: validation
validates :priority, :presence => true, :numericality => true, :inclusion => {:in => 1..SubjectPreference::MAX_SCIENCE_SUBJECT_CHOICE}
validates_uniqueness_of :subject_id, :scope => :subject_preference_id
validates_uniqueness_of :priority, :scope => :subject_preference_id
end
the uniqueness validator don't work on unsaved data?
How can I solve it?
Solution:
Instead of validating in itself, the parent object should do the validation:
def validate_science_subject_choices_uniqueness
if science_subject_choices.map(&:priority) != science_subject_choices.map(&:priority).uniq
errors[:base] << "Duplicated priority in science subject"
end
end
Validations do not work like that. They are dynamic by nature. If you want database constraints, you have to specify it in your migrations. For instance, a :uniq => true would make sure that a value is unique in your model.

Why aren't my before_validation methods firing if some validation is scoped?

In my model I've got a couple of methods to populate attributes of an Invoice before it is validated:
validates :account_id, :presence => true
validates :account_address, :presence => true
validates :number, :presence => true
validates :number, :uniqueness => true, :scope => :client_id
before_validation :generate_number, :associate_addresses, :on => :create
def generate_number
self.number = self.client.invoices.count + 1
end
def associate_addresses
self.account_address = self.account.addresses.first
end
And in the controller:
#invoice = #account.invoices.build(:client_id => #client.id)
if #invoice.save
#it saved
end
My problem is that the associate_addresses and generate_number methods only fire if I remove the :scope => :client_id argument on the :number validation.
Why would it skip the before_validation callbacks due to this?
Working in Rails 3.0.3
Thanks!
Thanks.
Don't know why it's skipping the before_validation methods, but to scope a uniqueness validation in Rails 3 you should use the following syntax:
validates :number, :presence => true, :uniqueness => { :scope => :client_id }
I guess that your syntax is making it try to add a scope validation, which doesn't exist. Probably there's a Rails bug that makes that skip the before_validation methods.

rails 3 validation on uniqueness on multiple attributes

I use Rails 3.0.0.beta4
I want to add a validation on uniqueness on two attributes, that means that my model is valid if the couple of 'recorded_at' and 'zipcode' is unique.
On one attribute here is the syntax
validates :zipcode, :uniqueness => true
thanks
In Rails 2, I would have written:
validates_uniqueness_of :zipcode, :scope => :recorded_at
In Rails 3:
validates :zipcode, :uniqueness => {:scope => :recorded_at}
For multiple attributes:
validates :zipcode, :uniqueness => {:scope => [:recorded_at, :something_else]}
Multiple Scope Parameters:
class TeacherSchedule < ActiveRecord::Base
validates_uniqueness_of :teacher_id, :scope => [:semester_id, :class_id]
end
http://apidock.com/rails/ActiveRecord/Validations/ClassMethods/validates_uniqueness_of
This should answer Greg's question.
Dont work for me, need to put scope in plural
validates_uniqueness_of :teacher_id, :scopes => [:semester_id,
:class_id]

Resources