11 ways you can use ChatGPT to write code

11 ways you can use ChatGPT to write code | Santiagoにコーディング時のChatGPTユースケースが紹介されていた。

以下のページよりイケてない設定として載っているコードをお借りし、多少修正した上でChatGPTに質問してみた。

コードの説明

Question

以下のコードが何をしているか説明してください。

class OrdersReport
  def initialize(orders, start_date, end_date)
    @orders = orders
    @startDate = start_date
    @endDate = end_date
  end
 
  def totalSalesWithinDateRange
    ordersWithinRange = []
    @orders.each do |order|
      if order.placed_at >= @startDate && order.placed_at <= @endDate
        ordersWithinRange << order
      end
    end
 
    sum = 0
    orders_within_range.each do |order|
      sum = sum + order.amount
    end
    return sum
  end
end
 
class Order < OpenStruct
end

ChatGPT

このコードは、注文(order)のレポートを生成するクラスを定義しています。

OrdersReportクラスは、初期化時に、注文のリスト(orders)、レポートを作成する期間の開始日(start_date)、終了日(end_date)を引数として受け取ります。

また、OrdersReportクラスには、totalSalesWithinDateRangeメソッドが定義されています。このメソッドは、指定された期間内に注文された注文の総額を計算して返すものです。

最後に、Orderクラスは、OpenStructクラスを継承しています。OpenStructクラスは、Rubyで手軽に構造体のようなオブジェクトを作成するためのクラスです。

コードの改善

Question

以下のコードをRubyの命名規則、Rubyの慣用的なスタイルを用いて書き換えてください。さらに、コード全体を簡略化してください。

class OrdersReport
  def initialize(orders, start_date, end_date)
    @orders = orders
    @startDate = start_date
    @endDate = end_date
  end
 
  def totalSalesWithinDateRange
    ordersWithinRange = []
    @orders.each do |order|
      if order.placed_at >= @startDate && order.placed_at <= @endDate
        ordersWithinRange << order
      end
    end
 
    sum = 0
    orders_within_range.each do |order|
      sum = sum + order.amount
    end
    return sum
  end
end
 
class Order < OpenStruct
end

ChatGPT

改善されたコードは以下のようになります。

class OrdersReport
  def initialize(orders, start_date, end_date)
    @orders = orders
    @start_date = start_date
    @end_date = end_date
  end
 
  def total_sales_within_date_range
    orders_within_range = @orders.select { |order| order.placed_at >= @start_date && order.placed_at <= @end_date }
    orders_within_range.sum { |order| order.amount }
  end
end
 
class Order < OpenStruct
end
  • キャメルケースのメソッド名、変数名がスネークケースに修正されている
  • 単純にeachでループして処理していたロジックが、Enumerable#selectEnumerable#sumを用いて簡略化されている

テストケースの作成

Question

改善されたOrdersReportクラスの動作をテストするためのコードをいくつか書いてください。

ChatGPT

次のようなコードで、OrdersReportクラスの動作をテストすることができます。

# テスト用の注文を生成する
orders = [
  Order.new(amount: 100, placed_at: Time.new(2020, 1, 1)),
  Order.new(amount: 200, placed_at: Time.new(2020, 1, 2)),
  Order.new(amount: 300, placed_at: Time.new(2020, 1, 3)),
  Order.new(amount: 400, placed_at: Time.new(2021, 1, 1)),
  Order.new(amount: 500, placed_at: Time.new(2021, 1, 2)),
]
 
# OrdersReportクラスを使用して、2020年1月1日から2020年1月3日までの期間の総額を計算する
report = OrdersReport.new(orders, Time.new(2020, 1, 1), Time.new(2020, 1, 3))
total_sales = report.total_sales_within_date_range
 
# 期待する結果が得られているかを確認する
if total_sales == 600
  puts "SUCCESS"
else
  puts "FAILED"
end
 

Question

Test::Unit用のテストコードをお願いします。

ChatGPT

Test::Unitを使用してOrdersReportクラスをテストする場合、以下のようなコードを書くことができます。

require "test/unit"
 
class OrdersReportTest < Test::Unit::TestCase
  def setup
    # テスト用の注文を生成する
    @orders = [
      Order.new(amount: 100, placed_at: Time.new(2020, 1, 1)),
      Order.new(amount: 200, placed_at: Time.new(2020, 1, 2)),
      Order.new(amount: 300, placed_at: Time.new(2020, 1, 3)),
      Order.new(amount: 400, placed_at: Time.new(2021, 1, 1)),
      Order.new(amount: 500, placed_at: Time.new(2021, 1, 2)),
    ]
  end
 
  def test_total_sales_within_date_range
    # OrdersReportクラスを使用して、2020年1月1日から2020年1月3日までの期間の総額を計算する
    report = OrdersReport.new(@orders, Time.new(2020, 1, 1), Time.new(2020, 1, 3))
    total_sales = report.total_sales_within_date_range
 
    # 期待する結果が得られているかを確認する
    assert_equal(600, total_sales)
  end
end
 

ドキュメントの生成

Question

このクラスのドキュメントを書いてください。

ChatGPT

以下がOrdersReportクラスのドキュメントになります。

# OrdersReportクラスは、指定された期間内の注文の総額を計算するクラスです。
#
# 使用方法は以下の通りです。
#
#   orders = [Order.new(amount: 100, placed_at: Time.new(2020, 1, 1)),
#             Order.new(amount: 200, placed_at: Time.new(2020, 1, 2)),
#             Order.new(amount: 300, placed_at: Time.new(2020, 1, 3))]
#   report = OrdersReport.new(orders, Time.new(2020, 1, 1), Time.new(2020, 1, 3))
#   total_sales = report.total_sales_within_date_range
#
#   puts total_sales # => 600
#
# OrderクラスはOpenStructを継承したクラスで、amountとplaced_atという属性を持ちます。
class OrdersReport
  # OrdersReportクラスを初期化する
  # @param orders [Array<Order>] 注文の配列
  # @param start_date [Time] 開始日時
  # @param end_date [Time] 終了日時
  def initialize(orders, start_date, end_date)
  end
 
  # 指定された期間内の注文の総額を返す
  # @return [Integer] 注文の総額
  def total_sales_within_date_range
  end
end
 
# 注文を表すクラス
class Order < OpenStruct
end

コードの翻訳

Question

このコードをpythonで書いてください。

ChatGPT

以下が、Pythonで書き換えられたOrdersReportクラスになります。

from dataclasses import dataclass
 
@dataclass
class Order:
    """注文を表すクラス"""
    amount: int
    placed_at: datetime
 
class OrdersReport:
    """OrdersReportクラスは、指定された期間内の注文の総額を計算するクラスです。
 
    使用方法は以下の通りです。
 
    orders = [Order(amount=100, placed_at=datetime(2020, 1, 1)),
              Order(amount=200, placed_at=datetime(2020, 1, 2)),
              Order(amount=300, placed_at=datetime(2020, 1, 3))]
    report = OrdersReport(orders, datetime(2020, 1, 1), datetime(2020, 1, 3))
    total_sales = report.total_sales_within_date_range()
 
    print(total_sales) # => 600
    """
 
    def __init__(self, orders, start_date, end_date):
        """OrdersReportクラスを初期化する
 
        :param orders: 注文の配列
        :type orders: List[Order]
        :param start_date: 開始日時
        :type start_date: datetime
        :param end_date: 終了日時
        :type end_date: datetime
        """
        self.orders = orders
        self.start_date = start_date
        self.end_date = end_date
 
    def total_sales_within_date_range(self):
        """指定された期間内の注文の総額を返す
 
        :return: 注文の総額
        :rtype: int
        """
        orders_within_range = []
        for order in self.orders:
            if order.placed_at >= self.start_date and order.placed_at <= self.end_date:
                orders_within_range.append(order)
 
        sum = 0
        for order in orders_within_range:
            sum += order.amount
        return sum

バグの追跡

Question

このコードのバグを見つけてください。

class OrdersReport
  def initialize(orders, start_date, end_date)
    @orders = orders
    @start_date = start_date
    @end_date = end_date
  end
 
  def total_sales_within_date_range
    orders_within_range = @orders.select { |order| order.placed_at <= @start_date && order.placed_at <= @end_date }
    orders_within_range.sum { |order| order.amount }
  end
end
 
class Order < OpenStruct
end

ChatGPT

このコードでは、orders_within_rangeを求める条件にバグがあります。

現在のコードでは、order.placed_at <= @start_date && order.placed_at <= @end_dateとなっていますが、これでは、order.placed_at@start_dateより小さいかつorder.placed_at@end_dateより小さいことを指定しています。このため、現在のコードでは、@start_date@end_dateよりも小さい場合、orders_within_rangeは空になってしまいます。

これを修正するには、条件をorder.placed_at >= @start_date && order.placed_at <= @end_dateとすることで、日付の範囲内であることを指定するようにすることで、バグを修正できます。

def total_sales_within_date_range
  orders_within_range = @orders.select { |order| order.placed_at >= @start_date && order.placed_at <= @end_date }
  orders_within_range.sum { |order| order.amount }
end

Scaffolding

Question

Webページをスクレイピングし取得したデータをsqlite3のデータベースへ格納するためのコードをRubyで書いてください。

ChatGPT

RubyでWebスクレイピングを行うためには、例えば「mechanize」や「nokogiri」といったライブラリを使用することができます。

下記は、mechanizeを使用してWebページをスクレイピングし、そのデータをsqlite3のデータベースへ格納するコードの例です。

require 'mechanize'
require 'sqlite3'
 
# Webスクレイピング用のクライアントを生成
agent = Mechanize.new
 
# スクレイピングするWebページを開く
page = agent.get('https://example.com')
 
# データを取得する
title = page.title
data = page.body
 
# sqlite3のデータベースを開く
db = SQLite3::Database.new 'scraping.db'
 
# テーブルを作成する
db.execute("CREATE TABLE IF NOT EXISTS pages (id INTEGER PRIMARY KEY, title TEXT, data TEXT)")
 
# データを挿入する
db.execute("INSERT INTO pages (title, data) VALUES (?, ?)", title, data)
 
# データベースを閉じる
db.close