Rails - how do I validate existence of a row referenced by foreign key

◇◆丶佛笑我妖孽 提交于 2020-01-01 04:12:20

问题


Given that the "Rails Way" seems to be not to use foreign key constraints, I'm looking for an alternative that will allow me to validate that the row a foreign key references does in fact exist in TableA before I save an object in TableB with table_a_id.

The only resource I've found to do this so far (can't find a link to the blog post it was mentioned in, was dated 2007) doesn't appear to be compatible with Rails 3.2, so can anyone suggest a way of doing this?

I'm currently looking at creating a validator to manually assign to the relevant attributes in my models, but I can't work out how to do it with validate_each(object, attribute, value).


回答1:


There is a plugin that helps you with this for belongs_to associations: Validates existence of. But, maybe you can add your own validation? What about something like this:

# Assuming your foreign key is user_id (which references the table User)
validate :user_id_exists

def user_id_exists
  return false if User.find_by_id(self.user_id).nil?
end



回答2:


Simply use like below,

validates :user, presence: true

It will automatically check the existence of user record in db.

Reference from the Active Record Validation - presence:

If you want to be sure that an association is present, you'll need to test whether the associated object itself is present, and not the foreign key used to map the association. This way, it is not only checked that the foreign key is not empty but also that the referenced object exists.




回答3:


I had problems with this piece of code:

return false if User.find(self.user_id).nil?

I had to catch the ActiveRecord exception when no matching record was found. nil? does not work when no record is found; the exception is thrown before nil? is executed.

# Assuming your foreign key is user_id (which references the table User)
validate :user_id_exists

def user_id_exists
  begin
    User.find(self.user_id)
  rescue ActiveRecord::RecordNotFound
    errors.add(:user_id, "user_id foreign key must exist")
    false
  end
end

This is useful when you use invalid? assertions in unit tests.

request.user_id = unknown
assert request.invalid?

request.user_id = 1
assert request.valid?



回答4:


Note that as of Rails 3.2, the validates_presence_of works exactly the way you want it to in this case and you don't have to build a complicated structure like the above answers or even use the nice validates_existence_of gem.




回答5:


I dislike exceptions. I solved this problem by doing this:

class Foo < ActiveRecord::Base

    validate :bar_exists

    protected

    def bar_exists
        if !User.where(bar_id: self.bar_id).exists? then
            errors.add(:bar_id, 'A valid bar_id is valid.')
        end
    end

end



回答6:


You need to specify the inverse_of option and validate that it's presence is true.

From the Active Record Validations Guide:

In order to validate associated records whose presence is required, you must specify the :inverse_of option for the association



来源:https://stackoverflow.com/questions/11062258/rails-how-do-i-validate-existence-of-a-row-referenced-by-foreign-key

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!