ルビー(星野瑠美衣)
仕事の話。何故か誰も書かないはずなのにrubyで動いているバッチがあり、それの改修を行おうとした。謎っぽい部分があって自宅PC環境にもrubyの環境を作った。適当に書いていたら狂ったように警告が出まくるので発狂しそうになったが、まあそんなもんだろう。言語というかプラットフォームが異なるというのは、異国に立ち入ることと同義だ。我々は旅人であり、立ち入った地の掟に従うべきである。「変数名をsnake caseにしろ!」「インデントはspace2charにしろ!」「3.0だかで文字列はイミュータブルにうんたらかんたら!」もう無理、狂いそう。
# rubocop:disable all
ハイ解決。「ヒャッハー!原住民は黙れ!黙れええい!」万が一検索で引っかかって見ている方がいるかも知れないので書きますが、 マジでrubyを習得したい人はやっちゃダメです 。
ほんとどいつもこいつもVisual Studio様(& C#)の爪の垢を煎じて飲め。※C#は言語自体がIDEを前提に考えられているので酷な物言いなのだが。
でだ、なんとrubyさん、boolで返ってくるような文字列の数値判定がないらしいのだ。PHPではis_numeric, ctype_digitなど。C#ではTryParse, String.All(char.IsDigit)など。まあこのあたりも毎度毎度で要件を完全に満たさないので改良してオレオレメソッド作ったりするのだけど。しかし、こんなもんに正規表現使いたくないぞ。rubyって正規表現速いのかな?知らんが。regex = 遅いという認識なので、どうしても必要がある場合以外は極力使いたくない。
で、rubyのcsv出力なのだが、文字列はダブルクオートで囲い、数値はそのまま出力したいのだが無いの。無いのよ。設定が。force_quotes:trueだと数値も囲っちゃうの。会社PCのrubyバージョンなのかな?と思ったがそうではないみたいなのね。
で、調べまくったが皆さん正規表現なのよなー。キャストして例外吐いたらfalseみたいな判別もあって笑ったけど、え?笑い事じゃない?
(20201031 すべて書き直したのを下に)
csvの中身
"Nier",100,"かぐや様",0050,-150,"回天剣舞六連","1.52",+1500,"2020-10-30","栗花落カナヲ"
"Nier",100,"かぐや様",0050,-150,"回天剣舞六連","1.52",+1500,"2020-10-30","栗花落カナヲ"
...
要件(データを取得するqueryでCOALESCE使うのでNULLは入ってこないしuintなので負の数もない)はクリアしているし特にアイデアもないのだけど、rubyメインの人はここらへん全てを正規表現でやってるんじゃろか。俺のググらびりてぃが低い?
追記
やはり00XX, +-XXXがキャストしていないのにint判定はどうかと思ったので修正。ちなみに空白はInteger(value)の時点で例外なので文字列判定です。
(20201031 すべて書き直したのを下に)
csv
"Nier",100,"かぐや様","0050","-150","回天剣舞六連","1.52","+1500","2020-10-30","栗花落カナヲ"
"Nier",100,"かぐや様","0050","-150","回天剣舞六連","1.52","+1500","2020-10-30","栗花落カナヲ"
...
うーん、なんか美しくないけどまあいいか。
追記
Classじゃないと気持ち悪いのでちょろっと入門サイト見てきた。
(20201031 すべて書き直したのを下に)
classのfieldは@@付けるのキモすぎ。それよりコンストラクタ内で初期化したわけでもないのに
@@output_file_path = './' + Time.now.to_i.to_s + '.csv'
これがエラーにならずに値が入っているのに驚いた。詳しく調べる気はないけどなんか不思議だなー。
追記
読みづらくて仕方がない && 0の文字列長が考慮されていないのを修正。なので書き直し && gistやっぱ普通に貼る。
# rubocop:disable all
require 'date'
class CsvFile
@@output_file_path = './' + Time.now.to_i.to_s + '.csv'
@@data = ['0', '100', 'かぐや様', '0050', '-150', '回天剣舞六連', '1.52', '+1500', '', '栗花落カナヲ']
private
def add_double_quote_to_string(values)
# 文字列はダブルクオートで囲む
result = []
values.each do |val|
if is_integer?(val) then
result << val
else
result << "\"" + val + "\""
end
end
return result
end
private
def is_integer?(value)
Integer(value)
if value.include?('+') || value.include?('-') then
return false
elsif value[0, 1] == '0' && value.size != 1 then
return false
end
return true
rescue ArgumentError
return false
end
public
def running
# たかが10000のループで落ちるんだが……しかたないので100
data_array = []
for idx in 1..100 do
data_array << add_double_quote_to_string(@@data)
end
File.open(@@output_file_path, "w") do |f|
data_array.each do |data|
f.puts(data.join(','))
end
end
puts 'end.'
end
end
obj = CsvFile.new
obj.running