【Ruby on Rails】annotateの導入

# はじめに

Railsなどを中心に勉強中のエンジニア初心者が他の記事を参考にしたり、実際に実装してみたりして、アウトプットの一環としてまとめたものです。
間違っていることもあると思われるので、その際は指摘いただけると幸いです。

# annotateとは

annotateとは、各モデルのスキーマ情報をモデルファイルなどに自動で書き出してくれる機能を持ったgemである。

開発時にschema.rbを確認したり、rails routesでルーティングを確認したりする手間を減らすことができる。

# annotateの導入

### Gemfileの追記

`Gemfile`に以下を追記して`bundle install`を実行する。

```ruby
group :development do
  gem 'annotate'
end
```

### スキーマ情報の自動書き出し設定

gemを追加したのみでは、`annotate`は機能しない。

`rails g annotate:install`を実行することで、マイグレーション時にスキーマ情報をモデルファイルに自動で書き出すように設定することができる。

```bash
$ rails g annotate:install
Running via Spring preloader in process 77144
      create  lib/tasks/auto_annotate_models.rake
```

# スキーマ情報の書き出し

自動書き出し設定をした後はマイグレーション実行時にモデルファイルにスキーマ情報が書き出されるが、すでに実行されているマイグレーションの情報については書き出されない。

そのため現時点の情報に関しては`bundle exec annotate --models`で書き出しを実行する必要がある。

### 手動での書き出し実行

```bash
$ bundle exec annotate --models
Annotated (4): app/models/task.rb, spec/factories/tasks.rb, app/models/user.rb, spec/factories/users.rb
```

### 書き出し例（モデルファイル）

```ruby
# models/task.rb

# == Schema Information
#
# Table name: tasks
#
#  id          :bigint           not null, primary key
#  description :text
#  name        :string(30)       not null
#  created_at  :datetime         not null
#  updated_at  :datetime         not null
#  user_id     :bigint           not null
#
# Indexes
#
#  index_tasks_on_user_id  (user_id)
#
class Task < ApplicationRecord
end
```

```ruby
# models/user.rb

# == Schema Information
#
# Table name: users
#
#  id              :bigint           not null, primary key
#  admin           :boolean          default(FALSE), not null
#  email           :string           not null
#  name            :string           not null
#  password_digest :string           not null
#  created_at      :datetime         not null
#  updated_at      :datetime         not null
#
# Indexes
#
#  index_users_on_email  (email) UNIQUE
#
class User < ApplicationRecord
end
```

# annotateの設定ファイル

`lib/tasks/auto_annotate_models.rakeでannotate`の設定を変更することができる。

```ruby
# NOTE: only doing this in development as some production environments (Heroku)
# NOTE: are sensitive to local FS writes, and besides -- it's just not proper
# NOTE: to have a dev-mode tool do its thing in production.
if Rails.env.development?
  require 'annotate'
  task :set_annotation_options do
    # You can override any of these by setting an environment variable of the
    # same name.
    Annotate.set_defaults(
      'active_admin'                => 'false',
      'additional_file_patterns'    => [],
      'routes'                      => 'false',
      'models'                      => 'true',
      'position_in_routes'          => 'before',
      'position_in_class'           => 'before',
      'position_in_test'            => 'before',
      'position_in_fixture'         => 'before',
      'position_in_factory'         => 'before',
      'position_in_serializer'      => 'before',
      'show_foreign_keys'           => 'true',
      'show_complete_foreign_keys'  => 'false',
      'show_indexes'                => 'true',
      'simple_indexes'              => 'false',
      'model_dir'                   => 'app/models',
      'root_dir'                    => '',
      'include_version'             => 'false',
      'require'                     => '',
      'exclude_tests'               => 'false',
      'exclude_fixtures'            => 'false',
      'exclude_factories'           => 'false',
      'exclude_serializers'         => 'false',
      'exclude_scaffolds'           => 'true',
      'exclude_controllers'         => 'true',
      'exclude_helpers'             => 'true',
      'exclude_sti_subclasses'      => 'false',
      'ignore_model_sub_dir'        => 'false',
      'ignore_columns'              => nil,
      'ignore_routes'               => nil,
      'ignore_unknown_models'       => 'false',
      'hide_limit_column_types'     => 'integer,bigint,boolean',
      'hide_default_column_types'   => 'json,jsonb,hstore',
      'skip_on_db_migrate'          => 'false',
      'format_bare'                 => 'true',
      'format_rdoc'                 => 'false',
      'format_yard'                 => 'false',
      'format_markdown'             => 'false',
      'sort'                        => 'false',
      'force'                       => 'false',
      'frozen'                      => 'false',
      'classified_sort'             => 'true',
      'trace'                       => 'false',
      'wrapper_open'                => nil,
      'wrapper_close'               => nil,
      'with_comment'                => 'true'
    )
  end

  Annotate.load_tasks
end
```

# 参考

https://tech.mof-mof.co.jp/blog/rails-annotate/

https://qiita.com/koki_develop/items/ae6b5f41c18b2872d527

https://qiita.com/SAPPOROBEER/items/8cc6040f9090b161eba5

# 最後に

いかがでしたでしょうか。
ここ違うよ！でしたり、こうした方がいいよ！などがあればコメントいただけると幸いです。

他にも下記のような記事を投稿しております。
興味がありましたら、ぜひご覧ください。

https://qiita.com/sekkey_777/items/b40135995de01ae95dc2