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.
- ActiveRecord
- DataMapper
- Sequel
- ROM
- Perpetuity
- Mongoid
- MongoMapper
- Mince
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
- 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
- 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.)
- 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)
-
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:
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
- 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
- Worth looking at
- Simple
- Implements the Data Mapper patter
- Supports MongoDB, PostgreSQL, in-memory
- Identity Map
- 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
- 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)
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
- Swift
- ORM Adapter
- Gives a standard API, sitting atop AR, DM, MM, or Mongoid
- POROs
- Sometimes you don't need persistence for all your models
- TODO: Show examples
- MagLev
- 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
Thx!