Skip to content

Instantly share code, notes, and snippets.

@booch
Created February 10, 2014 22:19
Show Gist options
  • Select an option

  • Save booch/8925423 to your computer and use it in GitHub Desktop.

Select an option

Save booch/8925423 to your computer and use it in GitHub Desktop.

Revisions

  1. booch created this gist Feb 10, 2014.
    214 changes: 214 additions & 0 deletions Ruby ORMs.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,214 @@
    Ruby ORMs
    =========


    Abstract
    --------

    Rails is really a collection of pieces that can be put together to create a web app.
    You can enhance or replace many of the components - how you write views, how controllers
    work, and how you build models. While models are built on top of ActiveRecord in the
    default Rails stack, you've got a lot of other choices.

    In this presentation, we'll take a look at ActiveRecord and alternative ORMs.
    We'll discuss the pros and cons of each, and take a look at what the future will bring us.


    ORMs
    ----

    * ActiveRecord
    * DataMapper
    * Sequel
    * ROM
    * Perpetuity
    * Mongoid
    * MongoMapper
    * Mince


    ActiveRecord Pros
    -----------------

    ActiveRecord is the 800-pount gorilla.

    * Ubiquitous
    * Everyone knows it
    * Lots of people improving on it
    * Plugins usually assume you're using it
    * Plenty of documentation
    * Well-tested
    * Well-understood
    * Super easy to get started
    * It's included in Rails by default
    * ARel behind the scenes


    ActiveRecord Cons
    -----------------

    * Class inheritance
    * Not (current) idiomatic Ruby
    * Prevents a hierarchical class structure
    * TODO: Show an example where this would be useful
    * Persistence and behavior in one class
    * Violates SRP
    * Makes testing harder and slower
    * TODO: Show examples of slow tests and fast test
    * Validations are also included (another responsibility)
    * No Identity Map
    * TODO: Show example of where this is a problem
    * Have to look 2 places to find everything:
    * Attributes (fields) are declared in the schema
    * Relations are declared in the model itself


    ActiveRecord Add-Ons
    --------------------

    * Includable ActiveRecord
    * Solves the inheritance issue
    * Annotated Models (TODO: or its replacement)
    * Kind of solves the problem of fields and relations in different places
    * Virtus::ActiveRecord or mini_record
    * Solves the problem of fields and relations in different places
    * Squeel
    * Gives a more Ruby-like API for scopes
    * Attachments (Paperclip, etc.)
    * Authentication (Devise, etc.)


    DataMapper
    ----------

    * Actually uses the Active Record pattern
    * Supports a lot more than just SQL on the back end
    * No further development (last updated 2012-08-27)


    [Sequel](http://sequel.jeremyevans.net/)
    ------

    * Probably the best alternative right now
    * Good documentation
    * Leverages database features (like foreign key constraints)
    * Supports almost any SQL database you can think of
    * Thread safety, connection pooling

    * Awesome feature - set a model to a subset of a table:
    ```ruby
    DB = Sequel.connect('sqlite://blog.db')
    class Post < Sequel::Model
    set_primary_key [:category, :title]
    set_dataset DB[:my_posts].where(category: 'ruby').select(:category, :title, :content).order(:date)
    end
    ```


    ROM
    ---

    * Should be the best alternative in the future
    * Previously was called DataMapper 2
    * But has diverged a lot since the name change
    * Truly implements the Data Mapper pattern
    * Taking longer to get to 1.0 than hoped
    * Developers seem to be low-level / bottom-up types
    * Supports in-memory (PostgreSQL in the works)
    * More pieces:
    * Axiom
    * ROM::Relation
    * ROM::Mapper
    * ROM::Session
    * Model
    * Identity Map


    Perpetuity
    ----------

    * Worth looking at
    * Simple
    * Implements the Data Mapper patter
    * Supports MongoDB, PostgreSQL, in-memory
    * Identity Map


    Mongoid and MongoMapper
    -----------------------

    * See Sarah Mei's essay on why to avoid MongoDB in most cases
    * Mongoid
    * Pretty simple
    * Be sure to turn on MongoDB persistence!
    * Pretty stable
    * TODO: Why to avoid MongoMapper


    Mince
    -----

    * Simple and light-weight (no relations)
    * Supports MongoDB, Hashy (in-memory), and DynamoDB
    * Multi-tier architecture
    * Collections and items
    * Causes some un-DRYness declaring fields
    * No further development (last updated 2013-06-07)

    ```ruby
    require 'mince'

    class BookDataModel
    include Mince::DataModel
    data_collection :books
    data_fields :title, :publisher
    end

    class Book
    include Mince::Model
    data_model BookDataModel
    fields :title, :publisher
    end

    book = Book.new title: 'The World In Photographs', publisher: 'National Geographic'
    book.save
    ```


    Others
    ------

    * [Swift](https://github.com/shanna/swift)
    * ORM Adapter
    * Gives a standard API, sitting atop AR, DM, MM, or Mongoid


    NoORM
    -----

    * POROs
    * Sometimes you don't need persistence for all your models
    * TODO: Show examples
    * MagLev


    The Future
    ----------

    * ROM will reach 1.0 and be usable in production
    * Hopefully ROM will become the go-to ORM many cases
    * Perpetuity might become useful before ROM
    * MageLev might gather a following
    * Virtus::ActiveRecord might be a stepping-stone to ROM
    * ActiveRecord will continue to improve
    * We'll learn how to better use ActiveRecord


    References
    ----------

    * http://solnic.eu/2011/11/29/the-state-of-ruby-orm.html
    * http://rhnh.net/2011/11/29/datamapper-retrospective
    * http://rosenfeld.herokuapp.com/en/articles/ruby-rails/2013-12-18-sequel-is-awesome-and-much-better-than-activerecord
    * Sarah Mei on MongoDB
    * http://java.dzone.com/articles/martin-fowler-orm-hate