I have the below models in a Ruby on Rails application(I am using Rails 7):
class Survey < ApplicationRecord
has_many :survey_questions, foreign_key: 'IdSurvey', dependent: :destroy
accepts_nested_attributes_for :survey_questions
self.table_name = 'Survey'
self.primary_key = 'IdSurvey'
end
class SurveyQuestion < ApplicationRecord
belongs_to :survey, foreign_key: 'IdSurvey', inverse_of: :survey_questions
has_many :survey_question_options, foreign_key: 'IdSurveyQuestion', dependent: :destroy
accepts_nested_attributes_for :survey_question_options
self.table_name = 'SurveyQuestion'
self.primary_key = 'IdSurveyQuestion'
end
class SurveyQuestionOption < ApplicationRecord
belongs_to :survey_question, foreign_key: 'IdSurveyQuestion', inverse_of: :survey_question_options
self.table_name = 'SurveyQuestionOption'
self.primary_key = 'IdSurveyQuestionOption'
end
While trying to create a new instance of Survey model including nested elements and saving it into the database I am getting the below error:
#<ActiveModel::Errors [#<ActiveModel::NestedError attribute=survey_questions.survey, type=blank, options={:message=>:required}>, #<ActiveModel::NestedError attribute=survey_questions.survey_question_options.survey_question, type=blank, options={:message=>:required}>]>
And here is how I am doing this:
irb(main):066:0> s = Survey.new(Title: 'S', survey_questions_attributes: [{Title: 'Q', survey_question_options_attributes: [{Title: 'O'}]}])
=>
#<Survey:0x00000226dea17528
...
irb(main):068:0> s.save
=> false
irb(main):069:0> s.errors
=> #<ActiveModel::Errors [#<ActiveModel::NestedError attribute=survey_questions.survey, type=blank, options={:message=>:required}>, #<ActiveModel::NestedError attribute=survey_questions.survey_question_options.survey_question, type=blank, options={:message=>:required}>]>
You need inverse_of
on both sides of the association to avoid the belongs_to
being considered blank when saving nested attributes
class Survey
has_many :survey_questions, inverse_of: :survey
end
class SurveyQuestion
belongs_to :survey, inverse_of: :survey_questions
has_many :survey_question_options, inverse_of: :survey_question
end
class SurveyQuestionOption
belongs_to :survey_question, inverse_of: :survey_question_options
end