module Switchman::ActiveRecord::Base

Public Class Methods

included(klass) click to toggle source
# File lib/switchman/active_record/base.rb, line 82
def self.included(klass)
  klass.singleton_class.prepend(ClassMethods)
  klass.set_callback(:initialize, :before) do
    @shard ||= if self.class.sharded_primary_key?
                 Shard.shard_for(self[self.class.primary_key], Shard.current(self.class.connection_classes))
               else
                 Shard.current(self.class.connection_classes)
               end
  end
end

Public Instance Methods

clone() click to toggle source
Calls superclass method
# File lib/switchman/active_record/base.rb, line 122
def clone
  result = super
  # TODO: adjust foreign keys
  # don't use the setter, cause the foreign keys are already
  # relative to this shard
  result.instance_variable_set(:@shard, shard)
  result
end
destroy() click to toggle source
Calls superclass method
# File lib/switchman/active_record/base.rb, line 118
def destroy
  shard.activate(self.class.connection_classes) { super }
end
hash() click to toggle source
Calls superclass method
# File lib/switchman/active_record/base.rb, line 137
def hash
  self.class.sharded_primary_key? ? self.class.hash ^ global_id.hash : super
end
initialize_dup(*args) click to toggle source
Calls superclass method
# File lib/switchman/active_record/base.rb, line 146
def initialize_dup(*args)
  copy = super
  @shard_set_in_stone = false
  copy
end
quoted_id() click to toggle source
Calls superclass method
# File lib/switchman/active_record/base.rb, line 152
def quoted_id
  return super unless self.class.sharded_primary_key?

  # do this the Rails 4.2 way, so that if Shard.current != self.shard, the id gets transposed
  self.class.connection.quote(id)
end
save(*, **) click to toggle source
Calls superclass method
# File lib/switchman/active_record/base.rb, line 108
def save(*, **)
  @shard_set_in_stone = true
  (self.class.current_scope || self.class.default_scoped).shard(shard, :implicit).scoping { super }
end
save!(*, **) click to toggle source
Calls superclass method
# File lib/switchman/active_record/base.rb, line 113
def save!(*, **)
  @shard_set_in_stone = true
  (self.class.current_scope || self.class.default_scoped).shard(shard, :implicit).scoping { super }
end
shard() click to toggle source
# File lib/switchman/active_record/base.rb, line 93
def shard
  @shard || Shard.current(self.class.connection_classes) || Shard.default
end
shard=(new_shard) click to toggle source
# File lib/switchman/active_record/base.rb, line 97
def shard=(new_shard)
  raise ::ActiveRecord::ReadOnlyRecord if !new_record? || @shard_set_in_stone

  return if shard == new_shard

  attributes.each do |attr, value|
    self[attr] = Shard.relative_id_for(value, shard, new_shard) if self.class.sharded_column?(attr)
  end
  @shard = new_shard
end
to_param() click to toggle source
# File lib/switchman/active_record/base.rb, line 141
def to_param
  short_id = Shard.short_id_for(id)
  short_id&.to_s
end
transaction(**kwargs, &block) click to toggle source
# File lib/switchman/active_record/base.rb, line 131
def transaction(**kwargs, &block)
  shard.activate(self.class.connection_classes) do
    self.class.transaction(**kwargs, &block)
  end
end
update_columns(*) click to toggle source
Calls superclass method
# File lib/switchman/active_record/base.rb, line 159
def update_columns(*)
  db = Shard.current(self.class.connection_classes).database_server
  if ::GuardRail.environment == db.guard_rail_environment
    super
  else
    db.unguard { super }
  end
end

Protected Instance Methods

connection_classes_for_reflection(reflection) click to toggle source

see also AttributeMethods#connection_classes_code_for_reflection

# File lib/switchman/active_record/base.rb, line 171
def connection_classes_for_reflection(reflection)
  if reflection
    if reflection.options[:polymorphic]
      begin
        read_attribute(reflection.foreign_type)&.constantize&.connection_classes
      rescue NameError
        # in case someone is abusing foreign_type to not point to an actual class
        ::ActiveRecord::Base
      end
    else
      # otherwise we can just return a symbol for the statically known type of the association
      reflection.klass.connection_classes
    end
  else
    connection_classes
  end
end