module NoBrainer::Document::AtomicOps

Public Instance Methods

_is_attribute_touched?(name) click to toggle source
# File lib/no_brainer/document/atomic_ops.rb, line 158
def _is_attribute_touched?(name)
  @_touched_attributes.include?(name.to_s)
end
_read_attribute(name) click to toggle source
Calls superclass method
# File lib/no_brainer/document/atomic_ops.rb, line 186
def _read_attribute(name)
  return super if name == self.class.pk_name

  ensure_exclusive_atomic!
  return super unless in_atomic?

  # If we are missing fields, it's okay, we'll assume nil.
  value = missing_field?(name) ? nil : super

  case value
  when PendingAtomicContainer then value
  when PendingAtomicUnset     then raise "Attribute `#{name}' is unset"
  when PendingAtomic          then value.dup
  else PendingAtomic._new(self, name, value, _is_attribute_touched?(name))
  end
end
_touch_attribute(name) click to toggle source
# File lib/no_brainer/document/atomic_ops.rb, line 151
def _touch_attribute(name)
  # The difference with dirty tracking and this is that dirty tracking does
  # not take into account fields that are set with their old value, whereas the
  # touched attribute does.
  @_touched_attributes << name.to_s
end
_write_attribute(name, value) click to toggle source
Calls superclass method
# File lib/no_brainer/document/atomic_ops.rb, line 203
def _write_attribute(name, value)
  ensure_exclusive_atomic!

  case [in_atomic?, value.is_a?(PendingAtomic)]
  when [true, false]  then raise NoBrainer::Error::AtomicBlock.new('Avoid the use of atomic blocks for non atomic operations')
  when [false, true]  then raise NoBrainer::Error::AtomicBlock.new('Use atomic blocks for atomic operations')
  when [true, true]   then super.tap { _touch_attribute(name) }
  when [false, false] then super.tap { _touch_attribute(name) }
  end
end
assign_attributes(attrs, options={}) click to toggle source
Calls superclass method
# File lib/no_brainer/document/atomic_ops.rb, line 214
def assign_attributes(attrs, options={})
  ensure_exclusive_atomic!
  super
end
clear_dirtiness(options={}) click to toggle source
Calls superclass method
# File lib/no_brainer/document/atomic_ops.rb, line 146
def clear_dirtiness(options={})
  super
  @_touched_attributes = Set.new
end
ensure_exclusive_atomic!() click to toggle source
# File lib/no_brainer/document/atomic_ops.rb, line 171
def ensure_exclusive_atomic!
  raise NoBrainer::Error::AtomicBlock.new('You may not access other documents within an atomic block') if in_other_atomic?
end
in_atomic?() click to toggle source
# File lib/no_brainer/document/atomic_ops.rb, line 162
def in_atomic?
  !!Thread.current[:nobrainer_atomic]
end
in_other_atomic?() click to toggle source
# File lib/no_brainer/document/atomic_ops.rb, line 166
def in_other_atomic?
  v = Thread.current[:nobrainer_atomic]
  !v.nil? && !v.equal?(self)
end
queue_atomic(&block) click to toggle source
# File lib/no_brainer/document/atomic_ops.rb, line 175
def queue_atomic(&block)
  ensure_exclusive_atomic!

  begin
    old_atomic, Thread.current[:nobrainer_atomic] = Thread.current[:nobrainer_atomic], self
    block.call(RethinkDB::RQL.new)
  ensure
    Thread.current[:nobrainer_atomic] = old_atomic
  end
end
reload(*) click to toggle source
Calls superclass method
# File lib/no_brainer/document/atomic_ops.rb, line 237
def reload(*)
  raise NoBrainer::Error::AtomicBlock.new('You may not reload fields within an atomic block') if in_atomic?
  super
end
save?(options={}) click to toggle source
Calls superclass method
# File lib/no_brainer/document/atomic_ops.rb, line 224
def save?(options={})
  # TODO allow reload => true as an option to save+reload in a single op.
  raise NoBrainer::Error::AtomicBlock.new('You may persist documents only outside of queue_atomic blocks') if in_atomic?
  super.tap do |saved|
    if saved
      @_attributes.each do |attr, value|
        next unless value.is_a?(PendingAtomic)
        @_attributes[attr] = value.class.new(self, attr, nil, false, value.type)
      end
    end
  end
end
unset(attr) click to toggle source
# File lib/no_brainer/document/atomic_ops.rb, line 219
def unset(attr)
  return queue_atomic { unset(attr) } unless in_atomic?
  _write_attribute(attr, PendingAtomicUnset.new(self, attr, nil, true, nil))
end