Search code examples
ruby-on-railsbelongs-to

RoR - Validates_existence_of with nil foreign key not working


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.


Solution

  • 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)