🔖
Rails7.13 generatorコマンドを使用してファイルを自動生成
はじめに
Rails generatorコマンドを使用して、model、service、rspec関連ファイルを効率的に生成する方法をご紹介します。
実行環境
- M2 mac mini
- Rails 7.1.3
- Ruby 3.2.3
- Mysql 8.0
- Docker 25.0.2
- vscodeエディタ
環境構築が済んでいない方はこちらを参考に環境構築を行なってください。
Schemafileの導入がまだの方はこちらから設定してください。
RSpecの導入
Grapeとgrape-entityの導入
フォルダ構成
app/
api/
v1/
posts.rb
entitys/
post.rb
models/
post.rb
services/
posts.rb
db/
Schemafile
lib/
generators/
apis/
apis_generator.rb
USAGE
template/
controller.rb.erb
entity.rb.erb
service.rb.erb
test.rb.erb
spec/
models/
post_spec.rb
factories/
posts.rb
services/
post_service_spec.rb
serviceフォルダの作成
mkdir app/services && mkdir spec/services
generatorの作成
ターミナルから以下のコマンドでrailsのgeneratorにapisを追加
※apiの場合、a_p_iとなってしまうため、apisで作成。
docker-compose exec web rails g generator apis
- create lib/generators/apis
- create lib/generators/apis/apis_generator.rb
- create lib/generators/apis/USAGE
- create lib/generators/apis/templates
- invoke rspec
以下のフォルダとファイルを削除(使用しないため) - create spec/generator/apis_generator_spec.rb
作成したgeneratorを確認
docker-compose exec web rails g -h
Apis:
apis
生成する雛形ファイルを生成
touch lib/generators/apis/templates/{controller.rb.erb,entity.rb.erb,service.rb.erb,test.rb.erb}
雛形ファイルを修正
controller雛形修正
lib/generators/apis/templates/controller.rb.erb
module V1
class <%= class_name.pluralize.camelize %> < Grape::API
=begin
<%- class_name.camelize.constantize.columns.each do |col| -%>
optional :<%= col.name %>, type: <%=
col.type.to_s == 'datetime' ? 'DateTime':
col.type.to_s == 'text' ? 'String':
col.type.to_s == 'boolean' ? 'Boolean':
col.type.to_s.camelize %>, description:''
<%- end -%>
=end
resource :<%= class_name.pluralize.underscore %> do
desc '一覧取得', { success: { model: Entitys::<%= class_name.camelize %> }, is_array:true }
params do
use :pagination
end
get '' do
<%= class_name.underscore %> = <%= class_name.camelize %>.all.per(params[:per_page])
present <%= class_name.underscore %>, with: Entitys::<%= class_name.camelize %>
end
desc '詳細取得', { success: { model: Entitys::<%= class_name.camelize %> } }
params do
requires :id, type: Integer, description:'ID'
end
get '/:id' do
<%= class_name.underscore %> = <%= class_name %>.find(params)
present <%= class_name.underscore %>, with: Entitys::<%= class_name.camelize %>
end
desc '新規作成', { success: { model: Entitys::<%= class_name.camelize %> } }
params do
end
post '' do
<%= class_name.underscore %> = <%= class_name %>.create!(params)
present <%= class_name.underscore %>, with: Entitys::<%= class_name.camelize %>
end
desc '更新', { success: { model: Entitys::<%= class_name.camelize %> } }
params do
requires :id, type: Integer, description:'ID'
end
put '/:id' do
<%= class_name.underscore %> = <%= class_name %>.find(params[:id])
<%= class_name.underscore %>.save!
present <%= class_name.underscore %>, with: Entitys::<%= class_name.camelize %>
end
desc '削除', { success: { model: Entitys::<%= class_name.camelize %> } }
params do
requires :id, type: Integer, description:'ID'
end
delete '/:id' do
<%= class_name.underscore %> = <%= class_name %>.find(params[:id])
<%= class_name.underscore %>.delete
present <%= class_name.underscore %>, with: Entitys::<%= class_name.camelize %>
end
end
end
end
entity雛形修正
lib/generators/apis/templates/entity.rb.erb
module Entitys
class <%= class_name.camelize %> < Grape::Entity
<%- class_name.camelize.constantize.columns.each do |col| -%>
expose :<%= col.name %>, documentation: { type: '<%=
col.type.to_s == 'datetime' ? 'DateTime':
col.type.to_s == 'text' ? 'String':
col.type.to_s == 'boolean' ? 'boolean':
col.type.to_s.camelize %>' }
<%- end -%>
end
end
service雛形修正
lib/generators/apis/templates/service.rb.erb
module Service
class <%= class_name.pluralize.camelize %>
end
end
test雛形修正
lib/generators/apis/templates/test.rb.erb
require 'rails_helper'
RSpec.describe <%= class_name.camelize %> do
end
apis_generator.rb
lib/generators/apis/apis_generator.rb
class ApisGenerator < Rails::Generators::NamedBase
source_root File.expand_path("templates", __dir__)
# APIのコントローラーを作成する
def create_controller_file
destination = Rails.root.join("app/api/v1/#{class_name.pluralize.underscore}.rb")
template('controller.rb.erb', destination)
end
# APIのEntityを作成する
def create_entity_file
destination = Rails.root.join("app/api/entitys/#{class_name.underscore}.rb")
template('entity.rb.erb', destination)
end
# サービスクラスを作成する
def create_service_file
destination = Rails.root.join("app/services/service/#{class_name.pluralize.underscore}.rb")
template('service.rb.erb', destination)
end
# サービスクラスのspecテストクラスを作成する
def create_test_file
destination = Rails.root.join("spec/services/#{class_name.underscore}_service_spec.rb")
template('test.rb.erb', destination)
end
end
ファイルの生成
以下の手順で作成し、コマンドを実行
※ model、DBにマイグレーションしていない場合、生成に失敗します。
1.Schemafileにテーブルを定義
2.テーブルをDBにマイグレーション
3.モデルの作成(マイグレーションをスキップ)
4.generatorコマンドでファイルを生成
Schemafileにpostsテーブルを適当に定義
Schemafile
options = "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=COMPRESSED"
create_table "posts", force: :cascade, options: options do |t|
t.string :title, null: false
end
テーブルをDBにマイグレーション
docker-compose exec web rake ridgepole:apply RAILS_ENV=development
モデルの作成
docker-compose exec web rails g model Post --skip-migration
entity、service、rspec関連ファイルを生成
docker-compose exec web rails g apis Post
まとめ
Rails generatorを活用すれば、開発時間を大幅に短縮することができます。ぜひ本記事を参考に、挑戦してみてください。
Discussion