I already had a ruby project, and there are few things I wanted to try to test some ActiveRecord queries. First I implemented a small script (see here ) But it was not easy to play with classes as I had to run the full script (gem installs, models definitions etc.).
I was looking a way to interact directly with the dabase in console.
Models
I had 4 different models in my ruby app:
- location
- role
- person
- region
defined like so:
class Location < ActiveRecord::Base
belongs_to :region
has_many :people
end
class Person < ActiveRecord::Base
belongs_to :location
belongs_to :role
belongs_to :manager, class_name: "Person", foreign_key: :manager_id
has_many :employees, class_name: "Person", foreign_key: :manager_id
end
class Region < ActiveRecord::Base
has_many :locations
end
class Role < ActiveRecord::Base
has_many :people
end
Gemfile
source "https://rubygems.org"
ruby "2.5.3"
gem "activerecord"
gem "byebug"
gem "database_cleaner"
gem "factory_girl"
gem "pg"
gem "pry"
gem "rake"
gem "rspec"
What we see in this gemfile is:
- activerecord gem is already present
- I used
pg
, but one can choose any database
to this Gemfile I had this gem
gem 'standalone_migrations'
This gem provide a way to run Rails migrations in non-Rails (and non Ruby) projects.
To install the gem I ran in console:
$ bundle install
Configuration
The 'standalone_migrations'
comes with a setup.
- The first step was to create a file
config.yml
indb
directory:
default: &default
adapter: postgresql
encoding: unicode
pool: 5
host: localhost
development:
<<: *default
database: has_many_development
- Then, I added this in the
Rakefile
require 'standalone_migrations'
StandaloneMigrations::Tasks.load_tasks
- I checked I had access to the rake tasks with:
$ bundle exec rake --tasks
Database
I started by creating the database:
$ bundle exec rake db:create
Created database 'has_many_development'
Then I made the migration to create the schema:
$ bundle exec rake db:new_migration name=create_roles
create db/migrate/20181113182825_create_roles.rb
I went to the file 20181113182825_create_roles
in db/migrate
directory and adapt the table:
class CreateRoles < ActiveRecord::Migration[5.2]
def change
create_table :roles do |t|
t.string :name
t.boolean :billable
end
end
end
Then I ran the bundle exec rake db:migrate
bundle exec rake db:migrate
== 20181113182825 CreateRoles: migrating ======================================
-- create_table(:roles)
-> 0.0515s
== 20181113182825 CreateRoles: migrated (0.0516s) =============================
I repeted this to create my 3 other tables. To finally have this schema:
ActiveRecord::Schema.define(version: 2018_11_13_184450) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "locations", force: :cascade do |t|
t.bigint "role_id"
t.string "name"
t.index ["role_id"], name: "index_locations_on_role_id"
end
create_table "people", force: :cascade do |t|
t.bigint "location_id"
t.string "name"
t.integer "salary"
t.bigint "role_id"
t.index ["location_id"], name: "index_people_on_location_id"
t.index ["role_id"], name: "index_people_on_role_id"
end
create_table "regions", force: :cascade do |t|
t.string "name"
end
create_table "roles", force: :cascade do |t|
t.string "name"
t.boolean "billable"
end
end
Then after having doing this, I can check my tables with
$ psql -d has_many_development -c "\d+ roles"
in console.
The last word is a way of specifying which table we are talking about.
Table "public.roles"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
----------+-------------------+-----------+----------+-----------------------------------+----------+--------------+-------------
id | bigint | | not null | nextval('roles_id_seq'::regclass) | plain | |
name | character varying | | | | extended | |
billable | boolean | | | | plain | |
Indexes:
"roles_pkey" PRIMARY KEY, btree (id)
Connecting to Database
Then, I launched an irb
console and I used these commands to access to the db:
require 'active_record'
require_relative './app/models/role'
db_configuration_file_path = '....../db/config.yml'
db_configuration = YAML.load(File.read(db_configuration_file_path))
ActiveRecord::Base.establish_connection(db_configuration["development"])
db_configuration_file_path
being the path to the config file.
Then I could direcly create records:
Role.create(name: 'role1', billable: true)
#<Role id: 1, name: "role1", billable: true>
>> Role.all
#<ActiveRecord::Relation [#<Role id: 1, name: "role1", billable: true>]>
☀️ we can leave the project and come back later. We don't need to recreate new records as the data are persisted in DB.
The only thing when coming back is to establish the connection to the DB, so we have to run the above script:
require 'active_record'
db_configuration = YAML.load(File.read("../db/config.yml"))
ActiveRecord::Base.establish_connection(db_configuration["development"])
The trap is not to forget to require models, so we can play with them.
require_relative './app/models/region'
true
>> Region.all
#<ActiveRecord::Relation [#<Region id: 1, name: "region1">, #<Region id: 2, name: "Bretagne">]>
If we don't require_relative
, we get:
>> Location.all
Traceback (most recent call last):
2: from /Users/cco/.rvm/rubies/ruby-2.5.3/bin/irb:11:in `<main>'
1: from (irb):10
NameError (uninitialized constant Location)
Notes
To navigate into PG:
// open pg console
$ psql postgres
// list all databases
\list
// change database
\c name_of_the_db
// to open a connection straight in console
>> require 'pg'
true
>> conn = PG::Connection.open(:dbname => 'has_many_development')
#<PG::Connection:0x00007fe586a29cc0>
To query data stores, I used Postico.
sources: This article + StackOverflow :)
next steps
- see how I can seed it straight from a
db/seed.rb
and access the db via the console
Ok, I just learned a simpler way to open IRB console.
With the script here that compiles all the gems, the models, and so on. I can add at the end, these two lines:
These command stops the execution of the file and open a IRB console