Создание метода в модели, который возвращает новый экземпляр с заполненными дочерними элементами ‘has_many through’

#ruby-on-rails

#ruby-on-rails

Вопрос:

Впервые создаю что-либо с Ruby on Rails и немного теряюсь при реализации «has_many through».

В этом приложении у меня есть вопросы, DailyQuestionSets (на каждый день будет один DailyQuestionSet) и DailyQuestions (таблица ссылок «многие ко многим», так что в DailyQuestionSets может быть несколько вопросов.

(Я понимаю, что эти названия таблиц / моделей плохие, любые предложения по улучшению приветствуются 🙂

Я застрял на этапе создания метода в приложении DailyQuestionSet с именем get_today_dailyquestionset, который обращается к базе данных, чтобы узнать, существует ли DailyQuestionSet уже на этот день, если это не так, то создайте его и верните его свойство .questions, заполненное всеми вопросами из базы данных.

(позже я изменю это с получения всех вопросов на выбор 3 случайных вопросов каждый день)

 
class Question < ApplicationRecord
  has_many :dailyquestions, foreign_key: 'dailyquestion_id'
  has_many :dailyquestionsets, :through => :dailyquestions
  default_scope -> { order(created_at: :desc) }
end

class DailyQuestion < ApplicationRecord
  belongs_to :daily_question_set
  belongs_to :question
end

class DailyQuestionSet < ApplicationRecord
  has_many :daily_questions, foreign_key: 'question_id'
  has_many :questions, :through => :daily_questions, :source => :question

  def self.get_today_dailyquestionset

    @dailyquestionset_list = DailyQuestionSet.where('posed_date BETWEEN ? AND ?', DateTime.now.beginning_of_day, DateTime.now.end_of_day).all

    if @dailyquestionset_list.count == 0

      @dailyquestionset = DailyQuestionSet.new(posed_date: DateTime.now)

      @dailyquestionset.save

    end

    @questionlist = Question.all

    @questionlist.each do |q|
      @dailyquestionset.questions << q

    end    
    return @dailyquestionset_list[0]  
  end  
end
 

Я получаю эту ошибку, которую я интерпретирую как означающую, что объекты вопроса возвращаются из вопроса.у всех нет связанного с ними DailyQuestionSet. Что имеет смысл. Но я не могу найти способ создать отношение «многие ко многим» для каждого вопроса, прежде чем добавлять его в .массив вопросов.

 ERROR["test_create_daily_daily_question_set_if_not_already_existing", DailyQuestionSetTest, 1.0837379119993784]
 test_create_daily_daily_question_set_if_not_already_existing#DailyQuestionSetTest (1.08s)
ActiveRecord::RecordInvalid:         ActiveRecord::RecordInvalid: Validation failed: Daily question set must exist
            app/models/daily_question_set.rb:20:in `block in get_today_dailyquestionset'
            app/models/daily_question_set.rb:19:in `get_today_dailyquestionset'
            test/models/daily_question_set_test.rb:11:in `block in <class:DailyQuestionSetTest>'
 

Комментарии:

1. Вы уверены @dailyquestionset.save , что возвращение верно? возможно, какая-то ошибка не позволила сохранить его, поэтому нет идентификатора. И, если count> 0, вы никогда не устанавливаете @dailyquestionset

Ответ №1:

Да, belongs_to проверяет, существует ли связь. Вы должны добавить необязательный: true, если вы этого не хотите

 class DailyQuestion < ApplicationRecord
  belongs_to :daily_question_set, optional: true
  belongs_to :question, optional: true
end
 

https://github.com/rails/rails/issues/34454

Вы должны это проверить

 @dailyquestionset.save
 

возвращает значение true, в противном случае проверка, возможно, не прошла. Или используйте save! чтобы вызвать исключение.

Кроме того, Если @dailyquestionset_list.count > 0 , то @dailyquestionset равно нулю.

п.д.: рад помочь, если вы предоставите больше информации п.д.д.: в

  @dailyquestionset_list = DailyQuestionSet.where('posed_date BETWEEN ? AND ?', DateTime.now.beginning_of_day, DateTime.now.end_of_day).all
 

Я думаю, что так и должно быть posted_dated

и

 @dailyquestionset = DailyQuestionSet.new(posed_date: DateTime.now)

 

Но это зависит от схемы.

Комментарии:

1. Большое спасибо за супер полезные советы! Я исправил некоторые очевидные ошибки, на которые вы указали 🙂 например, проверил @dailyquestionset на nil и изменил на @dailyquestionset.save! чтобы убедиться, что сохранение posed_date на самом деле не является опечаткой, просто мое имя столбца базы данных со странным именем для того, когда был задан набор вопросов, я попытался добавить optional: true к модели DailyQuestion, но затем я получаю сообщение об ошибке «метод. вопросы не определены» Больше никаких мыслей, которые наиболее ценятся!

2. Кроме того, меня немного смущает одна вещь: как эта таблица ссылок DailyQuestions фактически используется в коде модели. Я вижу добавление вопросов в DailyQuestionSet, но на самом деле это таблица DailyQuestions, которая управляет отношением «многие ко многим». Итак, если у меня есть существующий вопрос и DailyQuestionSet, какой код был бы правильным, чтобы связать их?

3. Вы должны начать использовать byebug. Это отладочный камень, который позволяет вам остановить код прямо перед ошибкой, чтобы вы могли проверить переменные и глубже взглянуть на то, что происходит. Так что, если вы получаете «метод . ошибка «Вопросы не определены», тогда @dailyquestionset — это не то, что вы думаете. github.com/deivid-rodriguez/byebug

4. Что касается вашего другого вопроса: ключевым моментом здесь является то, что у вас есть ассоциация has_many : through . Итак, когда вы добавляете вопрос в DailyQuestionSet и сохраняете его, rails создает объект DailyQuestion, который связывает вопрос и DailyQuestionSet. guides.rubyonrails.org /…