NoBrainer

A Ruby ORM for RethinkDB

Atomic Operations

NoBrainer supports atomic operations on document attributes to avoid races during updates (e.g. incrementing a number). NoBrainer provides a natural Ruby syntax to describe atomic operations: assignments ran within a queue_atomic block are performed atomically during the next save() operation.

Examples

The following examples use the following base code:

class User
  field :num_friends, :type => Integer
  field :friend_ids,  :type => Array
  field :tags,        :type => Set

  field :field1
  field :field2
end

user = User.first

Incrementing a field

user.queue_atomic do
  user.num_friends += 1
end
user.save!

Removing items from an array

user.queue_atomic do
  user.friend_ids -= ["id1", "id2"]
end
user.save!

Adding items to a set

user.queue_atomic do
  user.tags << "red"
end
user.save!

Swapping two fields

user.queue_atomic do
  user.field1, user.field2 = user.field2, user.field1
end
user.save!

Using different fields to compute some value

user.queue_atomic do
  user.field2 = (user.num_friends + user.field1)*2
end
user.save!

Removing a field

user.queue_atomic do
  user.unset(:field1)
end
user.save!

Using a RQL value

user.queue_atomic do |r|
  user.field1 = r.expr(1+2)
end
user.save!

Operations

  • Atomic operations are performed when invoking save().
  • Multiple atomic operations can be queued.
  • Once an attribute has atomic operations queued, validations are no longer performed on that attribute.
  • Once an atomic value is queued, the attribute value cannot be read anymore.

The following describes operations that can be performed on various types:

Any types

  • instance.unset(:field) removes the specified field from the document.
  • instance.field = value assigns field to value, which can be a RQL expression, or some operation using other fields from the same document.

Array

  • values1 & values2 performs the set intersection between values1 and values2.
  • values1 | values2 performs the set union of values1 and values2.
  • values1 + values2 performs the concatenation of values1 and values2.
  • values1 - values2 performs the difference between values1 and values2.
  • values << value appends value to values.
  • values.delete(value) removes value from values.

Set

Same as Array, except all operations are done with Set semantics.

String

  • value1 + value2 performs the concatenation of the two strings.

Integer / Float

  • + - / % performs the usual numeric computations.