Skip to content

3.1. Companies Model

Nicolas Erlichman edited this page Aug 18, 2022 · 4 revisions

The idea of this section is to learn how to create a new model and add basic attributes and validations.

Companies

First of all, we are going to create a new model Company with the following attributes:

- id: integer
- name: string
- entity: enum(llc, c_corp, s_corp)
- phone: integer
- user_id: integer

Rails provides an easy way to do this by running this command:

foo@bar:~$ rails generate model Company user:references name:string entity:integer phone:integer
invoke  active_record
      create    db/migrate/20220818153944_create_companies.rb
      create    app/models/company.rb
      invoke    test_unit
      create      test/models/company_test.rb
      create      test/fixtures/companies.yml

You can notice that we didn't specify the id attribute. That's because it's handled by Rails behind scenes, so you never have to specify that. You can also see that for the enum attribute, we indicated it to be an integer, and that's for performance purposes as it's faster to use integers than strings. We will specify the options in a moment.

Migrations

If you check the file db/migrate/20220818153944_create_companies.rb you should have something like this:

class CreateCompanies < ActiveRecord::Migration[7.0]
  def change
    create_table :companies do |t|
      t.references :user, null: false, foreign_key: true
      t.string :name
      t.integer :entity
      t.integer :phone

      t.timestamps
    end
  end
end

That's how a migration in Rails looks like. Have in mind that table names are always pluralized.

If you don't know yet what attributes the migration is going to contain, you can omit them when running the command.

Lastly, t.timestamps adds created_at and updated_at to our model.

Let's now execute the migration by running this:

foo@bar:~$ rails db:migrate

Models

If you check the file app/models/company.rb, you should have this:

class Company < ApplicationRecord
  belongs_to :user
end

Enums

Now we are going to add the enum values as follows:

class Company < ApplicationRecord
  enum entity: { llc: 0, c_corp: 1, s_corp: 2 }
end

Relations

As you saw we added user:references when generating the model. That adds a foreign key in the companies table pointing to the users table. We will now tell Rails we have a relationship there.

To do that, we can use the keyword belongs_to in the Company side.

class Company < ApplicationRecord
  enum entity: { llc: 0, c_corp: 1, s_corp: 2 }

  belongs_to :user
end

... and has_one on the User side.

class User < ApplicationRecord
  ...
  has_one :company, dependent: :destroy
  ...
end

With dependent: :destroy we tell Rails to destroy the company record if the user gets destroyed.

Validations

We want now to avoid Companies with empty and repeated names. To solve that, Rails introduces validations that can be added in the following way. For further reading check out the link.

class Company < ApplicationRecord
  enum entity: { llc: 0, c_corp: 1, s_corp: 2 }

  belongs_to :user

  validates :name, presence: true, uniqueness: true
end

The integers 0, 1 and 2 are the values that will be stored in the database.

We are looking better now, but that's not enough. We are covered on the Rails side, but not database-wise, as the table companies allows empty and repeated names. Let's fix it.

We will create a new migration to add a unique index and set the nullable condition.

foo@bar:~$ rails generate migration AddNameIndexToCompanies

You should have now a new file in the db/migrate folder that we will edit to introduce the index. We will have this:

class AddNameIndexToCompanies < ActiveRecord::Migration[7.0]
  def change
    change_column :companies, :name, :string, null: false
    add_index :companies, :name, unique: true
  end
end

Run the migration and you are good to go.

foo@bar:~$ rails db:migrate

Next: 3.2. Companies Controller

Clone this wiki locally