Получение ошибки базы данных при использовании find_or_initialize_by_ticker

#ruby-on-rails

#ruby-on-rails

Вопрос:

Я запускаю ассоциативный метод find_or_initialize_by_ticker и продолжаю получать

 PG::InFailedSqlTransaction: ERROR:  current transaction is aborted,
commands ignored until end of transaction block
  

У моей позиции есть атрибут stock_id, и я хочу проверить, существует ли конкретный объект stock для любой из моих позиций.

Если стандартный объект уже существует, я могу его захватить, а если нет, будет создана новая позиция, и я смогу использовать этот объект.

Я думал о написании собственного метода с расширением ассоциации, например

 has_many :positions do
  def find_or_initialize_by_ticker(ticker)
    position_with_ticker = self.select do |position|
      position.stock['symbol'] == ticker
    end
    if position_with_ticker
      position_with_ticker.first
    else
      Position.new
    end
  end
end
  

Это самый эффективный способ найти позицию?

Ответ №1:

Не могли бы вы использовать встроенный ActiveRecord #first_or_initialize ?

Он уже создан для вас, и гораздо быстрее выполнять фильтрацию в базе данных, а не возвращать все строки и затем фильтровать их вручную select (гораздо меньше данных для передачи).

То, как вы будете это использовать, зависит от того, как вы определили stock переменную:

Stock — это другая таблица

 my_model.positions
        .joins(:stock)
        .where(stock: { symbol: ticker })
        .first_or_initialize
  

Stock — это поле Postgres JSON или HSTORE

Из Active Record и PostgreSQL:

 # see docs for -> vs ->>
my_model.positions
        .where("stock->>'symbol' = ?", ticker)
        .first_or_initialize