class Endymion::API
Attributes
Public Class Methods
# File lib/endymion/api.rb, line 13 def initialize(datastore) @datastore = datastore end
Public Instance Methods
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
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 at once
# File lib/endymion/api.rb, line 77 def create_many(records) unpack_records(datastore.create(pack_records(records))) end
# 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
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
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
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
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
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
# File lib/endymion/api.rb, line 26 def pack(type, &block) packers[type] = block end
# File lib/endymion/api.rb, line 30 def packer_defined?(type) packers.has_key?(type) end
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
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
Saves multiple records at once.
# File lib/endymion/api.rb, line 66 def save_many(records) unpack_records(datastore.save(pack_records(records))) end
# File lib/endymion/api.rb, line 34 def unpack(type, &block) unpackers[type] = block end
# File lib/endymion/api.rb, line 38 def unpacker_defined?(type) unpackers.has_key?(type) end
# File lib/endymion/api.rb, line 142 def unpacker_for(type) @unpackers[type] end
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
# 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
# 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
# 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
# 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
# File lib/endymion/api.rb, line 267 def kind_spec_for(kind) @kind_specs ||= {} @kind_specs[kind] end
# 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
# 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
# File lib/endymion/api.rb, line 197 def pack_records(records) records.map do |record| pack_record(record) end end
# 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
# File lib/endymion/api.rb, line 149 def packers @packers ||= {} end
# File lib/endymion/api.rb, line 272 def save_kind_spec(kind_spec) @kind_specs ||= {} @kind_specs[kind_spec.kind] = kind_spec end
# 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
# File lib/endymion/api.rb, line 181 def unpack_records(records) records.map do |record| unpack_record(record) end end
# File lib/endymion/api.rb, line 153 def unpackers @unpackers ||= {} end
# 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
# File lib/endymion/api.rb, line 231 def update_timestamps(record) new?(record) ? update_created_at(record) : update_updated_at(record) end
# 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