I am using the validates_existence_of gem. It works well except when I want to allow my foreign key to be nil.
Here are my models for User and Project. A project belongs_to a user and a contributor (a contributor is also a user), but the contributor can be nil.
Here is my user model:
class User < ActiveRecord::Base
attr_accessible :first_name, :last_name
has_many :projects, :dependent => :destroy
has_many :user_trimester_statuses, :dependent => :destroy
end
And here is my project model:
class Project < ActiveRecord::Base
attr_accessible :added, :amount, :contributor_id, :label, :ref, :trimester_id, :user_id
belongs_to :user
belongs_to :contributor, :class_name => 'User'
belongs_to :trimester
validates :user, :existence => { :both => false }
validates :trimester, :existence => { :both => false }
validates :contributor, :existence => { :allow_nil => true, :both => false }
end
When I try to add a new project, I have an error if the user_id or trimester_id field is blank or invalid. But for the contributor_id field, there is no error thrown if the field is invalid. It goes through either way (valid, invalid, or nil).
What am I doing wrong? I am using ruby 2.0.0p0 and rails 3.2.13.
It looks like there is an open bug about this in the project.
https://github.com/perfectline/validates_existence/issues/15
You may have to write a simple custom validator for this case until this gets fixed. (or dig in and see if you can fix the issue yourself)
UPDATE: I just cloned the project and wrote a test to see what the issue was. It seems that when you add the allow_nil, the existence validator doesn't get called at all. I'm not sure why that is, but in the meantime, you can work around the bug in an easy way, by using a proc. instead of
validates :contributor, :existence => { :allow_nil => true, :both => false }
this would get the job done
validates_existence_of :contributor, :unless => Proc.new { |obj| obj.contributor_id.blank? }
I was able to prove that in my test case. (I went with the 'validates_existence_of' method, instead of 'validates', because I thought it was cleaner in this case)