LearnActive Record Without a Rails App

Jay McGavren
writes on November 1, 2017

When you want to work with Ruby on Rails models, even if you’re just playing around, you have to go through a few steps:

  • Create an app directory
  • Create a database
  • Generate model classes
  • Run migrations

But sometimes you need something much more lightweight. When I was creating code challenges for our new Active Record Associations in Rails course recently, I needed to simulate a full Rails environment without actually loading Rails (which would have been too slow). So I created a setup that:

  • Loads just the Active Record library, not all of Rails
  • Creates a database entirely in RAM, not on disk
  • Sets up the database without running migrations

I wanted to share my results with all of you, so you can experiment with new Rails models without having to create full Rails apps.

Start learning to code today with a free trial on Treehouse.

The Code

The bulk of our simulated Rails app resides in a single file. This particular setup mimics an app for a veterinary office, including an Owner model that has_many instances of a Pet model. (But you can substitute model classes of your own, if you want).

Create a file named vet.app, in any folder you want, and paste in this code. (We’ll explain all the code in a bit.)

File: vet.rb

# Instead of loading all of Rails, load the
# particular Rails dependencies we need
require 'sqlite3'
require 'active_record'

# Set up a database that resides in RAM
ActiveRecord::Base.establish_connection(
  adapter: 'sqlite3',
  database: ':memory:'
)

# Set up database tables and columns
ActiveRecord::Schema.define do
  create_table :owners, force: true do |t|
    t.string :name
  end
  create_table :pets, force: true do |t|
    t.string :name
    t.references :owner
  end
end

# Set up model classes
class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end
class Owner < ApplicationRecord
  has_many :pets
end
class Pet < ApplicationRecord
  belongs_to :owner
end

Now to actually use these models. In the same folder, create another file (you can name it anything you want).

File: your_code.rb

# Load the above file
require './vet'

# Play around!
owner = Owner.create(name: "Jay")
owner.pets.create(name: "Max")
owner.pets.create(name: "Chai")
p Owner.first.pets

If you run the above file from your terminal, the model objects will be created and saved to the in-memory database!

$ ruby your_code.rb
-- create_table(:owners, {:force=>true})
   -> 0.0193s
-- create_table(:pets, {:force=>true})
   -> 0.0008s
#<ActiveRecord::Associations::CollectionProxy [
  #<Pet id: 1, name: "Max", owner_id: 1>,
  #<Pet id: 2, name: "Chai", owner_id: 1>
]>
$ 

And when Ruby exits, the database will be removed from memory, leaving you with a clean slate again. You don’t need a Rails app directory or a SQLite database file; all you need is these two Ruby code files.

How it Works

If we’re just playing with Active Record models, we don’t need all of Rails, we just need a database adapter and Active Record itself. These two lines load the necessary libraries:

require 'sqlite3'
require 'active_record'

If you use the special value of ":memory:", SQLite3 can write everything to a database in RAM, rather than a file on disk. Sure, everything disappears when Ruby exits, but that’s actually preferable when you’re just playing around. These lines set Active Record up to use an in-memory database:

ActiveRecord::Base.establish_connection(
  adapter: 'sqlite3',
  database: ':memory:'
)

Your model classes won’t work unless the database contains the appropriate tables and columns. A Rails app maintains its database setup in a file named db/schema.rb, and that file can be used to recreate a database from scratch, without running migrations. But the schema doesn’t have to be kept in a separate file; we can just throw it straight into our single-file app!

ActiveRecord::Schema.define do
  create_table :owners, force: true do |t|
    t.string :name
  end
  create_table :pets, force: true do |t|
    t.string :name
    t.references :owner
  end
end

And then we need the actual model classes. These lines set them up:

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end
class Owner < ApplicationRecord
  has_many :pets
end
class Pet < ApplicationRecord
  belongs_to :owner
end

Now to load your makeshift Active Record environment, and set up the database. This line looks in the current directory for a file named vet.rb, and runs the code it contains:

require './vet'

Once that’s done, you’re free to create new instances of your model classes, save them to the in-memory database, and load them back out again!

owner = Owner.create(name: "Jay")
owner.pets.create(name: "Max")
owner.pets.create(name: "Chai")
p Owner.first.pets

Other Stuff to Try

You don’t even have to create multiple files for this – you can house all your code in a single file. For example, here’s a mini-app that lets you play with Post and Comment models from a blog.

The next time you’re troubleshooting an issue with your models, or you just want to show off your code, you don’t have to share a whole Rails app. Instead, you can create one of these miniature apps, and share everything you need with a single file!

P.S.: If you liked this post, you should try out our new Active Record Associations in Rails course!

Leave a Reply

Learning to code can be fun!

Get started today with a free trial and discover why thousands of students are choosing Treehouse to learn about web development, design, and business.

Learn more