Модель недействительна, потому что внешний ключ не существует при его создании - PullRequest
0 голосов
/ 10 января 2020

У меня есть таблица user и две другие таблицы, каждая из которых имеет внешние ключи для поля id таблицы user. Когда я создаю пользователя, я хотел бы инициализировать запись во всех трех таблицах, но у меня возникают проблемы с этим. Запись user в конечном итоге создается, но не записи в двух других таблицах. После некоторой отладки я обнаружил, что эти модели не были сохранены, потому что они были недействительными. В сообщении об ошибке сказано: User must exist. Я пытаюсь выполнить sh инициализацию внутри метода create:

  def create
    logger.info "inside sessions create"
    # how do I save user first, THEN create a record associated with user in 2 tables ? 
    User.where(:id => auth_hash.uid).first_or_create do |user| # finds the matching record in users table
        user.name = auth_hash.info.name
        user.id = auth_hash.uid
        user.token = auth_hash.credentials.token
        user.secret = auth_hash.credentials.secret
      @tweetstore = Tweetstore.new() # Record I'd like to save in Table with Foreign KEY
      @tweetidstore = Tweetidstore.new() # Another Record I'd like to save in a Table with Foreign KEY
      istsvalid = @tweetstore.valid? # returns false
      istsidvalid = @tweetidstore.valid?
      error = @tweetstore.errors.full_messages #USER MUST EXIST
      @tweetstore[:user_id] = auth_hash.uid
      @tweetidstore[:user_id] = auth_hash.uid
      is_tweetstore_save = @tweetstore.save # false
      is_tweet_idstore_save = @tweetidstore.save
    end
    session[:user_id] = auth_hash.uid
    redirect_to '/'
  end

Как мне реструктурировать мой код так, чтобы к моменту инициализации других зависимых таблиц существовал User? Я попытался обойти проблему, добавив параметр optional к моделям (например, belongs_to :user, optional: true), но затем я получил другую ошибку: QLite3::ConstraintException: FOREIGN KEY constraint failed Я новичок ie в Ruby, поэтому, пожалуйста, ELI5

Ответы [ 3 ]

0 голосов
/ 10 января 2020

попробуйте это:

def create
  ...
  #user.id = auth_hash.uid <---- do not set this
  ...
  @tweetstore[:user_id] = user.id
  @tweetidstore[:user_id] = user.id
  ...
0 голосов
/ 10 января 2020

Я отказался от метода first_or_create и просто включил условие существования записи. Я не уверен, когда пользователь сохранен в блоке where, который я использовал выше, поэтому я явно сохранил его перед сохранением записей в моих зависимых таблицах.

if !User.exists?(auth_hash.uid)
  @user = User.new()
  @user.name = auth_hash.info.name
    @user.id = auth_hash.uid
    @user.token = auth_hash.credentials.token
    @user.secret = auth_hash.credentials.secret
  is_user_save = @user.save
  @tweetstore = Tweetstore.new()
  @tweetidstore = Tweetidstore.new()
  @tweetstore[:user_id] = auth_hash.uid
  @tweetidstore[:user_id] = auth_hash.uid
  is_tweetstore_save = @tweetstore.save
  is_tweet_idstore_save = @tweetidstore.save
end
0 голосов
/ 10 января 2020

Рассмотрите возможность использования транзакций, когда вам нужно создать зависимые модели. В случае сбоя одной из вставок разрешите откат всего, что было вставлено в БД до этого.

Также вы должны использовать user.id, а не auth_hash.uid ex.

@tweetstore[:user_id] = auth_hash.uid

должно быть

@tweetstore[:user_id] = user.id

Также

istsvalid = @tweetstore.valid? # returns false значение false, поскольку оно еще не сохранено в базе данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...