Examples

Existing open source connectors

Code samples

Implementing specific mapping

Most of the mappings can and should be done with the HashMapper gem, including the use of after_(de)normalize and before_(de)normalize. But sometimes they can't, or it would be too ugly. In those cases, you can overload the framework mapping methods:

class Entities::Journal < Maestrano::Connector::Rails::Entity
	def map_to_external(entity)
		mapped_entity = super
		#Do something
	end
	
	def map_to_connec(entity)
		mapped_entity = super
		#Do something
	end
end

You can do pretty much what you need in it, just remember to call super at some point to insure maintainability with the framework.

 Complex entity version
class Entities::SubEntities::Bill < Maestrano::Connector::Rails::SubEntityBase	
	def map_to(name, entity)
		# Name is the name of the entity you're mapping to
		mapped_entity = super
		# Do something
	end
end

References between entities

If you have entities that reference each other by id, you'll need to declare it in the entity model:

class Entities::People < Maestrano::Connector::Rails::Entity
	...
	# Expect a array of hash with the following format:
	def self.references
		['organization_id', 'lines/linked_transactions/id']
	end
end

References are an empty array by default.

The framework will then handle the referencing during the mapping.

 For complex entities

For complex entities, the method looks like:

def self.references
	{
		'contacts' => ['organization_id'],
		'leads' => ['organization_id']
	}
end


so that you can define different references for each entities you're mapping to.


You will then need to map all the references fields in the mapper:

class SomeMapper
	extend HashMapper
 
	map from('details/organization_id'), to('ContactId')
end


Filter data coming from Connec!™

Connec!™ API support filter, and you can pass filter to the GET call using the framework:

def get_connec_entities(last_synchronization)
	@opts.merge!(:$filter => "type eq 'CUSOMTER' and status eq 'DRAFT'")
	super
end

Refer to the API documentation on filters for more details on filtering syntax.


Because this filtering will only apply on explicit calls and not for webhooks, you will also need to perform the same mapping yourself in the filter_connec_entities method:

def filter_connec_entities(entities)
	entities.select{|e| e['type'] == 'CUSTOMER' && e['status'] == 'DRAFT}
end


Smart merging

Connec!™ supports smart merging on the records: it will try to merge the record with any existing one based on the field you're passing. (see Connec! Smart merging of record when creating or updating). You can specify your matching fields in each entity or sub entity:

def self.connec_matching_field
	[['first_name'], ['reference']]
end


Singleton ressources

If you want to use a Connec!™ singleton resource, like Company, you'll have to declare it in the entity class:

class Entities::Company < Maestrano::Connector::Rails::Entity
 
	def self.connec_entity_name
		'Company'
	end


	def self.singleton?
		true
	end
end

All entities are non singleton by default.


(warning) Singleton are not supported on complex entities yet. Please contact us if you need to handle a complex entity with singleton(s).

Before and after sync

If you need to, you can add some logic to the synchronization process.

class Entities::Contact < Maestrano::Connector::Rails::Entity
	...
	
	def before_sync(last_synchronization)
		# Do something
	end
 
	def after_sync(last_synchronization)
		# Do something
	end
end

The before_sync is called before any data is fetched for this entity, and the after_sync is called after all data have been pushed for this entity.


Read only, write only, ... ressources

If one of the entity you're working with has limitations, you can declare them in your entity to skip part of the synchronization process:

class Entities::Company < Maestrano::Connector::Rails::Entity
	def self.can_read_connec?
      false
    end

	def self.can_read_external?
      false
    end

    def self.can_write_connec?
      false
    end


    def self.can_write_external?
      false
    end

    def self.can_update_external?
      false
    end
end

It works the same way for complex entities (to be declared in each sub entity)


Overloading the framework methods


All the main files of the framework implements a decorator pattern, so you can overload any methods on an entity by entity basis to fit any specific need.


You'll probably need to understand how the magic happens in the framework, so here are a few words about it:

Synchronization process

The framework rely on synchronizations which are started by background workers. There is one synchronisation job per organization, and each job synchronizes each entity with the following process:

Entities architecture

Entities and complex entities architecture. Green classes are implemented (or most of them) by the framework, whereas purple ones belong to the connector:

Overloading methods

You can have a look directly at the framework code if you need to overload a method for which no example is given here. Make sure that, whenever possible, your overloaded methods still use the framework code (call to super) to insure maintainability.