I have a Rails 3.1 project with multi-level nested forms which are reused.
For instance, a Teacher has a nested Being.
class Teacher < ActiveRecord::Base
has_one :being
accepts_nested_attributes_for :being
end
An Entrant also has a nested Being
class Entrant < ActiveRecord::Base
has_one :being
accepts_nested_attributes_for :being
end
I would like to be able to validate birthdays (in the being model), but only if the parent of being is Entrant.
In the being model:
attr_accessor :no_birthday
validates :birthday, :presence => {:message => 'Birthday is required to enter classes.'}, :unless => :no_birthday?
def no_birthday?
unless self.no_birthday
errors.add(:entrant, "Birthday is required.")
end
end
In the form (teacher version only)
<%= hidden_field_tag 'no_birthday', "1" %>
And, just in case, in the teacher_controller:
def create
...
@teacher = Teacher.new(params[:teacher])
@teacher.being.no_birthday = 1
...
end
Somehow, I am very far from the mark. I can make the validation work for everybody, or nobody. I feel like there is a simple solution running parallel to me. Anybody know what that may be?
So, a few problems with the above approach:
1) the validation line. while it seems like :unless should be a real thing, it doesn’t seem to be the case. reformat as an :if statement (in the being model):
I also changed the name of the method in the model to make better english sense as an if instead of unless.
2) I can solve the problem by setting an accessor from the required controllers. So, one parent’s controller will set the accessor to true, and another will not. No hidden form fields weirdness or any of the other random approaches I was looking for:
parent #1’s create controller, as an example:
the other parent will simply not have this accessor set at all.
Of course, I will have to create an appropriate accessor for the being model or the whole thing will error out:
And now, it all works. Teachers don’t need birthdays and entrants do. Finally both parents can get along.