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!