Reputation: 8083
I created an index in my migrations:
add_index "enrollments", ["student_id", "lecture_id"], :name => "index_enrollments_on_student_id_and_lecture_id", :unique => true
How is it possible to validate this pair of keys in Rails? I tried:
validates_uniqueness_of :enrollment_id, :scope => [:student_id, :lecture_id]
But it doesn't work properly.
Also, I need to find out in a view, if this key already exists, or if it is possible to create a new entry.
Upvotes: 1
Views: 1789
Reputation: 11
Sorry for opening an old thread but since it's 2011 and I still couldn't find a proper validator, I created one myself:
class UniqueSetValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
setup record
record.errors[attribute] << "- collection of fields [" + @fields + "] is not unique" if record.class.count(:conditions => @conditions) > 0
end
def check_validity!
raise ArgumentError, "Must contain an array of field names' symbols" unless options[:in] && options[:in].respond_to?(:each)
end
private
def setup record
conditions = []
fields = []
options[:in].each do |field|
conditions |= [ field.to_s + " = '" + record[field].to_s + "'" ]
fields |= [ field.to_s ]
end
@conditions = conditions.join(" AND ")
@fields = fields.join(", ")
end
end
It seems to work to me. To use it paste the code into:
your_rails_app/lib/unique_set_validator.rb
and enable it in:
your_rails_app/config/application.rb
by adding this line:
config.autoload_paths += %W( #{config.root}/lib )
Then you can simply use it in your model:
validates :field, :unique_set => [ :field, :field2 ]
It will validate the uniqueness of pair [ :field, :field2 ], and any error would be returned to :field. I haven't tried but it should work for more that 2 fields.
I hope that I didn't messed up anything, and that this will help someone. :)
Upvotes: 1
Reputation: 16339
Try this!
validates_uniqueness_of :enrollment_id, student_id, :scope => [:student_id, :lecture_id], :lecture_id], :message => "combination of enrollment, student and lecture should be unique."
If combination of student and lecture is not unique than you will get message in your error messages.
Update:
validates_uniqueness_of :student_id, :scope => [:lecture_id], :message => "combination of student and lecture should be unique."
The way voldy define in answer that's the correct way.
Upvotes: 0
Reputation: 12868
class Enrollment < ActiveRecord::Base
validates_uniqueness_of :student_id, :scope => :lecture_id
end
If you want to determine in the view before submitting new enrollment that this pair exists then you can use ajax request (I prefer RJS with JQuery) and check it with:
class Enrollment < ActiveRecord::Base
def self.pair_exists?(student_id, lecture_id)
Enrollment.find_all_by_student_id_and_lecture_id(student_id, lecture_id).any?
end
end
Hope this will help you.
Upvotes: 3