Уперт в Rails ActiveRecord - PullRequest
       6

Уперт в Rails ActiveRecord

28 голосов
/ 14 января 2011

Имеет ли ActiveRecord встроенную функцию upsert? Я знаю, что мог бы написать это сам, но, очевидно, не хочу, если такая вещь уже существует.

Ответы [ 6 ]

14 голосов
/ 21 июня 2012

Я только что наткнулся на эту библиотеку: https://github.com/seamusabshere/upsert

Я еще не тестировал ее, но она выглядит многообещающе

14 голосов
/ 14 января 2011

Model.find_or_initialize, вероятно, делает то, что вы хотите. Вы можете связать его с помощью save или update_attributes, если это имеет смысл.

Больше информации в Направляющих рельсов .

1 голос
/ 14 января 2011

Существует также Model.find_or_create

0 голосов
/ 25 июня 2019

В rails 6 появилась потрясающая новая функция: они добавили upsert и upsert_all к ActiveRecord

Более подробную информацию можно найти здесь https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence/ClassMethods.html#method-i-upsert_all

0 голосов
/ 22 апреля 2016

Механизм IMO Upsert требует настраиваемой конфигурации для каждой модели.

Таким образом, наилучшим решением будет реализация настраиваемого запроса SQL для модели, например

insert into <table> (<field_1>, ..., <field_n>) 
  values (<field_1_value>, ..., <field_n_value>)
on duplicate key update
  field_x = field_x_value,
  ...
  field_z = field_z_value;
0 голосов
/ 17 августа 2014

Я написал пост в блоге о том, как этого добиться. Проверьте это здесь .

Вам нужно написать расширение активной записи. Это будет выглядеть примерно так.

module ActiveRecordExtension
  extend ActiveSupport::Concern

  def self.upsert(attributes)
    begin
        create(attributes)
    rescue ActiveRecord::RecordNotUnique, PG::UniqueViolation => e
        find_by_primary_key(attributes['primary_key']).
        update(attributes)
    end
  end
end

ActiveRecord::Base.send(:include, ActiveRecordExtension)
...