module Epiphy::Repository::ClassMethods

Public Instance Methods

adapter=(adapter) click to toggle source

Assigns an adapter.

Epiphy::Repository is shipped with an adapters:

* Rethinkdb

@param adapter [Object] an object that implements

`Epiphy::Model::Adapters::Abstract` interface

@since 0.1.0

@see Epiphy::Adapter::Rethinkdb

@example

class UserRepository
  include Epiphy::Repository
end

# Adapter is set by a shared adapter by default. Unless you want 
to change, you shoul not need this
adapter = Epiphy::Adapter::Rethinkdb.new aconnection, adb
UserRepository.adapter = adapter
# File lib/epiphy/repository.rb, line 261
def adapter=(adapter)
  @adapter = adapter
end
all() click to toggle source

Returns all the persisted entities.

@return [Array<Object>] the result of the query

@since 0.1.0

@example

require 'epiphy/model'

class ArticleRepository
  include Epiphy::Repository
end

ArticleRepository.all # => [ #<Article:0x007f9b19a60098> ]
# File lib/epiphy/repository.rb, line 463
def all
  all_row = @adapter.all(collection)
  cursor = Epiphy::Repository::Cursor.new all_row do |item|
    to_entity(item)
  end
  cursor.to_a
end
clear() click to toggle source

Deletes all the records from the current collection.

Execute a ‘r.table().delete()` on RethinkDB level.

@since 0.1.0

@example

require 'epiphy/model'

class ArticleRepository
  include Epiphy::Repository
end

ArticleRepository.clear # deletes all the records
# File lib/epiphy/repository.rb, line 593
def clear
  @adapter.clear(collection)
end
count() click to toggle source

Count the entity in this collection

@param void @return Interget @api public @since 0.2.0

# File lib/epiphy/repository.rb, line 603
def count
  @adapter.count(collection)
end
create(entity) click to toggle source

Creates a record in the database for the given entity. It assigns the ‘id` attribute, in case of success.

If already persisted (‘id` present), it will try to insert use that id and will raise an error if the `id` is already exist

@param entity [#id,#id=] the entity to create

@return [Object] the entity

@since 0.1.0

@see Epiphy::Repository#persist

@example

require 'epiphy/model'

class ArticleRepository
  include Epiphy::Repository
end

article = Article.new(title: 'Introducing Epiphy::Model')
article.id # => nil

ArticleRepository.create(article) # creates a record
article.id # => 23

ArticleRepository.create(article) # no-op
# File lib/epiphy/repository.rb, line 336
def create(entity)
  #unless entity.id
  begin
    result = @adapter.create(collection, to_document(entity))
    entity.id = result
  rescue Epiphy::Model::EntityExisted => e
    raise e
  rescue RethinkDB::RqlRuntimeError => e
    raise Epiphy::Model::RuntimeError, e.message
  end
  #end
end
delete(entity) click to toggle source

Deletes a record in the database corresponding to the given entity.

If not already persisted (‘id` present) it raises an exception.

@param entity [#id] the entity to delete

@return [Object] the entity

@raise [Epiphy::Model::NonPersistedEntityError] if the given entity

wasn't already persisted.

@since 0.1.0

@see Epiphy::Model::NonPersistedEntityError

@example With a persisted entity

require 'epiphy/model'

class ArticleRepository
  include Epiphy::Repository
end

article = ArticleRepository.find(23)
article.id # => 23

ArticleRepository.delete(article) # deletes the record

@example With a non persisted entity

require 'epiphy/model'

class ArticleRepository
  include Epiphy::Repository
end

article = Article.new(title: 'Introducing Epiphy::Model')
article.id # => nil

ArticleRepository.delete(article) # raises Epiphy::Model::NonPersistedEntityError
# File lib/epiphy/repository.rb, line 439
def delete(entity)
  if entity.id
    @adapter.delete(collection, entity.id)
  else
    raise Epiphy::Model::NonPersistedEntityError
  end

  entity
end
find(id) click to toggle source

Finds an entity by its identity.

If used with a SQL database, it corresponds to the primary key.

@param id [Object] the identity of the entity

@return [Object] the result of the query

@raise [Epiphy::Model::EntityNotFound] if the entity cannot be found.

@since 0.1.0

@see Epiphy::Model::EntityNotFound

@example With a persisted entity

require 'epiphy/model'

class ArticleRepository
  include Epiphy::Repository
end

ArticleRepository.find(9) # => raises Epiphy::Model::EntityNotFound
# File lib/epiphy/repository.rb, line 493
def find(id)
  entity_id = nil
  if id.is_a? Epiphy::Entity
    raise TypeError, "Expecting an string, primitve value"
  end

  if id.is_a?(String) || id.is_a?(Integer)
    entity_id = id
  else
    entity_id = id.id if id.respond_to? :id
  end

  raise Epiphy::Model::EntityIdNotFound, "Missing entity id" if entity_id.nil?
  result = @adapter.find(collection, entity_id).tap do |record|
    raise Epiphy::Model::EntityNotFound.new unless record
  end
  to_entity(result)
end
first(order_by=:id) click to toggle source

Returns the first entity in the database.

@return [Object,nil] the result of the query

@since 0.1.0

@see Epiphy::Repository#last

@example With at least one persisted entity

require 'epiphy/model'

class ArticleRepository
  include Epiphy::Repository
end

ArticleRepository.first # => #<Article:0x007f8c71d98a28>

@example With an empty collection

require 'epiphy/model'

class ArticleRepository
  include Epiphy::Repository
end

ArticleRepository.first # => nil
# File lib/epiphy/repository.rb, line 537
def first(order_by=:id)
  result = @adapter.first(collection, order_by: order_by)
  if result
    to_entity result
  else
    result
  end
end
last(order_by=:id) click to toggle source

Returns the last entity in the database.

@return [Object,nil] the result of the query

@since 0.1.0

@see Epiphy::Repository#last

@example With at least one persisted entity

require 'epiphy/model'

class ArticleRepository
  include Epiphy::Repository
end

ArticleRepository.last # => #<Article:0x007f8c71d98a28>

@example With an empty collection

require 'epiphy/model'

class ArticleRepository
  include Epiphy::Repository
end

ArticleRepository.last # => nil
# File lib/epiphy/repository.rb, line 571
def last(order_by=:id)
  if result = @adapter.last(collection, order_by: order_by)
    to_entity result
  else
    nil
  end
end
persist(entity) click to toggle source

Creates or updates a record in the database for the given entity.

@param entity [#id, id=] the entity to persist

@return [Object] the entity

@since 0.1.0

@see Epiphy::Repository#create @see Epiphy::Repository#update

@example With a non persisted entity

require 'epiphy'

class ArticleRepository
  include Epiphy::Repository
end

article = Article.new(title: 'Introducing Epiphy::Model')
article.id # => nil

ArticleRepository.persist(article) # creates a record
article.id # => 23

@example With a persisted entity

require 'epiphy'

class ArticleRepository
  include Epiphy::Repository
end

article = ArticleRepository.find(23)
article.id # => 23

article.title = 'Launching Epiphy::Model'
ArticleRepository.persist(article) # updates the record

article = ArticleRepository.find(23)
article.title # => "Launching Epiphy::Model"
# File lib/epiphy/repository.rb, line 304
def persist(entity)
  @adapter.persist(collection, to_document(entity))
end
update(entity) click to toggle source

Updates a record in the database corresponding to the given entity.

If not already persisted (‘id` present) it raises an exception.

@param entity [#id] the entity to update

@return [Object] the entity

@raise [Epiphy::Model::NonPersistedEntityError] if the given entity

wasn't already persisted.

@since 0.1.0

@see Epiphy::Repository#persist @see Epiphy::Model::NonPersistedEntityError

@example With a persisted entity

require 'epiphy/model'

class ArticleRepository
  include Epiphy::Repository
end

article = ArticleRepository.find(23)
article.id # => 23
article.title = 'Launching Epiphy::Model'

ArticleRepository.update(article) # updates the record

@example With a non persisted entity

require 'epiphy/model'

class ArticleRepository
  include Epiphy::Repository
end

article = Article.new(title: 'Introducing Epiphy::Model')
article.id # => nil

ArticleRepository.update(article) # raises Epiphy::Model::NonPersistedEntityError
# File lib/epiphy/repository.rb, line 391
def update(entity)
  if entity.id
    @adapter.update(collection, to_document(entity))
  else
    raise Epiphy::Model::NonPersistedEntityError
  end
end

Private Instance Methods

entity_name() click to toggle source

Determine entity name for this repository @return [String] entity name

@api public @since 0.1.0

@see self#get_name

# File lib/epiphy/repository.rb, line 736
def entity_name
  name = self.to_s.split('::').last
  if name.nil?
    return nil
  end
  name[0..-11]
end
get_name() click to toggle source

Determine colleciton/table name of this repository. Note that the repository name has to be the model name, appending Repository

@return [Symbol] collection name

@api public @since 0.1.0

@see Epiphy::Adapter::Rethinkdb#get_table

# File lib/epiphy/repository.rb, line 720
def get_name
  name = self.to_s.split('::').last
  #end = Repository.length + 1
  if name.nil?
    return nil
  end
  name = name[0..-11].downcase.to_sym
end
query(to_entity: true, &blk) click to toggle source

Fabricates a query and yields the given block to access the low level APIs exposed by the query itself.

This is a Ruby private method, because we wanted to prevent outside objects to query directly the database. However, this is a public API method, and this is the only way to filter entities.

The returned query SHOULD be lazy: the entities should be fetched by the database only when needed.

The returned query SHOULD refer to the entire collection by default.

Queries can be reused and combined together. See the example below.

A repository is storage independent. All the queries are delegated to the current adapter, which is responsible to implement a querying API.

Epiphy::Model is shipped with adapter:

* RethinkDB: which yields a RethinkDB::ReQL class.

By default, all return items will be convert into its entity. The behavious can change by alter ‘to_entity` parameter

@param to_entity [Boolean] to convert the result back to a entity class or not.

@param blk [Proc] a block of code that is executed in the context of a

query.
The block will be passed two parameters. First parameter is the `reql`
which is building. the second parameter is th `r` top name space of
RethinkDB. By doing this, Repository doesn't have to include
RethinkDB::Shortcuts

@return a query, the type depends on the current adapter

@api public @since 0.1.0

@see Epiphy::Adapters::Rethinkdb

@example

require 'epiphy/model'

class ArticleRepository
  include Epiphy::Repository

  def self.most_recent_by_author(author, limit = 8)
    query do |r|
      where(author_id: author.id).
        desc(:published_at).
        limit(limit)
    end
  end

  def self.most_recent_published_by_author(author, limit = 8)
    # combine .most_recent_published_by_author and .published queries
    most_recent_by_author(author, limit).published
  end

  def self.published
    query do
      where(published: true)
    end
  end

  def self.rank
    # reuse .published, which returns a query that respond to #desc
    published.desc(:comments_count)
  end

  def self.best_article_ever
    # reuse .published, which returns a query that respond to #limit
    rank.limit(1)
  end

  def self.comments_average
    query.average(:comments_count)
  end
end
# File lib/epiphy/repository.rb, line 689
def query(to_entity: true, &blk)
  result = @adapter.query(table: collection, &blk)
  require 'pp'
  if result.is_a? RethinkDB::Cursor
    return Epiphy::Repository::Cursor.new result do |item|
      to_entity(item)
    end
  end

  if result.is_a? Array
    result.map! do |item|
      to_entity(item)
    end
  end

  if result.is_a? Hash
    return to_entity(result)
  end
  result
end
to_document(entity) click to toggle source

Convert all value of the entity into a document

@param [Epiphy::Entity] Entity @return [Hash] hash object of entity value, except the nil value

@api public @since 0.1.0

# File lib/epiphy/repository.rb, line 774
def to_document entity
  document = {}
  entity.instance_variables.each {|var| document[var.to_s.delete("@")] = entity.instance_variable_get(var) unless entity.instance_variable_get(var).nil? }
  document
end
to_entity(ahash) click to toggle source

Convert a hash into the entity object.

Note that we require a Entity class same name with Repository class, only different is the suffix Repository.

@param [Hash] value object

@return [Epiphy::Entity] Entity

@api public @since 0.1.0

# File lib/epiphy/repository.rb, line 753
def to_entity ahash
  begin 
    name = entity_name
    e = Object.const_get(name).new
    ahash.each do |k,v|
      e.send("#{k}=", v)
    end
  rescue
    raise Epiphy::Model::EntityClassNotFound
  end
  e
end