class Endymion::API

Attributes

datastore[R]

Public Class Methods

new(datastore) click to toggle source
# File lib/endymion/api.rb, line 13
def initialize(datastore)
  @datastore = datastore
end

Public Instance Methods

count_by_kind(kind, args={}) click to toggle source

Counts records of the specified kind that match the filters provided.

# File lib/endymion/api.rb, line 129
def count_by_kind(kind, args={})
  datastore.count(build_query(kind, args))
end
create(record) click to toggle source

Creates a record. While save delegates to a create or update based on the result of new?, this always creates. This allows you to set the key explicitly

# File lib/endymion/api.rb, line 72
def create(record)
  create_many([record]).first
end
create_many(records) click to toggle source

Create many records at once

# File lib/endymion/api.rb, line 77
def create_many(records)
  unpack_records(datastore.create(pack_records(records)))
end
defentity(kind) { |kind_spec| ... } click to toggle source
# File lib/endymion/api.rb, line 17
def defentity(kind)
  kind = Format.format_kind(kind)
  kind_spec = KindSpec.new(kind, self)
  yield(kind_spec)
  save_kind_spec(kind_spec)
  pack(kind.to_sym) {|value| pack_record((value || {}).merge(:kind => kind))}
  unpack(kind.to_sym) {|value| unpack_record((value || {}).merge(:kind => kind))}
end
delete_by_key(kind, key) click to toggle source

Removes the record stored with the given key. Returns nil no matter what.

# File lib/endymion/api.rb, line 119
def delete_by_key(kind, key)
  datastore.delete_by_key(kind, key)
end
delete_by_kind(kind, args={}) click to toggle source

Deletes all records of the specified kind that match the filters provided.

# File lib/endymion/api.rb, line 124
def delete_by_kind(kind, args={})
  datastore.delete(build_query(kind, args))
end
find_by_key(kind, key) click to toggle source

Retrieves the value associated with the given key from the datastore. nil if it doesn’t exist.

# File lib/endymion/api.rb, line 87
def find_by_key(kind, key)
  unpack_record(datastore.find_by_key(kind, key))
end
find_by_kind(kind, args={}) click to toggle source

Returns all records of the specified kind that match the filters provided.

find_by_kind(:dog) # returns all records with :kind of \"dog\"
find_by_kind(:dog, :filters => [[:name, '=', "Fido"]]) # returns all dogs whos name is Fido
find_by_kind(:dog, :filters => [[:age, '>', 2], [:age, '<', 5]]) # returns all dogs between the age of 2 and 5 (exclusive)
find_by_kind(:dog, :sorts => [[:name, :asc]]) # returns all dogs in alphebetical order of their name
find_by_kind(:dog, :sorts => [[:age, :desc], [:name, :asc]]) # returns all dogs ordered from oldest to youngest, and gos of the same age ordered by name
find_by_kind(:dog, :limit => 10) # returns upto 10 dogs in undefined order
find_by_kind(:dog, :sorts => [[:name, :asc]], :limit => 10) # returns upto the first 10 dogs in alphebetical order of their name
find_by_kind(:dog, :sorts => [[:name, :asc]], :limit => 10, :offset => 10) # returns the second set of 10 dogs in alphebetical order of their name

Filter operations and acceptable syntax:

"=" "eq"
"<" "lt"
"<=" "lte"
">" "gt"
">=" "gte"
"!=" "not"
"contains?" "contains" "in?" "in"

Sort orders and acceptable syntax:

:asc "asc" :ascending "ascending"
:desc "desc" :descending "descending"
# File lib/endymion/api.rb, line 114
def find_by_kind(kind, args={})
  unpack_records(datastore.find(build_query(kind, args)))
end
new?(record) click to toggle source

Returns true if the record is new (not saved/doesn’t have a :key), false otherwise.

# File lib/endymion/api.rb, line 82
def new?(record)
  !record.has_key?(:key)
end
pack(type, &block) click to toggle source
# File lib/endymion/api.rb, line 26
def pack(type, &block)
  packers[type] = block
end
packer_defined?(type) click to toggle source
# File lib/endymion/api.rb, line 30
def packer_defined?(type)
  packers.has_key?(type)
end
packer_for(type) click to toggle source

NOTE: these methods were marked as private in Hyperion, but were actually accessed from outside, in the FieldSpec class. Temporarily made public until things are cleand up

# File lib/endymion/api.rb, line 138
def packer_for(type)
  @packers[type]
end
save(record, attrs={}) click to toggle source

Saves a record. Any additional parameters will get merged onto the record before it is saved.

Hyperion.save({:kind => :foo})

> {:kind=>“foo”, :key=>“<generated key>”}

Hyperion.save({:kind => :foo}, :value => :bar)

> {:kind=>“foo”, :value=>:bar, :key=>“<generated key>”}

# File lib/endymion/api.rb, line 61
def save(record, attrs={})
  save_many([record.merge(attrs || {})]).first
end
save_many(records) click to toggle source

Saves multiple records at once.

# File lib/endymion/api.rb, line 66
def save_many(records)
  unpack_records(datastore.save(pack_records(records)))
end
unpack(type, &block) click to toggle source
# File lib/endymion/api.rb, line 34
def unpack(type, &block)
  unpackers[type] = block
end
unpacker_defined?(type) click to toggle source
# File lib/endymion/api.rb, line 38
def unpacker_defined?(type)
  unpackers.has_key?(type)
end
unpacker_for(type) click to toggle source
# File lib/endymion/api.rb, line 142
def unpacker_for(type)
  @unpackers[type]
end
with_datastore(name, opts={}) { || ... } click to toggle source

Assigns the datastore within the given block

# File lib/endymion/api.rb, line 43
def with_datastore(name, opts={})
  old_datastore = @datastore
  @datastore = Endymion.new_datastore(name, opts)
  begin
    yield
  rescue
    @datastore = old_datastore
    raise
  end
end

Private Instance Methods

build_filters(kind, filters) click to toggle source
# File lib/endymion/api.rb, line 164
def build_filters(kind, filters)
  (filters || []).map do |(field, operator, value)|
    operator = Format.format_operator(operator)
    packed_field = pack_field(kind, field)
    value = pack_value(kind, field, value)
    Filter.new(packed_field, operator, value)
  end
end
build_query(kind, args) click to toggle source
# File lib/endymion/api.rb, line 157
def build_query(kind, args)
  kind = Format.format_kind(kind)
  filters = build_filters(kind, args[:filters])
  sorts = build_sorts(kind, args[:sorts])
  Query.new(kind, filters, sorts, args[:limit], args[:offset])
end
build_sorts(kind, sorts) click to toggle source
# File lib/endymion/api.rb, line 173
def build_sorts(kind, sorts)
  (sorts || []).map do |(field, order)|
    field = pack_field(kind, field)
    order = Format.format_order(order)
    Sort.new(field, order)
  end
end
create_entity(record) { |record, new_record, name, spec| ... } click to toggle source
# File lib/endymion/api.rb, line 251
def create_entity(record)
  record = Format.format_record(record)
  kind = record[:kind]
  spec = kind_spec_for(kind)
  unless spec
    record
  else
    key = record[:key]
    base_record = {:kind => kind}
    base_record[:key] = key if key
    spec.fields.reduce(base_record) do |new_record, (name, spec)|
      yield(record, new_record, name, spec)
    end
  end
end
kind_spec_for(kind) click to toggle source
# File lib/endymion/api.rb, line 267
def kind_spec_for(kind)
  @kind_specs ||= {}
  @kind_specs[kind]
end
pack_field(kind, field) click to toggle source
# File lib/endymion/api.rb, line 214
def pack_field(kind, field)
  field = Format.format_field(field)
  kind_spec = kind_spec_for(kind)
  return field unless kind_spec
  field_spec = kind_spec.fields[field]
  return field unless field_spec
  return field_spec.db_name
end
pack_record(record) click to toggle source
# File lib/endymion/api.rb, line 203
def pack_record(record)
  if record
    entity = create_entity(record) do |record, entity, field, field_spec|
      value = record[field]
      entity[field_spec.db_name] = field_spec.pack(value || field_spec.default)
      entity
    end
    update_timestamps(entity)
  end
end
pack_records(records) click to toggle source
# File lib/endymion/api.rb, line 197
def pack_records(records)
  records.map do |record|
    pack_record(record)
  end
end
pack_value(kind, field, value) click to toggle source
# File lib/endymion/api.rb, line 223
def pack_value(kind, field, value)
  kind_spec = kind_spec_for(kind)
  return value unless kind_spec
  field_spec = kind_spec.fields[field]
  return value unless field_spec
  return field_spec.pack(value)
end
packers() click to toggle source
# File lib/endymion/api.rb, line 149
def packers
  @packers ||= {}
end
save_kind_spec(kind_spec) click to toggle source
# File lib/endymion/api.rb, line 272
def save_kind_spec(kind_spec)
  @kind_specs ||= {}
  @kind_specs[kind_spec.kind] = kind_spec
end
unpack_record(record) click to toggle source
# File lib/endymion/api.rb, line 187
def unpack_record(record)
  if record
    create_entity(record) do |record, entity, field, field_spec|
      value = record[field_spec.db_name]
      entity[field] = field_spec.unpack(value)
      entity
    end
  end
end
unpack_records(records) click to toggle source
# File lib/endymion/api.rb, line 181
def unpack_records(records)
  records.map do |record|
    unpack_record(record)
  end
end
unpackers() click to toggle source
# File lib/endymion/api.rb, line 153
def unpackers
  @unpackers ||= {}
end
update_created_at(record) click to toggle source
# File lib/endymion/api.rb, line 243
def update_created_at(record)
  spec = kind_spec_for(record[:kind])
  if spec && spec.fields.include?(:created_at)
    record[:created_at] = Time.now
  end
  record
end
update_timestamps(record) click to toggle source
# File lib/endymion/api.rb, line 231
def update_timestamps(record)
  new?(record) ? update_created_at(record) : update_updated_at(record)
end
update_updated_at(record) click to toggle source
# File lib/endymion/api.rb, line 235
def update_updated_at(record)
  spec = kind_spec_for(record[:kind])
  if spec && spec.fields.include?(:updated_at)
    record[:updated_at] = Time.now
  end
  record
end