Coder Social home page Coder Social logo

moribus's Introduction

Moribus

Build Status

Moribus is a set of tools for managing complex graphs of ActiveRecord objects for which there are many inbound foreign keys, attributes and associations with high rates of change, and business demands for well-tracked change history.

##AggregatedBehavior

AggregatedBehavior implements a pattern in which an object's identity is modeled apart from its attributes and outbound associations. This enables a higher level of normalization of your data, since one set of properties may be shared among multiple objects. This set of properties - attributes and outbound associations - are modeled on an object called an "info object". And we say that this info object is aggregated by host object(s) and it acts (behaves) as aggregated. When an aggregated object is about to be saved, it looks up for an existing record with the same attributes in the database under the hood, and if it is found, it 'replaces' itself with that record. This allows you to work with attributes of your entity as if they are properties of an actual model and normalize your data at the same time.

Inbound foreign keys will always point at the same object in memory, and the object will never be stale, as it has no attributes of its own that are subject to change. This is useful for objects with many inbound foreign keys and high-traffic attributes/associations, such as statuses. Without this pattern it would be difficult to avoid many StaleObjectErrors.

##TrackedBehavior

TrackedBehavior implements history tracking on the stack of objects representing the identity object's attributes and outbound associations. When a model behaves as a tracked behavior, it will never actually get updated. Instead, it will update it's own 'is_current' column to false and will be saved as a new record with new attribute values and the 'is_current' column as 'true'. Thus, under the hood, new attributes will supersede old attributes, leaving the old record as historical.

##Macros, Associations and Combination

Despite the fact that Moribus may be used by models on its own, its main purpose is to be used within associations, and in conjunction with associations. The best way to demonstrate this is by example.

Let's assume we have a User entity with attributes that should be tracked and normalized. Those attributes may be, for example, :first_name, :last_name and :status as enumerated integer value. This entity may be represented with three models: User - with main model for interactions, tracked UserInfo (user_id, person_name_id, status) for tracking, and aggregated UserName (first_name, last_name) for name normalization. Class definitions for these models will appear as follows:

  class User < ActiveRecord::Base
    has_one_current :user_info
    delegate_associated :user_name, :to => :user_info
  end

  class UserInfo < ActiveRecord::Base
    has_aggregated :person_name
    acts_as_tracked
  end

  class UserName < ActiveRecord::Base
    acts_as_aggregated
  end

Despite the fact that internal representation is more complicated now, top-level operations will look exactly the same:

  user = User.create(:first_name => 'John', :last_name => 'Smith', :status => 0)
  # This creates User(id: 1) record, PersonName(id: 1, first_name: 'John', last_name: 'Smith')
  # record and UserInfo(id: 1, user_id: 1, person_name_id: 1, status: 0, is_current: true)

  user.update_attributes(:status => 1)
  # This creates new UserInfo(id: 2, user_id: 1, person_name_id: 1, status: 1, is_current: true)
  # record, and changes UserInfo(id: 1) record's 'is_current' attribute to false.

  user.update_attributes(:first_name => 'Mike')
  # This creates new PersonName(id: 2, first_name: 'Mike', last_name: 'Smith') record and new
  # current UserInfo(id: 3, user_id: 1, person_name_id: 2, :status: 1, is_current: true)

  # Now, if we want to create another 'John Smith' user:
  user2 = User.create(:first_name => 'John', :last_name => 'Smith', :status => 5)
  # This creates User(id: 2) record and UserInfo(id: 4, user_id: 2, person_name_id: 1, status: 5, is_current: true)
  # record that reuses existing UserName information.

Run tests

rake spec

Credits

Copyright

Copyright (c) 2013 TMX Credit.

moribus's People

Contributors

akuzko avatar greyblake avatar mityaliu avatar baburdick avatar zekefast avatar romatr avatar albertosaurus avatar cryo28 avatar dresselm avatar

Watchers

rosa maria palacios juncosa avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.