module Sequel::Plugins::Upsert::InstanceMethods

Attributes

upsert_plugin_upserting[R]

dirty stateful attribute because we can’t pass any opts through to the _insert_dataset method

Public Instance Methods

upsert(opts = {}) click to toggle source
# File lib/sequel/plugins/upsert.rb, line 20
def upsert(opts = {})
  @upsert_plugin_upserting = true
  if postgres? || mysql?
    save(opts)
  else
    manual_upsert(opts)
  end
  load_values_from_previously_inserted_object unless id
  self
rescue Sequel::NoExistingObject
  load_values_from_previously_inserted_object
  self
ensure
  @upsert_plugin_upserting = false
end

Private Instance Methods

_insert_dataset() click to toggle source

naughty override of Sequel private method to avoid having to rewrite the whole save method logic

Calls superclass method
# File lib/sequel/plugins/upsert.rb, line 84
def _insert_dataset
  if upsert_plugin_upserting
    if postgres?
      super.insert_conflict(update: values_to_update, target: self.class.upsert_plugin_identifying_columns)
    elsif mysql?
      columns_to_update = values_to_update.keys - self.class.upsert_plugin_identifying_columns
      super.on_duplicate_key_update(*columns_to_update)
    else
      super
    end
  else
    super
  end
end
columns_to_not_update_when_exists() click to toggle source
# File lib/sequel/plugins/upsert.rb, line 115
def columns_to_not_update_when_exists
  @columns_to_not_update ||=  self.class.upsert_plugin_ignore_columns_on_update || (self.class.upsert_plugin_identifying_columns + [:created_at, self.class.primary_key]).flatten
end
columns_with_nil_values() click to toggle source
# File lib/sequel/plugins/upsert.rb, line 111
def columns_with_nil_values
  self.class.columns.each_with_object({}) {|key, hash| hash[key] = nil }
end
find_previously_inserted_object() click to toggle source
# File lib/sequel/plugins/upsert.rb, line 55
def find_previously_inserted_object
  query = self.class.upsert_plugin_identifying_columns.each_with_object({}) do | column_name, q |
    q[column_name] = values[column_name]
  end
  model.where(query).single_record
end
load_values_from_previously_inserted_object() click to toggle source
# File lib/sequel/plugins/upsert.rb, line 38
def load_values_from_previously_inserted_object
  set_primary_key_columns_from_previously_inserted_object
  refresh
end
manual_upsert(opts) click to toggle source
# File lib/sequel/plugins/upsert.rb, line 70
def manual_upsert(opts)
  # Can use slice when we drop support for Ruby 2.4
  query = values.select{ |k, _| self.class.upsert_plugin_identifying_columns.include?(k) }
  existing_record = model.where(query).single_record
  if existing_record
    existing_record.set(values_to_update)
    existing_record.save(opts)
  else
    save(opts)
  end
end
mysql?() click to toggle source
# File lib/sequel/plugins/upsert.rb, line 99
def mysql?
  model.db.adapter_scheme.to_s =~ /mysql/
end
postgres?() click to toggle source
# File lib/sequel/plugins/upsert.rb, line 103
def postgres?
  model.db.adapter_scheme.to_s =~ /postgres/
end
primary_key_columns_are_same_as_identifying_columns() click to toggle source
# File lib/sequel/plugins/upsert.rb, line 66
def primary_key_columns_are_same_as_identifying_columns
  upsert_primary_key_columns == self.class.upsert_plugin_identifying_columns.sort
end
set_primary_key_columns_from_previously_inserted_object() click to toggle source
# File lib/sequel/plugins/upsert.rb, line 43
def set_primary_key_columns_from_previously_inserted_object
  if !primary_key_columns_are_same_as_identifying_columns
    existing_record = find_previously_inserted_object
    upsert_primary_key_columns.each do | column |
      self.send("#{column}=".to_sym, existing_record[column])
    end
    # Need to clear out the _update_dataset when the NoExistingObject is thrown because
    # the ID gets incremented somewhere in the Sequel code
    @this = nil
  end
end
upsert_primary_key_columns() click to toggle source
# File lib/sequel/plugins/upsert.rb, line 62
def upsert_primary_key_columns
  @upsert_primary_key_columns ||= [*primary_key].sort
end
values_to_update() click to toggle source
# File lib/sequel/plugins/upsert.rb, line 107
def values_to_update
  columns_with_nil_values.merge(values).reject{ |k, _| columns_to_not_update_when_exists.include?(k) }
end