Create a Model

This tutorial describes how to create a model and migration using the souls db If you need to review ActiveRecord, we recommend reading this ActiveRecord first.

create_migration

Finish the quick start and make sure the app is running. In this tutorial, we will proceed with development using the application created in the quick start.

We'll work in the API directory here.

Run the test

The SOULs framework will be developed alongside Rspec tests. Go to the api directory and launch the SOULs API.

First, run the tests.

$ cd apps/api
$ souls test
Inspecting 32 files
................................

31 files inspected, no offenses detected
Run options: exclude {:uses_external_service=>true, :long=>true}

All examples were filtered out

Randomized with seed 10663

Finished in 0.13387 seconds (files took 1.38 seconds to load)
0 examples, 0 failures

Randomized with seed 10663

0 tests have been confirmed.

Creating a migration file

Create a migration file using the souls db create_migration

$ souls db create_migration ${table_name}

${table_name} table name is entered in ${table_name}, specify user

$ souls db create_migration user
db/migrate/20210930154336_create_users.rb
Created file! : ./app/models/user.rb
Created file! : ./spec/models/user_spec.rb

souls db create_migration command generated the following five files:

file name role path
*_create_users.rb migration API directory
user.rb Model API directory
user_spec.rb Rspec API directory

Now let's check the generated file.

Migration file

apps/api/db/migrate/20210930151749_create_users.rb
class CreateUsers < ActiveRecord::Migration[6.1]
  def change
    create_table :users do |t|

      t.boolean :is_deleted, null: false, default: false
      t.timestamps
    end
  end
end

The SOULs framework creates the following three columns by default.

Column name Mold
is_deleted Boolean
created_at DateTime
updated_at DateTime

These columns are associated with the files that will be auto-generated by the souls g scaffold command.

Model file

app/models/user_model.rb
class User < ActiveRecord::Base
end

A User Model has been generated. This inherits from ActiveRecord and the usual validations and callbacks can therefore be used.

Rspec file

app/api/spec/models/user_spec.rb
RSpec.describe "User Model テスト", type: :model do
  describe "User データを書き込む" do
    it "valid User Model" do
      expect(FactoryBot.build(:user)).to be_valid
    end
  end
end

Rspec file for the User Model has been generated.

Migration file definition

Define the columns User table in the Migration file generated earlier.

db/migrate/20210728081544_create_users.rb
class CreateUsers < ActiveRecord::Migration[6.1]
  def change
    create_table :users do |t|
      t.string :uid, null: false, unique: true
      t.string :username, null: false, default: ""
      t.string :screen_name, null: false, default: ""
      t.string :last_name, null: false, default: ""
      t.string :first_name, null: false, default: ""
      t.string :last_name_kanji, null: false, default: ""
      t.string :first_name_kanji, null: false, default: ""
      t.string :last_name_kana, null: false, default: ""
      t.string :first_name_kana, null: false, default: ""
      t.string :email, null: false, unique: true
      t.string :tel, null: false, default: ""
      t.string :icon_url, null: false, default: ""
      t.string :birthday, null: false, default: ""
      t.string :gender, null: false, default: ""
      t.string :lang, null: false, default: "ja"
      t.string :category, null: false, default: "user"
      t.integer :roles_mask, null: false, default: 1
      t.boolean :is_deleted, null: false, default: false
      t.timestamps
    end
    add_index :users, :uid
    add_index :users, :screen_name
    add_index :users, :email, unique: true
    add_index :users, :username
    add_index :users, :is_deleted
  end
end

Execute souls db command

By running souls help

You can see the SOULs CLI command.

Let's get help for the souls db

$ souls db help
  Commands:
    souls db add_column [CLASS_NAME]            # Create ActiveRecord Migration File
    souls db change_column [CLASS_NAME]         # Create ActiveRecord Migration File
    souls db create                             # Create Database
    souls db create_migration [CLASS_NAME]      # Create ActiveRecord Migration File
    souls db drop_table [CLASS_NAME]            # Create ActiveRecord Migration File
    souls db help [COMMAND]                     # Describe subcommands or one specific subcommand
    souls db migrate                            # Migrate Database
    souls db migrate_reset                      # Reset Database
    souls db model [CLASS_NAME]                 # Generate Model Template
    souls db remove_column [CLASS_NAME]         # Create ActiveRecord Migration File
    souls db rename_column [CLASS_NAME]         # Create ActiveRecord Migration File
    souls db reset                              # Reset Database and Seed
    souls db rspec_model [CLASS_NAME]           # Generate Rspec Model Test from schema.rb
    souls db seed                               # Insert Seed Data

souls db command to add a new table.

Execute souls db create

$ souls db create
Created database 'souls-api-dev'
Created database 'souls-api-test'

Executing the souls db migrate

$ souls db migrate
== 20210930154336 CreateUsers: migrating ======================================
-- create_table(:users)
   -> 0.0193s
-- add_index(:users, :uid)
   -> 0.0054s
-- add_index(:users, :screen_name)
   -> 0.0050s
-- add_index(:users, :email, {:unique=>true})
   -> 0.0050s
-- add_index(:users, :username)
   -> 0.0052s
-- add_index(:users, :is_deleted)
   -> 0.0052s
== 20210930154336 CreateUsers: migrated (0.0454s) =============================

You can also view the help details for the command.

$ souls db help create
Usage:
  souls db create

Options:
  --e, [--env=ENV]  # Difine APP Enviroment - development | production
                    # Default: development

Create Database

To run in production, specify the environment variable with --e=production

$ souls db create --e=production
$ souls db migrate --e=production

Create an Article Model

Similarly, Article Model.

Here, in order to dynamically manage the categories of ArticleCategory , this time we will create an Article

We'll also add a Comment table so you can comment on your blog posts.

Execute souls db command

Create a migration file with the souls db create_migration

$ souls db create_migration article_category
$ souls db create_migration article
$ souls db create_migration comment

Migration file definition

Define a migration file for each.

apps/api/db/migrate/[timestamp]_create_article_categories.rb
class CreateArticleCategories < ActiveRecord::Migration[6.1]
  def change
    create_table :article_categories do |t|
      t.string :name, null: false
      t.text :tags, array: true, default: []
      t.boolean :is_deleted, null: false, default: false
      t.timestamps
    end
    add_index :article_categories, :name
    add_index :article_categories, :is_deleted
  end
end
apps/api/db/migrate/[timestamp]_create_articles.rb
class CreateArticles < ActiveRecord::Migration[6.1]
  def change
    create_table :articles do |t|
      t.belongs_to :user
      t.string :title, null: false, unique: true
      t.text :body, null: false, default: ""
      t.string :thumnail_url, null: false, default: ""
      t.datetime :public_date, null: false, default: Time.now + 30.days
      t.belongs_to :article_category, null: false
      t.boolean :is_public, default: false, null: false
      t.boolean :just_created, default: true, null: false
      t.string :slug, null: false, unique: true
      t.text :tags, array: true, default: []
      t.boolean :is_deleted, null: false, default: false
      t.timestamps
    end
    add_index :articles, :slug, unique: true
    add_index :articles, :title, unique: true
    add_index :articles, :is_public
    add_index :articles, :is_deleted
  end
end
apps/api/db/migrate/[timestamp]_create_comments.rb
class CreateComments < ActiveRecord::Migration[6.1]
  def change
    create_table :comments do |t|
      t.belongs_to :article
      t.string :from, null: false, default: "名無し"
      t.text :body, null: false, default: ""
      t.boolean :is_deleted, null: false, default: false
      t.timestamps
    end
  end
end

Execute souls db command

Run the souls db migrate

$ souls db migrate

Definition of relationship model

Define an ActiveRecord relationship in Model.

apps/api/models/article_category.rb
class ArticleCategory < ActiveRecord::Base
  has_many :article
end
apps/api/models/article.rb
class Article < ActiveRecord::Base
  belongs_to :user
  belongs_to :article_category
  has_many :comment
end
apps/api/models/comment.rb
class Comment < ActiveRecord::Base
  belongs_to :article, dependent: :destroy
end
apps/api/app/models/user.rb
class User < ActiveRecord::Base
  include RoleModel
  has_many :article

  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  private_constant :VALID_EMAIL_REGEX
  validates :email, presence: true, uniqueness: true, format: { with: VALID_EMAIL_REGEX }

  roles :normal, :user, :admin, :master
  before_create :assign_initial_roles

  # Scope
  default_scope -> { order(created_at: :desc) }

  def assign_initial_roles
    roles << [:normal]
  end
end