communicator

A simple communication layer to keep database records in sync between two Rails apps.

Setup

Install in Rails apps by adding this to your Gemfile:

gem 'communicator'

Import rake tasks in your Rails.root/Rakefile:

require 'communicator/tasks'

Set up the database tables for the messages by importing the corresponding migrations from the gem:

$ rake communicator:update_migrations
$ rake db:migrate

After doing these steps, you can proceed to configure either the server or client. On both sides, you’ll have to configure the client and server. You can do so by placing a configuration file in Rails.root/config/communicator.yml that looks somewhat like this:

defaults: &defaults
  username: communicator
  password: verysecret
  base_uri: localhost:3001 # Can be ommitted for server config

test:
  <<: *defaults

development:
  <<: *defaults

production:
  <<: *defaults
  password: Uber!Secret
  base_uri: 192.168.0.104:4000 # Can be ommitted for server config

The configuration for the current ‘Rails.env` will then be automatically loaded when you `require ’communicator’‘.

You can also skip the YAML configuration and set up the credentials programmatically:

Communicator::Server.username = 'foo'
Communicator::Server.password = 'bar'

Communicator::Client.username = 'foo'
Communicator::Client.password = 'bar'
Communicator::Client.base_uri 'localhost:1234'

Server side

On the server side, you can mount the server component in a Rails 2.3 app as a rack middleware inside environment.rb:

require 'communicator'
config.middleware.use 'Communicator::Server'

It will then be mounted at /messages.json for GET and POST requests, requesting HTTP Basic Auth with the configured credentials.

Client side

Tell the client the server url and port as well as the auth credentials inside your environment.rb:

require 'communicator'

When everything’s fine, you should be able to push and pull using the client:

Communicator::Client.push
Communicator::Client.pull

Active Record integration

To keep models in sync, specify the model class (in underscored type) the local class receives updates from like this:

class Post < ActiveRecord::Base
  receives_from :post
end

If you want to skip some remote attributes and not let them progapate into local instances, use ‘receives_from :post, :except => [:user_id]`.

Attributes that are not physically present in the local database will be skipped automatically.

Use the automatically added ‘publish` instance method on your models to push changes to the other side. They will be enqueued in the local `outbound_messages` table and will arrive at the other side when a client pulls or pushes.

When an update is received from a remote side, the message will be stored in ‘inbound_messages` and the received changes will be applied to the local record, either updating existing or creating new records.

Compatibility

Communicator is currently only proven to work on Rails 2 apps using either REE, 1.8.7, 1.9.1 or 1.9.2.

Note on Patches/Pull Requests

  • Fork the project.

  • Make your feature addition or bug fix.

  • Add tests for it. This is important so I don’t break it in a future version unintentionally.

  • Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)

  • Send me a pull request. Bonus points for topic branches.

Copyright © 2010 Capita Unternehmensberatung GmbH. See LICENSE for details.