Claude 3.5 Sonnetを使ってOpenAPI仕様のAPI仕様書からRailsのソースコードを生成する

開発の効率化の検証のために、
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:

  1. Gemfile
  2. config/routes.rb
  3. app/controllers/application_controller.rb
  4. app/controllers/shops_controller.rb
  5. app/models/shop.rb
  6. db/migrate/YYYYMMDDHHMMSS_create_shops.rb
  7. 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:

  1. devise_token_auth: This gem provides token-based authentication, which is required for the API as specified in the OpenAPI document.
  2. jbuilder: Although not strictly necessary, this gem can be helpful for building JSON responses in a more structured way.
  3. 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.
  4. kaminari: (Not included in the Gemfile, but recommended) This gem provides easy pagination, which would be useful for implementing the page parameter in the shop listing endpoint.

To set up the project, you would need to:

  1. Run bundle install to install the gems.
  2. Run rails db:create db:migrate to set up the database.
  3. 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.

役に立ったらシェアしていただけると嬉しいです
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次