Class: Guacamole::DocumentModelMapper

Inherits:
Object
  • Object
show all
Defined in:
lib/guacamole/document_model_mapper.rb

Overview

Note:

If you plan to bring your own DocumentModelMapper please consider using an IdentityMap.

This is the default mapper class to map between Ashikawa::Core::Document and Guacamole::Model instances.

If you want to build your own mapper, you have to build at least the document_to_model and model_to_document methods.

Defined Under Namespace

Classes: Attribute

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model_class, identity_map = IdentityMap) ⇒ DocumentModelMapper

Create a new instance of the mapper

You have to provide the model class you want to map to. The Document class is always Ashikawa::Core::Document

Parameters:

  • model_class (Class)


109
110
111
112
113
114
# File 'lib/guacamole/document_model_mapper.rb', line 109

def initialize(model_class, identity_map = IdentityMap)
  @model_class          = model_class
  @identity_map         = identity_map
  @models_to_embed      = []
  @attributes           = []
end

Instance Attribute Details

#attributesArray<Attribute> (readonly)

The list of Attributes to treat specially during the mapping process

Returns:

  • (Array<Attribute>)

    The list of special attributes



101
102
103
# File 'lib/guacamole/document_model_mapper.rb', line 101

def attributes
  @attributes
end

#model_classclass (readonly)

The class to map to

Returns:

  • (class)

    The class to map to



91
92
93
# File 'lib/guacamole/document_model_mapper.rb', line 91

def model_class
  @model_class
end

#models_to_embedArray (readonly)

The arrays embedded in this model

Returns:

  • (Array)

    An array of embedded models



96
97
98
# File 'lib/guacamole/document_model_mapper.rb', line 96

def models_to_embed
  @models_to_embed
end

Class Method Details

.collection_for(model_name) ⇒ class

Note:

This is an class level alias for #collection_for

construct the collection class for a given model name.

Examples:

collection_class = collection_for(:user)
collection_class == userscollection # would be true

Parameters:

  • model_name (symbol, string)

    the name of the model

Returns:

  • (class)

    the collection class for the given model name



126
127
128
# File 'lib/guacamole/document_model_mapper.rb', line 126

def collection_for(model_name)
  "#{model_name.to_s.classify.pluralize}Collection".constantize
end

Instance Method Details

#attribute(attribute_name, options = {}) ⇒ Object

Mark an attribute of the model to be specially treated during mapping

Examples:

Define a relation via an Edge in a Graph

class Authorship
  include Guacamole::Edge

  from :users
  to :posts
end

class BlogpostsCollection
  include Guacamole::Collection

  map do
    attribute :author, via: Authorship
  end
end

Parameters:

  • attribute_name (Symbol)

    The name of the model attribute

  • options (Hash) (defaults to: {})

    Additional options to configure the mapping process

Options Hash (options):

  • :via (Edge)

    The Edge class this attribute relates to



233
234
235
# File 'lib/guacamole/document_model_mapper.rb', line 233

def attribute(attribute_name, options = {})
  @attributes << Attribute.new(attribute_name, options)
end

#collection_for(model_name = model_class.name) ⇒ class

TODO:

As of now this is some kind of placeholder method. As soon as we implement the configuration of the mapping (#12) this will change. Still the Guacamole::DocumentModelMapper seems to be a good place for this functionality.

construct the collection class for a given model name.

Examples:

collection_class = collection_for(:user)
collection_class == userscollection # would be true

Parameters:

  • model_name (symbol, string) (defaults to: model_class.name)

    the name of the model

Returns:

  • (class)

    the collection class for the given model name



142
143
144
# File 'lib/guacamole/document_model_mapper.rb', line 142

def collection_for(model_name = model_class.name)
  self.class.collection_for model_name
end

#document_to_model(document) ⇒ Model

Map a document to a model

Sets the revision, key and all attributes on the model

Parameters:

  • document (Ashikawa::Core::Document)

Returns:

  • (Model)

    the resulting model with the given Model class



152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/guacamole/document_model_mapper.rb', line 152

def document_to_model(document)
  identity_map.retrieve_or_store model_class, document.key do
    model = model_class.new(document.to_h)

    model.key = document.key
    model.rev = document.revision

    handle_related_documents(model)

    model
  end
end

#edge_attributesArray<Attribute>

Returns a list of attributes that have an Edge class configured

Returns:

  • (Array<Attribute>)

    A list of attributes which all have an Edge class



240
241
242
# File 'lib/guacamole/document_model_mapper.rb', line 240

def edge_attributes
  attributes.select(&:map_via_edge?)
end

#embeds(model_name) ⇒ Object

Declare a model to be embedded

With embeds you can specify that the document in the collection embeds a document that should be mapped to a certain model. Your model has to specify an attribute with the type Array (of this model).

Examples:

A blogpost with embedded comments

class BlogpostsCollection
  include Guacamole::Collection

  map do
    embeds :comments
  end
end

class Blogpost
  include Guacamole::Model

  attribute :comments, Array[Comment]
end

class Comment
  include Guacamole::Model
end

blogpost = BlogpostsCollection.find('12313121')
p blogpost.comments #=> An Array of Comments

Parameters:

  • model_name (Symbol)

    Pluralized name of the model class to embed



209
210
211
# File 'lib/guacamole/document_model_mapper.rb', line 209

def embeds(model_name)
  @models_to_embed << model_name
end

#model_to_document(model) ⇒ Ashikawa::Core::Document

Map a model to a document

This will include all embedded models

Parameters:

Returns:

  • (Ashikawa::Core::Document)

    the resulting document



171
172
173
174
175
176
177
178
# File 'lib/guacamole/document_model_mapper.rb', line 171

def model_to_document(model)
  document = model.attributes.dup.except(:key, :rev)

  handle_embedded_models(model, document)
  handle_related_models(document)

  document
end

#responsible_for?(model) ⇒ Boolean

Is this Mapper instance responsible for mapping the given model

Parameters:

  • model (Model)

    The model to check against

Returns:

  • (Boolean)

    True if the given model is an instance of #model_class. False if not.



248
249
250
# File 'lib/guacamole/document_model_mapper.rb', line 248

def responsible_for?(model)
  model.instance_of?(model_class)
end