UUIDs

<img src=“img.shields.io/gem/v/uuids.svg?style=flat” alt=“Gem Version” /> <img src=“img.shields.io/travis/nepalez/uuids.svg?style=flat” alt=“Bild Status” /> <img src=“img.shields.io/codeclimate/github/nepalez/uuids.svg?style=flat” alt=“Code Metrics” /> <img src=“img.shields.io/gemnasium/nepalez/uuids.svg?style=flat” alt=“Dependency Status” /> <img src=“img.shields.io/coveralls/nepalez/uuids.svg?style=flat” alt=“Coverage Status” /> <img src=“img.shields.io/badge/license-MIT-blue.svg?style=flat” alt=“License” />

About

The gem adds addressing ActiveRecord objects by UUID following the RFC4122 standard.

It provides:

Uuids::Uuid

A model of UUIDs associated with various records.

Uuids::Base

A module provides ActiveRecord class helpers has_uuids and has_many (with uuid: true option).

The gem is a mountable Rails engine.

Pattern

This model allows adressing records by some UUID (not the ID). It is expected any UUID is assigned to one record, but a record can be identified by many UUIDs.

If necessary any referred record can be merged with another one. All you need is to reassign all UUIDs to merged record and outer associations remains valid.

A UUID should be neither deleted, no changed. It can only be reassigned to another resource. On ther other hand, the outer record should be merged to another one (reassign UUIDs) to prevent existance of UUIDs assigned to nothing.

Example

Suppose you have models referred to cities. One day you discover a duplication among two cities: the “New York” and the “NEW YORK”.

You should:

  • reassign both UUIDs to “New York”;

  • safely remove the “NEW YORK” record.

You needn’t track all records that refer to “NEW YORK”. All those references will authomatically lead to merged record via old UUID.

Now the model of cities should **know nothing about outer models** that use it.

Translations

Error messages are translated to English and Russian (see config/locales). Translations to other languages are welcome.

Installation

Add this line to your application’s Gemfile:

gem "uuids"

And then execute:

$ bundle

Or install it yourself as:

$ gem install uuids

Initialization

To initialize the module you need to copy and run uuid’s db migrations.

Rails application

Run from a command line in application root:

$ rake uuids:install

Rails mountable engine

Run from a command line in application root:

$ rake app:uuids:install

Usage

Adding UUIDs to models

Add the assotiation to your AR model:

class City < ActiveRecord::Base
  include Uuids::Base
  has_uuids
end

This will add methods:

#uuids

List of Uuids::Uuid objects referred to the record.

#uuid

main UUID for the record - a value of the first uuids (ordered by value).

.by_uuid

A scope for unique records by UUID: City.by_uuid

The first uuid is added by default. It can also be set manually:

# UUID is generated by default
city = City.new
city.save!

# UUID is assigned manually
city = City.new
city.uuids.new value: "6d9456a9-8f54-4ff7-ba0d-9854f1954417"
city.save

The destruction of object is forbidden if it has a uuid. You should reassign all object’s UUIDs to another object in advance.

Referring model by UUID

Instead of ActiveRecord::Associations belongs_to, has_one and has_many, you should define custom methods explicitly.

class CreateStreetsTable < ActiveRecord::Migration
  def change
    create_table :streets do |t|
      t.string :city_uuid, limit: 36
    end
    add_index :streets_table, :city_uuid
  end
end

class Street < ActiveRecord::Base

  scope :by_city, ->(city) { City.by_uuid(city.uuid) }

  def city
    @city ||= City.by_uuid(city_uuid)
  end

  def city=(city)
    read_attribute :city_uuid, city.uuid
  end
end

Contributing

  1. Fork it ( github.com/nepalez/uuids/fork )

  2. Create your feature branch (git checkout -b my-new-feature)

  3. Commit your changes (git commit -am 'Add some feature')

  4. Push to the branch (git push origin my-new-feature)

  5. Create a new Pull Request

License

The plugin is distributed under MIT license