Active Record Without a Rails App

Treehouse

November 1, 2017

-

5 min read

Learn

Last Updated on June 12, 2023 by Dev Support

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

You must be logged in to post a comment.

You might also like other posts...

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