開発の効率化の検証のために、
Claude 3.5 Sonnetを使って、OpenAPI仕様のAPI仕様書からRailsのAPIソースコードを生成することを試してみました。
利用したAPI仕様書は、店舗(Shop)に対するCRUDを定義したシンプルなものです。
claudeのサイトから生成を行いました。
質問の仕方(プロンプト)が大事かと思いますが、今回は一旦雑に質問をして試してみました。
※生成された全文は本記事の末尾に掲載します。
まず、生成されたコードをもとにRailsの環境構築を試みました。
生成されたGemfileではRailsのバージョン6.1以上を指定していましたが、
操作時点での最新版は7.2.1なので、注意する必要があると感じました。
また、手順に従ったところデータベースの作成やサーバーの起動時にエラーとなりました。
前提としているモデルやgemなどが足りないようでした。
環境の構築までは世に多くある手順書を参照した方が良いかもしれないと思いました。
次に生成された処理(controllerやmodel)について、
contorllerについては、単純なCRUDだからかもしれませんが、大枠の処理について記述がされていました。
ただ、ソース上ではgem kaminariのメソッドが使われていましたが、claudeでの説明では利用推奨の追加gemになっていたため、そのままでは利用できませんでした。
また、openapiに非ログインの場合にエラーを返すレスポンスが定義されていたからか、
認証の処理が記載されていましたが、前提のモデル等が足りていないのでエラーとなっていました。
modelについて、各カラムの必須validationが記載されていました。
phone_numberについては、仕様書には記載がない「10桁から11桁のみ許可する」というvalidationが追加されていました。
phone_numberというカラム名から推測して追記されたのかもしれません。
結論
現状では、雑に質問するだけでは、生成されたコードをそのままの利用はできないと感じました。
Railsの過去バージョンを指定していたりと罠もあったので生成されたコードでうまく動いていたとしても注意が必要だと思いました。
一方で、プロンプトを改善すれば、大枠を生成するということには役立ちそうに思いました。
ただ、使い慣れている言語やフレームワークに対してはそのような需要はないと思うので、
新しい言語やフレームワークをすぐに始めなければいけない場合のとっかかりとしては使えるのではないか
と思いました。
参考
Claudeで生成された全文
Certainly, I’ll create the necessary Rails project files to meet the OpenAPI specification you’ve provided. I’ll also suggest additional gems that might be helpful for this project.
Let’s start by creating the basic structure and then I’ll provide the content for each file.
First, let’s list the files we’ll need to create:
- Gemfile
- config/routes.rb
- app/controllers/application_controller.rb
- app/controllers/shops_controller.rb
- app/models/shop.rb
- db/migrate/YYYYMMDDHHMMSS_create_shops.rb
- config/initializers/devise_token_auth.rb
Now, let’s create each file:
Gemfile
source 'https://rubygems.org' gem 'rails', '~> 6.1.0' gem 'sqlite3' gem 'puma' gem 'bootsnap', require: false # API-related gems gem 'jbuilder' gem 'rack-cors' # Authentication gem 'devise_token_auth' group :development, :test do gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] end group :development do gem 'listen' gem 'spring' gem 'spring-watcher-listen' end
config/routes.rb
Rails.application.routes.draw do mount_devise_token_auth_for 'User', at: 'auth' resources :shops end
app/controllers/application_controller.rb
class ApplicationController < ActionController::API include DeviseTokenAuth::Concerns::SetUserByToken before_action :authenticate_user! end
app/controllers/shops_controller.rb
class ShopsController < ApplicationController before_action :set_shop, only: [:show, :update, :destroy] def index @shops = Shop.all @shops = @shops.where("name LIKE ?", "%#{params[:name]}%") if params[:name].present? @shops = @shops.page(params[:page] || 1) render json: { shops: @shops } end def show render json: @shop end def create @shop = Shop.new(shop_params) if @shop.save render json: { status: 'success', data: @shop }, status: :created else render json: { error: { error_code: 400001, messages: @shop.errors.full_messages } }, status: :bad_request end end def update if @shop.update(shop_params) render json: { status: 'success' } else render json: { error: { error_code: 400001, messages: @shop.errors.full_messages } }, status: :bad_request end end def destroy @shop.destroy render json: { success: true } end private def set_shop @shop = Shop.find(params[:id]) rescue ActiveRecord::RecordNotFound render json: { error: { error_code: 404001, messages: ['ページが存在しません。'] } }, status: :not_found end def shop_params params.require(:shop).permit(:name, :address, :phone_number) end end
app/models/shop.rb
class Shop < ApplicationRecord validates :name, presence: true validates :address, presence: true validates :phone_number, presence: true, format: { with: /\A\d{10,11}\z/, message: "は10桁または11桁の数字で入力してください" } end
db/migrate/YYYYMMDDHHMMSS_create_shops.rb
class CreateShops < ActiveRecord::Migration[6.1] def change create_table :shops do |t| t.string :name, null: false t.string :address, null: false t.string :phone_number, null: false t.timestamps end end end
config/initializers/devise_token_auth.rb
DeviseTokenAuth.setup do |config| config.change_headers_on_each_request = false config.token_lifespan = 2.weeks config.batch_request_buffer_throttle = 5.seconds end
Now, let me explain the additional gems we’re using and why:
devise_token_auth
: This gem provides token-based authentication, which is required for the API as specified in the OpenAPI document.jbuilder
: Although not strictly necessary, this gem can be helpful for building JSON responses in a more structured way.rack-cors
: This gem is useful for handling Cross-Origin Resource Sharing (CORS), which might be necessary if your API is accessed from different domains.kaminari
: (Not included in the Gemfile, but recommended) This gem provides easy pagination, which would be useful for implementing thepage
parameter in the shop listing endpoint.To set up the project, you would need to:
- Run
bundle install
to install the gems.- Run
rails db:create db:migrate
to set up the database.- Generate a User model for DeviseTokenAuth:
rails generate devise_token_auth:install User auth
Remember to configure your database settings in
config/database.yml
and set up any necessary environment variables.This setup provides a basic implementation that meets the OpenAPI specification. You might need to add more error handling, improve the responses to match exactly with the specified formats, and add any business logic specific to your application.
コメント