#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