John M L
2008-Apr-11 17:32 UTC
Validating an ActiveRecord object and its has_many :through associations
Considering an object with several has_many :through => associations, what is the ''best'' way to handle validations? As an example: class Student < ActiveRecord::Base # some attrbutes like # :name # :grade # relationships has_many :students_assignment, :dependent => :destroy has_many :assignments, :through => :students_assignment has_many :students_class, :dependent => :destroy has_many :classes, :through => :students_class has_many :students_extracurricular_activity, :dependent => :destroy has_many :extracurricular_activities, :through => :students_extracurricular_activity has_many :students_school, :dependent => :destroy has_many :students_schools, :through => :students_school end Suppose a student can''t belong to a class and extracurricular activity that occur at the same time? I figure that this validation would be best handled in the Student class since the other case would require writing validations for both classes and eca''s. Also, this is just an example. So, what if a student also can only take a :class through multiple :schools if they are of a certain :grade and only 5 students can belong to each eca? I''m trying to illustrate a complex situation where the combination of multiple associations affect the validity. So either each association has to be validated, which means processing for the most part the same validations for all associations. For instance, checking a students eca''s against the students classes (for timing conflicts) would be done twice, once from eca''s and again from classes. i would like to handle this through a validates_associated so that the Student is validated whenever an association is changed or added. However, I can''t see how this would work. To illustrate:>>ss = StudentsSchool.new(:school_id => 1, :student_id => 10)=> #<StudentsSchooll>...>>ss.student=> #<Student>...>>ss.student.students_school=> [] So the ss is still a temporary object that won''t be seen in the Student validation. Can anyone share some ideas? --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Danimal
2008-Apr-11 21:02 UTC
Re: Validating an ActiveRecord object and its has_many :through associations
With this complexity, you are best off (IMNSHO) rolling your own validation code. In the Student model, just override the "validate" method: def validate .. do all your logic here, e.g. .. errors.add("student", "this student can''t be in that class and that activity") if XYZ end Then, you set the errors hash (or array? I forget what data structure it is) if anything goes wrong. I''d start by pseudo-coding it in plain english to be sure you''ve articulated your association constraints. That call is on the model, so you get all the association goodness, like if a student has_many activities, you can do: self.activities in that call to reference the activities association for the student instance being validated. Remember, get the logic working first, then refactor later. I used to have a lot of trouble with this. I''d spend an hour mentally figuring out the "perfect" way to capture and solve a specific problem instead of doing "good enough" in 3 minutes, then refactoring the next day for 5 minutes. Good luck! -Danimal On Apr 11, 11:32 am, John M L <recaffeina...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Considering an object with several has_many :through => associations, > what is the ''best'' way to handle validations? > > As an example: > > class Student < ActiveRecord::Base > > # some attrbutes like > # :name > # :grade > > # relationships > > has_many :students_assignment, :dependent => :destroy > has_many :assignments, :through => :students_assignment > > has_many :students_class, :dependent => :destroy > has_many :classes, :through => :students_class > > has_many :students_extracurricular_activity, :dependent => :destroy > has_many :extracurricular_activities, :through > => :students_extracurricular_activity > > has_many :students_school, :dependent => :destroy > has_many :students_schools, :through => :students_school > > end > > Suppose a student can''t belong to a class and extracurricular activity > that occur at the same time? I figure that this validation would be > best handled in the Student class since the other case would require > writing validations for both classes and eca''s. Also, this is just an > example. So, what if a student also can only take a :class through > multiple :schools if they are of a certain :grade and only 5 students > can belong to each eca? > > I''m trying to illustrate a complex situation where the combination of > multiple associations affect the validity. So either each association > has to be validated, which means processing for the most part the same > validations for all associations. For instance, checking a students > eca''s against the students classes (for timing conflicts) would be > done twice, once from eca''s and again from classes. i would like to > handle this through a validates_associated so that the Student is > validated whenever an association is changed or added. However, I > can''t see how this would work. > > To illustrate: > > >>ss = StudentsSchool.new(:school_id => 1, :student_id => 10) > > => #<StudentsSchooll>...>>ss.student > => #<Student>... > >>ss.student.students_school > > => [] > > So the ss is still a temporary object that won''t be seen in the > Student validation. > > Can anyone share some ideas?--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
John M L
2008-Apr-11 21:37 UTC
Re: Validating an ActiveRecord object and its has_many :through associations
Thanks Danimal. I''m about to do the same. My main issue is figure out how to validate with associated objects that only exist in memory. I guess I have to actually attach them to the main (Student) object and then validate. John On Apr 11, 5:02 pm, Danimal <fightonfightw...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> With this complexity, you are best off (IMNSHO) rolling your own > validation code. In the Student model, just override the "validate" > method: > > def validate > .. do all your logic here, e.g. .. > errors.add("student", "this student can''t be in that class and that > activity") if XYZ > end > > Then, you set the errors hash (or array? I forget what data structure > it is) if anything goes wrong. > > I''d start by pseudo-coding it in plain english to be sure you''ve > articulated your association constraints. That call is on the model, > so you get all the association goodness, like if a student has_many > activities, you can do: self.activities in that call to reference the > activities association for the student instance being validated. > > Remember, get the logic working first, then refactor later. I used to > have a lot of trouble with this. I''d spend an hour mentally figuring > out the "perfect" way to capture and solve a specific problem instead > of doing "good enough" in 3 minutes, then refactoring the next day for > 5 minutes. > > Good luck! > > -Danimal > > On Apr 11, 11:32 am, John M L <recaffeina...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > Considering an object with several has_many :through => associations, > > what is the ''best'' way to handle validations? > > > As an example: > > > class Student < ActiveRecord::Base > > > # some attrbutes like > > # :name > > # :grade > > > # relationships > > > has_many :students_assignment, :dependent => :destroy > > has_many :assignments, :through => :students_assignment > > > has_many :students_class, :dependent => :destroy > > has_many :classes, :through => :students_class > > > has_many :students_extracurricular_activity, :dependent => :destroy > > has_many :extracurricular_activities, :through > > => :students_extracurricular_activity > > > has_many :students_school, :dependent => :destroy > > has_many :students_schools, :through => :students_school > > > end > > > Suppose a student can''t belong to a class and extracurricular activity > > that occur at the same time? I figure that this validation would be > > best handled in the Student class since the other case would require > > writing validations for both classes and eca''s. Also, this is just an > > example. So, what if a student also can only take a :class through > > multiple :schools if they are of a certain :grade and only 5 students > > can belong to each eca? > > > I''m trying to illustrate a complex situation where the combination of > > multiple associations affect the validity. So either each association > > has to be validated, which means processing for the most part the same > > validations for all associations. For instance, checking a students > > eca''s against the students classes (for timing conflicts) would be > > done twice, once from eca''s and again from classes. i would like to > > handle this through a validates_associated so that the Student is > > validated whenever an association is changed or added. However, I > > can''t see how this would work. > > > To illustrate: > > > >>ss = StudentsSchool.new(:school_id => 1, :student_id => 10) > > > => #<StudentsSchooll>...>>ss.student > > => #<Student>... > > >>ss.student.students_school > > > => [] > > > So the ss is still a temporary object that won''t be seen in the > > Student validation. > > > Can anyone share some ideas?--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---