コード日進月歩

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

RailsのActiveRecordでは add_column するときに after を指定すると追加するカラム位置がコントロールできる

主にMySQL向け

環境

rails (5.0.2)

やり方

カラム追加の記述の場合にafterを指定する。

name というカラムのあとに profile_text というカラムを足したい場合

class AddColumnHogeHoge < ActiveRecord::Migration[5.0]
  def change
    add_column :users, :profile_text, :string, after: :name, default: "", null: false
  end
end

原理

以下メソッドに記述があるとおり、AFTER文を継ぎ足している。そのため、AFTER文の概念がないpostgresqlにはできない。

def add_column_position!(sql, options)
if options[:first]
  sql << " FIRST"
elsif options[:after]
  sql << " AFTER #{quote_column_name(options[:after])}"
end

from: rails/schema_creation.rb at 36a6d935d2994e776054797be3c00cd50c19b1e9 · rails/rails

参考リンク

色覚多様性(色覚特性)を鑑みた見え方をチェックするときに便利なスマホアプリ「色のシュミレータ」

便利だったのでメモ的に

公式サイト

色のシミュレータ

このアプリでできること

公式サイトに記載のある通り

1型(P型)、2型(D型)、3型(T型)の2色覚の色の見えをリアルタイムに確認し、一般型(C型)の色の見えと比較することができます。 - 色のシミュレータ

一般的な普通の人が感じると言われている「C型」と他の見え方と窓を分割して確認することができる・

補足:それぞれの型の意味

ざっくりとした説明でいくと以下の通り

型名 特徴
P型 赤色の光を感じる力がない、もしくは感じる力が弱く暗く感じる
D型 緑色の光を感じる力がない、もしくは感じる力が弱く暗く感じる
T型 青色の光を感じる力がない、もしくは感じる力が弱く暗く感じる
A型 3種類の光を感じる力のうち、2つがない、もしくは全てがないため、明暗でしか判断ができない

C型を除き、多いとされているのはP型とD型

参考リンク

MySQL5.6にてひらがなとカタカナを同一のものとして検索するためにcollationsを使うのはリスクが多いのでメリット・デメリットを把握する

あいまい検索を実装する際に安易に飛びつくとやけどする気がするのでまとめた。

環境

今回はMySQL5.6のドキュメントをベースにしているためそちらの前提で記載しています。

そもそもMySQLのcollationsとは

日本語で表現すると「照合順序」という言葉になり。MySQLのヘルプには以下のように書かれている。

照合順序とは、文字セット内の文字を比較するためのルールを集めたものです。(中略)また実際には、ほとんどの照合順序は、大文字と小文字の区別だけでなく、アクセント符号 (「アクセント符号」とはドイツ語の「Ö」に見られるような文字に付けられた符号です) を区別するかどうかに関するルールや、複数文字のマッピングのルール (2 つのドイツ語の照合順序の一方における「Ö」 = 「OE」というルールなど) など多くのルールを含んでいます。 - MySQL :: MySQL 5.6 リファレンスマニュアル :: 10.1.1 一般の文字セットおよび照合順序

ざっくりとして意味としては並び替えをするルールであり「文字の並び順」と「どの文字を同一とみなすか」を決めるルールの集まり。

Unicodeにおける照合順序

基本は文字コードと照合順序はセットなので、文字コードごとに照合順序は存在する。Unicode(utf8/utf8mb)の場合はバリエーションが色々あるが、今回取り上げるのは以下のもの

  • utf8_bin
  • utf8_general_ci(デフォルト)
  • utf8_unicode_ci

*_bin命名規則文字の比較は、文字バイナリコード値に従って行われます。 と定義されており、文字のバイナリコードが合うものを同列とし、そのバイナリコードの順番で並べる。

それと比較して、*_ci命名規則大文字と小文字を区別しない照合順序を示します。と定義されており、「a」と「A」を同列で扱うような挙動をする。

そのなかでも general_ciunicode_ci は挙動が違う。ヘルプでは以下のように記載されている。

Unicode 文字セットの場合、xxx_general_ci 照合順序を使用して実行する演算は、xxx_unicode_ci 照合順序のものよりも高速です。たとえば、utf8_general_ci 照合順序の比較は、utf8_unicode_ci の比較よりも高速ですが、精度は少し低くなります。この理由は、utf8_unicode_ci では、ある文字がほかの文字の組み合わせに等しいものと見なされる拡張形式などのマッピングをサポートしているためです。たとえば、ドイツ語とほかのいくつかの言語では、「ß」は「ss」と同じです。utf8_unicode_ci は、短縮形式と無視可能な文字もサポートします。utf8_general_ci は、拡張形式、短縮形式、無視可能な文字をサポートしない従来の照合順序です。文字間で 1 対 1 の比較しかできません。 - MySQL :: MySQL 5.6 リファレンスマニュアル :: 10.1.14.1 Unicode 文字セット

上記のように unicode_ci は同一視される言語を同じ単語とするようにみなしているが、general_ci のほうは単純な大文字と小文字を同列にみなす程度のサポートしかしていないというもの

5.5のものだが、同一視される文字の一覧を見ると、「8」と「⑧」や「ル」と「ル」同一のものとみなされるなどが例に出されている。

unicode_ciによって起きるははパパ問題

ここまでの話を切り取ると「よしなに同一視しても問題ないものは unicode_ci のほうがよさそう」というように見えるが、実際はそんなに都合のいいものではなく、日本語的にはあんまり同一視してほしくないものも同一視する。

たとえば以下のようなもの

  • 「は」と「パ」
  • 「⺝」と「⽉」
  • 「⻯」と「⿓」

物によっては上記のようなものを同一視しても問題ないケースがあるかもしれないが、「は」などに関してはあとあと問題になるケースが多いと思われる。(これを「はは=パパ」問題と呼称したりする)

では general_ci ではどうか、というと今度は寿司ビール問題が発生する。

general_ciにすると起きる寿司ビール問題

寿司ビール問題というのは俗称で、🍣と🍺が同一の文字とみなされてしまう問題。

事象の原因としてはかみぽさんの記事に和訳があるのでそれを引用させてもらうと以下の通り

BMP文字で general collation (xxx_general_ci) の場合、コードポイントを使う。
・SMP文字(絵文字とか)の場合、0xfffd REPLACEMENT CHARACTER と同じ weight になる- MySQL と寿司ビール問題 - かみぽわーる

ということで絵文字はすべて同一とみなされてしまう。(なお、REPLACEMENT CHARACTERに関してはこちらを参照のこと)

そのため昨今の絵文字が日常的に使われる場面では _bin の照合順序にするほうが良いケースが多い

余談:MySQL8では

MySQL8系ではこの問題をカバーした utf8mb4_ja_0900_as_cs が登場している。こちらに関してはははパパ問題も寿司ビール問題も解決しているし、aとAを同一のものと解釈もする。詳しくは下記ブログ参照のこと。

日々の覚書: MySQL 8.0.1でutf8mb4_ja_0900_as_csが導入された

関連リンク

バッファは基本全部使われてしまうという話と「パーキンソンの法則」の関連性についてまとめる

「バッファなんて作ったら結局全部使い切るんだよ」という話はあるがどういう考え方なのか、パーキンソンの法則というキーワードからのざっくりまとめ

出典

第1法則
仕事の量は、完成のために与えられた時間をすべて満たすまで膨張する
第2法則
支出の額は、収入の額に達するまで膨張する
- パーキンソンの法則 - Wikipedia

もともとの話

もともとは組織の拡大とともに人は増えるが、本質的な業務が増加するからではなく、組織が拡大するにつれてその組織内の調整のためのコストも膨れていくため、新しく投入した人員の分だけ拡大していくわけではない。何かを成すために投入され、ある程度余裕を見越して投入されているはずなのに様々な些末ごとで埋まっていく。

この話の元ネタは官僚組織において本質的な仕事よりも部下を増やすことやっきになるコストでどんどん時間が食いつぶされていく様を分析した話ということだった。

プロジェクトマネジメントへの転用

このパーキンソンの法則の第一法則の文章がプロジェクトマネジメントの工程と組み合わさり、以下のような解釈になった。

「決められた工程日数よりもたとえ早く終わったとしても、決められた工数日数を使ってから次の作業に入る」

これは『早期完了の未報告』と呼ばれる現象で文字通り「早く終わったけど終わったと報告せずに時間を使い切るまで報告しない」というような話につながっている。

(この解釈に関してはは書籍『Critical Chain』で語られている)

バッファを食いつぶす、という観点の整理

パーキンソンの法則というよりも「早期発見の未報告」という観点が強く、細分化されたタスクひとつひとつにバッファを積むと、自然と食いつぶしてしまうので、個別のタスクにバッファを積むべきではない、という話につながる。

参考リンク

Rubyにおける ! を二重にした !! の使い所

エクスクラメーションマークの重ねがけ、二重のビックリマークなど、読み方が難しいやつ

環境

$ ruby -v
ruby 2.6.6p146 (2020-03-31 revision 67876) [x86_64-linux]

効能

明確に truefalse にしたいシーンがあるときに ! をかけてtrueかfalseにしてからさらにもう一回 ! をかけると、明確にtrueかfalseか表現することができる

x = 1
puts !!x
true

そのため、オブジェクトの存在チェックをする場合は !! をすると有効

余談:真と偽になるパターンに関して

基本Rubyの世界では falsenil 以外は真で評価をされる

false は nil オブジェクトとともに偽を表し、その他の全てのオブジェクトは真です。 - class FalseClass (Ruby 2.7.0 リファレンスマニュアル)

そのため下記のようなif文は成立する

x = 1
puts 2 if x
2

x = nil
puts 2 if x
# 何も出ない

このようなことがあるため !!hoge を能動的に使いたくなる場面は、? をつけるようなクラスを提供する時が多いかと思われる

読み方

英語圏では ! を bangと読むことがあるらしく、double-bangと読む読み方があるとのこと。

参考リンク

Rails(ActiveSupport)の blank? は false も trueになる

Railsガイドにも乗ってますが、改めてコードを掘り下げて挙動を見る。

環境

$ bin/rails -v
Rails 6.0.3.1

挙動

a = true
a.blank?
#=> false

a = ""
a.blank?
# => true

a = false
a.blank?
# => true

ソースコードから読む

かなり明快

def blank?
  respond_to?(:empty?) ? !!empty? : !self
end

rails/blank.rb at master · rails/rails · GitHub

empty? を持つオブジェクトであれば empty? の結果を !! を用いて 完全にtureか、falseのどちらかに変換する。持っていない場合は自分自身にnot演算子をかけた結果を返す。

false である FalseClassempty? を持たない。

FalseClass.method_defined?(:empty?)
#=> false

そのため、結果は !false で trueになる。

参考リンク

2020年8月現在、Slack(フリー版を除く)には「スター付き(Stared)」と同じ欄を作る機能がある

会社で有料版使っているのにみんな意外と知らない section の機能のことを雑に書く

出典

カスタムセクションを使用してサイドバーを整理する | Slack

機能的な説明

Staredのメニューの中にsectionを作る項目があるのでそれを押すと下記のような画面が出てくる

f:id:shinkufencer:20200826203022p:plain
新しいセクションを作る画面

ヘルプに色々書いてあるんですが箇条書きで特徴を書くと以下の感じ。

  • 昔からある「スター付き(Stared)」と同列でグルーピングをするための「カスタムセクション」という枠が作れる
  • Staredもカスタムセクションと同列の存在なので含めて並べ替えることが可能
  • カスタムセクションにはemojiが設定でき、見出しとして使うことができる

f:id:shinkufencer:20200826203059p:plain
自分のステータスのemojiと似た形でセクションごとにemojiが設定できる

f:id:shinkufencer:20200826203145p:plain
並べるとこんな感じ

参考リンク