コード日進月歩

しんくうの技術的な小話、メモ、つれづれ、など

RubyのCSVクラスでheaders:trueにするとき、空白文字列の扱いに気をつける

要因がわかれば自明だけどわかりづらい、自分の引いたバッドノウハウのメモ。

環境

ruby -v
ruby 3.0.1p64 (2021-04-05 revision 0fb782ee38) [x86_64-darwin19]

どういうことか

headerの文字列一致は空白も含めて行われる、そしてheaderの文字列が存在しないときにエラーなどは発生しないので気をつける。

下記のようなcsvがあるとする

$ cat test.csv
id,name ,age
1,taro,20
2,ziro,19
3,saburo,17

このcsvと同じディレクトリで以下のコードを sample1.rb として作る

require "csv"
CSV.foreach("test.csv",headers: true){ |row| p row["age"] }

結果としては以下

$ ruby sample1.rb
"20"
"19"
"17"

そして以下のコードを sample2.rb として作る

require "csv"
CSV.foreach("test.csv",headers: true){ |row| p row["name"] }

結果は以下のようになる

ruby sample2.rb
nil
nil
nil

このように完全に一致するヘッダがない場合はnilを返却する。正しくは以下のようなコード

require "csv"
CSV.foreach("test.csv",headers: true){ |row| p row["name "] }
ruby sample3.rb
"taro"
"ziro"
"saburo"

今回csvの列の2列目に含まれているため自明だが、末尾の列のheaderに空白が入っていると目視判断はつきづらい。例えば下記は age ではなく age だがエディタの助けがない限り判断はつかない

$ cat test.csv
id,name,age 
1,taro,20
2,ziro,19
3,saburo,17

まとめ

  • headerの行に関しては CSV.parse_line の挙動に従いパースされるので、添字に文字列を使う場合は空白文字列も含めて認識される
  • csv(さらにはtsv)の場合、末尾の空白は目視がしにくいので気をつける

関連リンク

URIでパーセントエンコーディングが推奨されない文字を整理する

原理を知っていれば納得な話なんですが、仕様に基づいた整理。

出典

RFC 3986 - Uniform Resource Identifier (URI): Generic Syntax

どういうことか

RFC3986では予約文字(Reserved Character)と非予約文字(Unreserved Character)という表現で利用できる文字が定義されている。

非予約文字は「利用可能な文字」を表すもので、対象としては以下の文字が定義されている。

unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"
  • ALPHA(アルファベットA-Z,a-z)
  • DIGIT(数字0-9)
  • -(ハイフン)
  • .(コロン)
  • _(アンダーバー)
  • ~(波線)

これらの文字はそのまま利用可能な文字なので、逆に考えるとこの文字はパーセントエンコーディングするべきではない文字ということになる。

ただ、エンコーディングを完全にしてはいけないというわけではなく、ちゃんと意味が通るようにエンコーディングされていればよい。

たとえば A0あ0という文字列をURLエンコーディングさせたい場合は、通常は

A0%E3%81%820

となるが、0を %30エンコードして

A0%E3%81%82%30

としても問題はない。

関連リンク

URIの自由設定部分で使えない予約された文字

エンコードされる文字列はあるが、具体的に何を含むと面倒なのかを調べる。

出典

URIに利用可能な文字列の定義はRFC3986より

RFC 3986 - Uniform Resource Identifier (URI): Generic Syntax

定義

RFC3986の中に、予約文字と非予約文字がある。予約文字として紹介されているのが以下。

記号 読み方
! エクスクラメーション
# シャープ
$ ドル
& アンド
' アポストロフィ
( 始め丸括弧、パーレン
) 終わり丸括弧
* アスタリスク、米マーク
+ プラス
, カンマ
/ スラッシュ
: コロン
; セミコロン
= イコール
? はてな、クエスチョン
@ アットマーク
[ 始め角括弧、ブラケット
] 終わり角括弧

この文字列は予約文字のため、何らかの用途で使われるもののため、クエリパラメータの文字などとして使いたい場合はパーセントエンコードする必要がある。

参考リンク

情報セキュリティ技術動向調査(2009 年下期):IPA 独立行政法人 情報処理推進機構

海外にはドラマのためなどの架空の電話番号はあるが、日本にはない

example.com の電話番号版のようなものが存在しないのか調べた

TL;DR

日本には明示的に案内されているダミー(フィクションなどに使う用途)の電話番号はない。

日本以外の例

日本以外にはある。

Fictitious telephone number - Wikipedia

各国いろいろな形であるのだが、例えば以下のような形。

  • アメリカはドラマや映画用で「555-0100〜555-0199」が使われる(もともとは架空の番号用途ではなかったが、現在では予約されている)
  • オーストラリアは決め打ちでいくつかの番号がフィクションの利用のために抑えられている

日本の場合

日本ではそのように「フィクションのための用途」というものは存在しておらず、ドラマや小説などでは基本的には伏せ字を使って表現をする。

関連リンク

EdgeやSafariは電話番号っぽいものに勝手にハイパーリンクをしてしまうが、制御できるタグがある

サポート範囲がわからなかったのでざっくりまとめる。

TL;DR

  • SafariやEdgeで電話番号と思わしき文字列があると自動でハイパーリンクが設定され、タップすると電話をかけられるようになる。しかしながらそうしてほしくない場面もある。
  • <meta name="format-detection" content="telephone=no"> を使うとApple系(Safari)もMicrosoft系(Edge,IE)も自動処理をしないようにしてくれる
  • Microsoft系だけ、x-ms-format-detection という選択肢が用意されている

両方とも有効なformat-detection

記述方法は以下、ページ全体に適用となる。

<meta name="format-detection" content="telephone=no">

出典は以下、まずはApple

By default, Safari on iOS detects any string formatted like a phone number and makes it a link that calls the number. Specifying telephone=no disables this feature. ( デフォルトでは、iOS上のSafariは電話番号のような形式の文字列を検出し、その番号を呼び出すリンクにします。telephone=noを指定すると、この機能が無効になります。 ) - Supported Meta Tags

そしてMicrosoft

To disable the behavior for a webpage, use the meta element: <meta name="format-detection" content="telephone=no"/> - Phone number format recognition (Windows) | Microsoft Docs?redirectedfrom=MSDN)

Microsoft系(Edge,IE11))のみに有効なx-ms-format-detection

記述例としては以下、こちらはmetaタグではなくタグの属性として記述をしてあげればOK。以下はpタグに付与した例。

<p x-ms-format-detection="none"> 090-000-0000 </p>

また、x-ms-format-detection の値にあたる部分は三種類用意されているが none のみが無効の設定となる。

Phone number format recognition (Windows) | Microsoft Docs?redirectedfrom=MSDN)

電話番号をちゃんと指定したい場合はどうするべきか

逆の話にはなるが、電話をかけられるようなハイパーリンクを作りたい場合はaタグにて tel: のURLスキームを利用する。詳しくはRFC3966に定義があるのでそちらを参考のこと。

関連リンク

HTMLのmetaタグのnameに関しては情報がまとまっているページがある

metaのnameに使える文字って何があるのか、というのをざっくりまとめる。

出典

標準メタデータ名 - HTML: HyperText Markup Language | MDN

name属性の値の考え方

もともと <meta> のタグ自体はMDNの記載曰く

HTML の < meta > 要素は、他のメタ関連要素 (< base >, < link >, < script >, < style >, < title >) で表すことができない任意のメタデータを提示します。 - : 文書レベルメタデータ要素 - HTML: HyperText Markup Language | MDN

という形でいわゆる文章内に記載しないメタデータを取り扱うためのタグ。

そしてname属性はcontent属性とワンセットで扱われ、nameの内容に応じてcontentを記述するという形になる。

標準的に決まっているもの

このnameに指定できる値で標準的に仕様が決まっているものは Standard metadata names という形でHTML Living Standardに定義がある。

そこで紹介されているのは以下のもの。

  • application-name
  • author
  • description
  • keywords
  • referrer
  • theme-color
  • color-scheme

他の仕様によって決まっているもの

W3CWHATWGによって標準的なものと認識されているもの以外のもので、ある種デファクトスタンダードなものが多数存在する。viewportなどが一番わかり易い例で、多くのサイトに記述があり、各社のブラウザもviewportとセットで記述されたcontentの値を見て挙動を制御する。

このような標準的ではないものに関して仕様がまとまっているページがWHATWG内のwikiにある。

MetaExtensions - WHATWG Wiki

例にあげた viewportCSSの仕様に準じた記述ということが解説されている。

関連リンク

GoogleAnalyticsのセッションとしてCookieの保持期限はデフォルトだと2年で設定される

GoogleAnalyticsは個別のIDなどを降るが、そのIDが同じユーザーとみなす情報の保持期限はどれくらいなのか

出典

Cookie とユーザーの識別  |  ウェブ向けアナリティクス(analytics.js)  |  Google Developers

上記のサイト曰く

ヒットが Google アナリティクスに送信されるたびに、Cookie の有効期限はその時点の時刻と cookieExpires フィールドの値を足した値に更新されます。したがって、デフォルトの cookieExpires の時間である 2 年間を使用している状況で、ユーザーが毎月サイトを訪問する場合、Cookie が期限切れになることはありません。

と記載があり、gaのオブジェクトをcreateするときに特別引数を指定しない場合は2年間は保持される。また、2年以内に再訪すれば値が更新がされる、らしい。

関連リンク