Twitterで読んだ本のメモってるのまとめてみる

大したこと書いてないし流れるままでいいかなと思ってたんだけど、この間読んだ当時の感想が役に立つことがあったので。

マンガとか読んだこともたまーに書いてるけど、そっちは後で見直してもしゃーないのでまとめない。

あと、返信はわざわざ張らない。

2017年だけやたら多いのは読んだ量もあるけど、書く割合が増えたのもある。2018年のは一年終わってからまとめる。

2014年

2016年

2017年

EloquentでのNULLABLEな日付の扱いでoptional()ヘルパ関数が便利

アクセサの値を普通に表示するだけなら、?:演算子だけでいい。PHPnullechoしても特に問題ないので。

<?php
echo $obj->created_at ?: 'default';

ただ、フォーマットしたい場合はちょっとやっかい。以下はcreated_atNULLの場合、nullのメソッドを呼び出してエラーになる。

<?php
echo $obj->created_at->format('Y/m/d') ?: 'default';

そこでoptional()を使うと便利。

<?php
echo optional($obj->created_at)->format('Y/m/d') ?: 'default';

optional()nullIlluminate\Support\Optionalクラスのオブジェクトでラップして返してくれる。このオブジェクトは、値がオブジェクトでない場合はメソッドを呼び出さないようになっている。

(なお、ドキュメントでは実装と違って、nullの場合のみエラーを防げるように書いてある)

Linux用Google ChromeのyumリポジトリのURLはどうやって探せばいいのか

2019-08-30追記

2のあたり、「別のプラットフォーム向けの Chrome をダウンロード」なくなってるっぽい。フッタのメニューに、「他のプラットフォーム」というのがあって、そこで行けそう。

追記ここまで


Linuxデスクトップは使ってないんだけど、自動テストとか用にChromeが欲しくて、ちょっと調べたところ以下のURLが出てきた。

http://dl.google.com/linux/chrome/rpm/stable/$basearch

まあ、google.comではあるんだけど、軽く探した感じどうも出所がわからなくて、このままでは使いたくない。ということでもうちょっと探した結果、以下のようにすることで見つかった。

  1. Google Chromeの公式サイトに移動。
  2. 「別のプラットフォーム向けの Chrome をダウンロード」で.rpmをダウンロード、インストール
  3. 2のダイアログの注に「注: Google Chrome をインストールすると Google レポジトリが追加され」とある通り、/etc/yum.repos.d/google-chrome.repoができてる。
  4. その中にhttp://dl.google.com/linux/chrome/rpm/stable/x86_64がある
  5. x86_64部分は$basearch同等なので、これが最初のURLにつながる。

ブラウザの「戻る」で戻ったときに選択しているoption要素を戻す方法

select要素のonchangeで即ページ遷移するような実装をすることがたまにある。ボタン押して普通にsubmitさせろよとも思うけど、手順一つ省略したい気持ちもまあわかる。

$('select').on('change', function () { $(this).closest('form').submit() });

まあ、こんな感じに。

これ自体は問題ない。問題はこの後にブラウザの「戻る」で戻った場合で、ほとんどのブラウザの実装では、キャッシュがある限り、フォームコントロールはそのまま戻ることになる。

普通ならそれで問題はないのだが、select要素でonchangeでやってる場合ちょっとやっかいなことになる。なぜかというと、select要素をクリックして、メニューを開いた後、選択を変えずにメニューを閉じた場合、onchangeは発火しないから。

だからこのような使い方をする場合、HTML上のselected属性の通りに選択されていて欲しい。それをどう実現するか?

結論から言うと、window.onloadと、Firefoxなど向けにwindow.onshowpageに、HTML上のselectedをじっさいの選択に合わせる関数を登録すればいい。jQueryでやるならこんな感じ。

function init() {
  if ($('select option[selected=selected]').attr('selected')) {
    $('select').val($('select option[selected=selected]').val());
  }
  else {
    $('select option:first').prop('selected', 'selected');
  }
}

jQuery(function () {
    init();
    $(window).on('pageshow', init);
});

注意点がいくつかあって、

  1. :selected擬似セレクタではなく、[selected=selected]を使う。
  2. selected属性がどのoption要素にもない場合に、ブラウザっぽく最初のoption要素をselectedにするようにする。
  3. selectedにするのにはval(), attr()あたりではなくprop()を使う。

Android版Google日本語入力で、「○○は」「○○が」みたいな変換をしやすいように辞書登録する方法

奥さんの名前がGoogle日本語入力で登録されていない漢字のようなので、辞書登録して使っているのだが、カテゴリを「名」にしても「人名」にしても変換がどうもおかしく、

○○は
○○が
○○の
○○を

あたりをタイプしても、変換候補に出てこなかったり、出てきてもかなり後ろになって不便だった。

いろいろ試したところ、どうも「名詞」にするとうまく変換されるようだ。名詞に辿り着くまでに試したのは「名」「人名」のほか、「姓」「固有名詞」など。どれも適切に変換されてしかるべきだと思うのだが、なんでされないのやら。

LaravelやRailsでcollationをデフォルトのまま使ってしまった時は

utf8mb4_unicode_ciは「か」と「が」を同一視したりするので、日本語アプリケーションでは使えない。のだが、日本語対応が十分でないフレームワークなどではよくデフォルトになっている。

最初からちゃんと設定しておけばいいのだが、忘れたまましばらくしてから気付いてしまった場合は、修正が面倒だ。

MySQLでは、collationはデータベースのデフォルト、テーブルのデフォルト、カラムのデフォルトと3段階ある。そのうちデータベースのデフォルトについては多分フレームワーク側では関与していないので、今回は無視する。

テーブルとカラムのデフォルトは、以下のクエリで変更できる。

ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

-- あるいは、utf8mb4のデフォルトのcollationはutf8mb4_general_ciなので、これでも同じ
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4;

残念ながらMySQLではALTER TABLEを繰り返して実行することはできないので、データベース内のすべてのテーブルを一括で変更するには、シェルスクリプトなりで対応するしかない。zshならこんな感じとか。

for table in $(mysql DATABASE -BNe 'show tables')
mysql DATABASE -e "ALTER TABLE $table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci"

注意

ALTER TABLE ... CONVERT TO CHARACTER SET ...は、今回のようにCHARACTER SETを変更しないような場合はおそらく安全に使えるが、CHARACTER SETを変更する場合は文字列系のカラムのサイズが変更されてしまう場合がある。

データ型が VARCHAR か、またはいずれかの TEXT 型であるカラムに対して、CONVERT TO CHARACTER SET は、新しいカラムが確実に元のカラムと同じ数の文字を格納できる十分な長さになるように、必要に応じてデータ型を変更します。 https://dev.mysql.com/doc/refman/5.6/ja/alter-table.html

特にフレームワークでmigratorを使っているような場合致命的な問題が発生しかねないので気をつけた方がいいかもしれない。

plackup -Iで一貫性のないモジュール読み込みになる場合がある

plackup -Iは、perl -Iと同様にinclude pathを追加できるオプションなのだが、ちょっと特殊な挙動になっていて、問題が起きる場合がある。

plackup -Iでは、plackup自身の実行時に使用するモジュールのinclude pathは指定できない。これはまあ当然なのだが、なんとplackupの実行時に読み込まれたモジュールは、その後PSGIアプリケーションを実行する時点でも残ってしまっている。

これにより、「plackup自身が読み込んだモジュールは、-Iで指定されたパスにあっても読み込まれない」ということになる。

さらにモジュールによってはやっかいな問題につながる。

たとえば古いCarpモジュールではCarp::Heavyを遅延ロードしているのだが、plackup時に古いCarpを読み込んで、しかし-Iで指定したパスには新しいCarpが入っている場合、その後PSGIアプリケーション側でCarp::Heavyを遅延ロードするようなことをすると、新しいCarpCarp::Heavyは古いバージョンのCarpとは互換性がないためdieするようになっているため、アプリケーションが落ちる。

なお回避策は簡単で、-Iオプションを使用せず、PERL5LIB=... plackupとするだけである。-Iオプションはなくしてもいいのではないだろうか。