Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When should I validate the presence of an ActiveRecord association object vs its id?

Suppose I have an ActiveRecord association like:

class City < ActiveRecord::Base
  belongs_to :state
end

A city without a state should be invalid. It seems that both of these are possible validations:

validates :state,    presence: true
# OR
validates :state_id, presence: true

I would guess that they are identical, since:

  • belongs_to creates methods state and state=
  • state= sets the state_id

However, I've just fixed a failing spec by changing it to check for the id instead of the object.

Are these two ways of validating both acceptable? If so, when would you use one or the other?

like image 564
Nathan Long Avatar asked Jul 27 '12 20:07

Nathan Long


People also ask

What is validation in Rails?

Rails validation defines valid states for each of your Active Record model classes. They are used to ensure that only valid details are entered into your database. Rails make it easy to add validations to your model classes and allows you to create your own validation methods as well.

What is Active Record validations?

Active Record offers many pre-defined validation helpers that you can use directly inside your class definitions. These helpers provide common validation rules. Every time a validation fails, an error is added to the object's errors collection, and this is associated with the attribute being validated.

What does Active Record base mean?

ActiveRecord::Base indicates that the ActiveRecord class or module has a static inner class called Base that you're extending.

What is custom validation in Rails?

Published Feb 02, 2018. Validation is one of the core features which rails provides. There are plenty of built in validation helpers there which helps validating our form inputs or user attributes.


2 Answers

validates :state will use the relationship from city to state (the belongs_to) along with the foreign key whereas validates :state_id alone will just use the column state_id and see if it has any value at all.

My preferred method is to validate state (the relationship) as this requires both the key and the relationship to be present.

Validating state_id will work, in that it will make sure that a state id exists, however it won't check for the validity of the code, i.e. that a state actually 'exists' for any given state key in City.

Basically if the foreign keys (for state_id) used in City all exist as actual records in State, the effect is the same. The difference would show if you had an invalid state code in state.

like image 154
Michael Durrant Avatar answered Oct 14 '22 11:10

Michael Durrant


What if you did something like

s = State.new
c = City.new
c.state = s
c.valid?

I haven't tried this but I'm guessing that, if you're checking for the presence of c.state_id, it will be missing, even though c does have a state (because the ID hasn't been generated yet, because the state hasn't been saved yet).

That is to say, if what you care about is the presence of the state, you should validate the presence of the state.

like image 23
Jacob Mattison Avatar answered Oct 14 '22 09:10

Jacob Mattison