class FrozenRecord::Base

Constants

FALSY_VALUES
FIND_BY_PATTERN

Attributes

abstract_class[RW]

Public Class Methods

abstract_class?() click to toggle source
# File lib/frozen_record/base.rb, line 92
def abstract_class?
  defined?(@abstract_class) && @abstract_class
end
add_index(attribute, unique: false) click to toggle source
# File lib/frozen_record/base.rb, line 145
def add_index(attribute, unique: false)
  index = unique ? UniqueIndex.new(self, attribute) : Index.new(self, attribute)
  self.index_definitions = index_definitions.merge(index.attribute => index).freeze
end
all()
Alias for: current_scope
attribute(attribute, klass) click to toggle source
# File lib/frozen_record/base.rb, line 150
def attribute(attribute, klass)
  self.attribute_deserializers = attribute_deserializers.merge(attribute.to_s => klass).freeze
end
attributes() click to toggle source
# File lib/frozen_record/base.rb, line 85
def attributes
  @attributes ||= begin
    load_records
    @attributes
  end
end
current_scope() click to toggle source
# File lib/frozen_record/base.rb, line 96
def current_scope
  store[:scope] ||= Scope.new(self)
end
Also aliased as: all
current_scope=(scope) click to toggle source
# File lib/frozen_record/base.rb, line 101
def current_scope=(scope)
  store[:scope] = scope
end
default_attributes() click to toggle source
# File lib/frozen_record/base.rb, line 67
def default_attributes
  _default_attributes
end
default_attributes=(default_attributes) click to toggle source
# File lib/frozen_record/base.rb, line 71
def default_attributes=(default_attributes)
  self._default_attributes = default_attributes.transform_keys(&:to_s)
end
eager_load!() click to toggle source
# File lib/frozen_record/base.rb, line 176
def eager_load!
  return if auto_reloading || abstract_class?

  load_records
end
file_path() click to toggle source
# File lib/frozen_record/base.rb, line 109
def file_path
  raise ArgumentError, "You must define `#{name}.base_path`" unless base_path
  file_path = File.join(base_path, backend.filename(name))
  if !File.exist?(file_path) && File.exist?("#{file_path}.erb")
    "#{file_path}.erb"
  else
    file_path
  end
end
find(id) click to toggle source
# File lib/frozen_record/base.rb, line 123
def find(id)
  raise RecordNotFound, "Can't lookup record without ID" unless id
  find_by(primary_key => id) or raise RecordNotFound, "Couldn't find a record with ID = #{id.inspect}"
end
find_by(criterias) click to toggle source
# File lib/frozen_record/base.rb, line 128
def find_by(criterias)
  if criterias.size == 1
    criterias.each do |attribute, value|
      attribute = attribute.to_s
      if index = index_definitions[attribute]
        load_records
        return index.lookup(value).first
      end
    end
  end
  current_scope.find_by(criterias)
end
find_by!(criterias) click to toggle source
# File lib/frozen_record/base.rb, line 141
def find_by!(criterias)
  find_by(criterias) or raise RecordNotFound, "No record matched"
end
find_by_id(id) click to toggle source
# File lib/frozen_record/base.rb, line 119
def find_by_id(id)
  find_by(primary_key => id)
end
load(attrs = {})
Alias for: new
load_records(force: false) click to toggle source
# File lib/frozen_record/base.rb, line 188
def load_records(force: false)
  if force || (auto_reloading && file_changed?)
    unload!
  end

  @records ||= begin
    records = backend.load(file_path)
    if attribute_deserializers.any? || default_attributes
      records = records.map { |r| assign_defaults!(deserialize_attributes!(r.dup)).freeze }.freeze
    end
    @attributes = list_attributes(records).freeze
    define_attribute_methods(@attributes.to_a)
    records = FrozenRecord.ignore_max_records_scan { records.map { |r| load(r) }.freeze }
    index_definitions.values.each { |index| index.build(records) }
    records
  end
end
memsize(object = self, seen = Set.new.compare_by_identity) click to toggle source
# File lib/frozen_record/base.rb, line 154
def memsize(object = self, seen = Set.new.compare_by_identity)
  return 0 unless seen.add?(object)

  size = ObjectSpace.memsize_of(object)
  object.instance_variables.each { |v| size += memsize(object.instance_variable_get(v), seen) }

  case object
  when Hash
    object.each { |k, v| size += memsize(k, seen) + memsize(v, seen) }
  when Array
    object.each { |i| size += memsize(i, seen) }
  end
  size
end
new(attrs = {}) click to toggle source
# File lib/frozen_record/base.rb, line 213
def new(attrs = {})
  load(assign_defaults!(deserialize_attributes!(attrs.transform_keys(&:to_s))))
end
Also aliased as: load
new(attrs = {}) click to toggle source
# File lib/frozen_record/base.rb, line 281
def initialize(attrs = {})
  @attributes = attrs.freeze
end
primary_key() click to toggle source
# File lib/frozen_record/base.rb, line 75
def primary_key
  _primary_key
end
primary_key=(primary_key) click to toggle source
# File lib/frozen_record/base.rb, line 79
def primary_key=(primary_key)
  self._primary_key = -primary_key.to_s
end
respond_to_missing?(name, *) click to toggle source
# File lib/frozen_record/base.rb, line 169
def respond_to_missing?(name, *)
  if name.to_s =~ FIND_BY_PATTERN
    load_records # ensure attribute methods are defined
    return true if $1.split('_and_').all? { |attr| instance_method_already_implemented?(attr) }
  end
end
scope(name, body) click to toggle source
# File lib/frozen_record/base.rb, line 206
def scope(name, body)
  singleton_class.send(:define_method, name, &body)
end
unload!() click to toggle source
# File lib/frozen_record/base.rb, line 182
def unload!
  @records = nil
  index_definitions.values.each(&:reset)
  undefine_attribute_methods
end
with_max_records_scan(value) { || ... } click to toggle source
# File lib/frozen_record/base.rb, line 59
def with_max_records_scan(value)
  previous_max_records_scan = max_records_scan
  self.max_records_scan = value
  yield
ensure
  self.max_records_scan = previous_max_records_scan
end

Private Class Methods

assign_defaults!(record) click to toggle source
# File lib/frozen_record/base.rb, line 229
def assign_defaults!(record)
  if default_attributes
    default_attributes.each do |key, value|
      unless record.key?(key)
        record[key] = value
      end
    end
  end

  record
end
deserialize_attributes!(record) click to toggle source
# File lib/frozen_record/base.rb, line 241
def deserialize_attributes!(record)
  if attribute_deserializers.any?
    attribute_deserializers.each do |key, deserializer|
      if record.key?(key)
        record[key] = deserializer.load(record[key])
      end
    end
  end

  record
end
dynamic_match(expression, values, bang) click to toggle source
# File lib/frozen_record/base.rb, line 260
def dynamic_match(expression, values, bang)
  results = where(expression.split('_and_'.freeze).zip(values))
  bang ? results.first! : results.first
end
file_changed?() click to toggle source
# File lib/frozen_record/base.rb, line 219
def file_changed?
  last_mtime = @file_mtime
  @file_mtime = File.mtime(file_path)
  last_mtime != @file_mtime
end
list_attributes(records) click to toggle source
# File lib/frozen_record/base.rb, line 265
def list_attributes(records)
  attributes = Set.new
  records.each do |record|
    record.each_key do |key|
      attributes.add(key)
    end
  end
  attributes
end
method_missing(name, *args) click to toggle source
Calls superclass method
# File lib/frozen_record/base.rb, line 253
def method_missing(name, *args)
  if name.to_s =~ FIND_BY_PATTERN
    return dynamic_match($1, args, $2.present?)
  end
  super
end
store() click to toggle source
# File lib/frozen_record/base.rb, line 225
def store
  @store ||= ThreadSafeStorage.new(name)
end

Public Instance Methods

==(other) click to toggle source
Calls superclass method
# File lib/frozen_record/base.rb, line 298
def ==(other)
  super || other.is_a?(self.class) && !id.nil? && other.id == id
end
[](attr) click to toggle source
# File lib/frozen_record/base.rb, line 293
def [](attr)
  @attributes[attr.to_s]
end
Also aliased as: attribute
attribute(attr)
Alias for: []
attributes() click to toggle source
# File lib/frozen_record/base.rb, line 285
def attributes
  @attributes.dup
end
id() click to toggle source
# File lib/frozen_record/base.rb, line 289
def id
  self[self.class.primary_key]
end
persisted?() click to toggle source
# File lib/frozen_record/base.rb, line 302
def persisted?
  true
end
to_key() click to toggle source
# File lib/frozen_record/base.rb, line 306
def to_key
  [id]
end

Private Instance Methods

attribute?(attribute_name) click to toggle source
# File lib/frozen_record/base.rb, line 312
def attribute?(attribute_name)
  !FALSY_VALUES.include?(self[attribute_name]) && self[attribute_name].present?
end
attribute_method?(attribute_name) click to toggle source
# File lib/frozen_record/base.rb, line 316
def attribute_method?(attribute_name)
  respond_to_without_attributes?(:attributes) && self.class.attributes.include?(attribute_name)
end