Skip to content

Instantly share code, notes, and snippets.

@mattsan
Last active January 26, 2025 00:26
Show Gist options
  • Save mattsan/19b06a78e6f4c5c07c22ed137bfea979 to your computer and use it in GitHub Desktop.
Save mattsan/19b06a78e6f4c5c07c22ed137bfea979 to your computer and use it in GitHub Desktop.
SheetWriter
class SheetWriter
class Row
def initialize(writer, headers, index)
@writer = writer
@headers = headers
@index = index
end
def []= (header, value)
@writer[@index, @headers.index_of(header)] = value
end
end
class Headers
def initialize(writer, headers, initial_index)
@writer = writer
@indices = headers.zip(initial_index..).to_h
@next_header_index = @indices.size + initial_index
@initial_index = initial_index
@indices.each { |header, index| writer[initial_index, index] = header }
end
def add(header)
@writer[@initial_index, @next_header_index] = header
@indices[header] = @next_header_index
@next_header_index = @next_header_index.succ
end
def index_of(header)
add(header) if !@indices.has_key?(header)
@indices[header]
end
end
def initialize(sheet, headers: [], initial_index: 1)
@sheet = sheet
@headers = Headers.new(self, headers, initial_index)
@last_row_index = initial_index
end
def next_row
@last_row_index = @last_row_index.succ
Row.new(self, @headers, @last_row_index)
end
def []= (row_index, column_index, value)
@sheet.append(row_index, column_index, value)
end
end
require 'minitest/autorun'
require_relative 'sheet_writer'
class SheetWriterTest < Minitest::Test
describe '初期化時にヘッダ行を指定しない' do
before do
@sheet = []
@writer = SheetWriter.new(@sheet)
end
it '初期化直後は空であること' do
assert_equal [], @sheet
end
it '最初にヘッダを指定した順にヘッダが追加され、以降ヘッダ行の位置にデータが挿入されること' do
row = @writer.next_row
row['Charlie'] = 33
row['Alice'] = 11
row['Bob'] = 22
row = @writer.next_row
row['Bob'] = 222
row['Alice'] = 111
row['Charlie'] = 333
assert_equal [1, 1, 'Charlie', 2, 1, 33, 1, 2, 'Alice', 2, 2, 11, 1, 3, 'Bob', 2, 3, 22, 3, 3, 222, 3, 2, 111, 3, 1, 333], @sheet
end
end
describe '初期化時にヘッダ行を指定する' do
before do
@sheet = []
@writer = SheetWriter.new(@sheet, headers: %w(Alice Bob Charlie))
end
it 'ヘッダ行が headers の値で初期化されること' do
assert_equal [1, 1, 'Alice', 1, 2, 'Bob', 1, 3, 'Charlie'], @sheet
end
it '初期化時に指定したヘッダ行の位置にデータが挿入されること' do
row = @writer.next_row
row['Charlie'] = 33
row['Alice'] = 11
row['Bob'] = 22
row = @writer.next_row
row['Bob'] = 222
row['Alice'] = 111
row['Charlie'] = 333
assert_equal [1, 1, 'Alice', 1, 2, 'Bob', 1, 3, 'Charlie', 2, 3, 33, 2, 1, 11, 2, 2, 22, 3, 2, 222, 3, 1, 111, 3, 3, 333], @sheet
end
end
describe '独自クラス' do
class Sheet
attr_reader :sheet
def initialize
@sheet = []
end
def append(row_index, column_index, value)
@sheet[row_index] ||= []
@sheet[row_index][column_index] = value
end
end
before do
@sheet = Sheet.new
@writer = SheetWriter.new(@sheet, initial_index: 0)
end
it '' do
row = @writer.next_row
row['Charlie'] = 33
row['Alice'] = 11
row['Bob'] = 22
row = @writer.next_row
row['Bob'] = 222
row['Alice'] = 111
row['Charlie'] = 333
assert_equal [['Charlie', 'Alice', 'Bob'], [33, 11, 22], [333, 111, 222]], @sheet.sheet
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment