Photo by Tobias Fischer on Unsplash
Creating the Database schema
Part 4 of building a Rails 7 application
Rails provides scaffolds for generating all the boilerplate code for a Model in the application. This also includes the database migrations that will be needed.
These scaffolds are a little bit limited in what they support in terms of database migrations but will be a good enough start from which they can be customized.
I will not be going into too much detail about the structure of the database as it is not entirely relevant to this blogging exercise. Here are the relationship diagrams though.
An example scaffold result:
% rails generate scaffold ItemSellPack name:string canonical:boolean
invoke active_record
identical db/migrate/20220608092914_create_item_sell_packs.rb
identical app/models/item_sell_pack.rb
invoke test_unit
identical test/models/item_sell_pack_test.rb
identical test/fixtures/item_sell_packs.yml
invoke resource_route
route resources :item_sell_packs
invoke scaffold_controller
create app/controllers/item_sell_packs_controller.rb
invoke tailwindcss
create app/views/item_sell_packs
create app/views/item_sell_packs/index.html.erb
create app/views/item_sell_packs/edit.html.erb
create app/views/item_sell_packs/show.html.erb
create app/views/item_sell_packs/new.html.erb
create app/views/item_sell_packs/_form.html.erb
create app/views/item_sell_packs/_item_sell_pack.html.erb
invoke resource_route
invoke test_unit
create test/controllers/item_sell_packs_controller_test.rb
create test/system/item_sell_packs_test.rb
invoke helper
create app/helpers/item_sell_packs_helper.rb
invoke test_unit
invoke jbuilder
create app/views/item_sell_packs/index.json.jbuilder
create app/views/item_sell_packs/show.json.jbuilder
create app/views/item_sell_packs/_item_sell_pack.json.jbuilder
It is not possible to specify the default value of an attribute using the scaffold so to set canonical
to be a default value of false
that will require manually editing the generated file.
class CreateItemSellPacks < ActiveRecord::Migration[7.0]
def change
create_table :item_sell_packs do |t|
t.string :name
t.boolean :canonical, default: false
t.timestamps
end
end
end
It also is not possible to specify json
or jsonb
as a type using the scaffolding so I'll need to manually set those too in the generated file.
class CreateTasks < ActiveRecord::Migration[7.0]
def change
create_table :tasks do |t|
t.string :type
t.integer :context_id
t.string :context_type
t.text :description
t.jsonb :before
t.jsonb :after
t.string :status
t.string :error
t.boolean :requires_approval
t.boolean :approved
t.references :approved_by, foreign_key: true
t.timestamp :approved_at
t.timestamps
end
end
end
Another change to this file is the approved_by
reference. By default these are set to null: false
because all belongs_to
associations are now assumed to be required. For my requirement though this is not the case so I need to remove that rule and also mark the association in the model as optional too.
class Action < ApplicationRecord
belongs_to :approved_by, optional: true
end
Unfortunately the scaffolded code has many Rubocop violations as well. So I'll fix those using the auto correct.
% rubocop
...
154 files inspected, 1056 offenses detected, 1056 offenses autocorrectable
% rubocop -A
Now I can create the development and test databases. Back in Part 2 when I initialized the application it already created a default database.yml file. Nothing in there needs to be changed just yet so I can do the following.
% rails db:create
Created database 'catalogue_cleanser_development'
Created database 'catalogue_cleanser_test'
% rails db:migrate RAILS_ENV=test
== 20220608092914 CreateItemSellPacks: migrating ==============================
-- create_table(:item_sell_packs)
-> 0.0102s
== 20220608092914 CreateItemSellPacks: migrated (0.0103s) =====================
% rails db:migrate
== 20220608092914 CreateItemSellPacks: migrating ==============================
-- create_table(:item_sell_packs)
-> 0.0076s
== 20220608092914 CreateItemSellPacks: migrated (0.0077s) =====================
...
Finally I can start the application for the first time. I am using Rubymine so I need to add a new Run configuration to use Foreman as the server launcher. This will ensure that the TailwindCSS is compiled properly whenever a change is made.
First of all add Foreman to the Gemfile.
group :development do
# Process manager
gem 'foreman'
end
Then add a new Rubymine run configuration.
And now I have a running Rails 7 server.