コード日進月歩

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

ActiveRecord::Type::Boolean.new.cast はかなり揺らいだ変換になるので気をつける

昔のPHPを彷彿とさせる変換だったので書き留める

環境

$ bin/rails --version
Rails 6.0.3.6

どういうことか

ActiveRecord::Type::Boolean.new.cast は引数をtrueあるいはfalseに変換してくれるのだが、変換の基準は以下のものに引っかかるものがfalseになる。

クラスとしてはこちらに定義がある。

FALSE_VALUES = [
  false, 0,
  "0", :"0",
  "f", :f,
  "F", :F,
  "false", :false,
  "FALSE", :FALSE,
  "off", :off,
  "OFF", :OFF,
].to_set.freeze

また、""nilnil になる

def cast_value(value)
  if value == ""
    nil
  else
    !FALSE_VALUES.include?(value)
  end
end

つまり以下のものはすべて false に変換される

  • false
  • 0
  • "0"
  • :0
  • "false"
  • :false
  • "FALSE"
  • :FALSE
  • "off"
  • :off
  • "OFF"
  • :OFF

また、 以下のものは nil になる

  • nil
  • ""

そしてそれ以外のものは true になる。

false になるシリーズは以下

target = "f"
ActiveRecord::Type::Boolean.new.cast(target)
# => false

target = 0
ActiveRecord::Type::Boolean.new.cast(target)
# => false

target = "false"
ActiveRecord::Type::Boolean.new.cast(target)
# => false

target = false
ActiveRecord::Type::Boolean.new.cast(target)
# => false

target = "FALSE"
ActiveRecord::Type::Boolean.new.cast(target)
# => false

target = "off"
ActiveRecord::Type::Boolean.new.cast(target)
# => false

target = :off
ActiveRecord::Type::Boolean.new.cast(target)
# => false

target = :false
ActiveRecord::Type::Boolean.new.cast(target)
# => false

target = :FALSE
ActiveRecord::Type::Boolean.new.cast(target)
# => false

target = 0
ActiveRecord::Type::Boolean.new.cast(target)
# => false

target = 1
ActiveRecord::Type::Boolean.new.cast(target)
# => true

ただし False は設定値にないので true になる

target = :False
ActiveRecord::Type::Boolean.new.cast(target)
# => true

target = "False"
ActiveRecord::Type::Boolean.new.cast(target)
# => true

そして空文字とnilnilになる

target = nil
ActiveRecord::Type::Boolean.new.cast(target)
# => nil

target = ""
ActiveRecord::Type::Boolean.new.cast(target)
# => nil

関連リンク

Rubyの生成されたインスタンスのクラスを調べるときはinstance_of?とkind_of?(is_a?)を使い分ける

エイリアスかと思ったら違うのでちゃんと記述する

環境

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

概要

生成されたインスタンスのクラスを調べたいときは instance_of? を使う。継承元のクラスも含めて調べたいときは kind_of? あるいは is_a? を使う。

実例

Exceptionクラスを継承しているStandardErrorクラスをベースに説明する。

error = StandardError.new
# => #<StandardError: StandardError>

継承関係まで見る kind_of?is_a? は継承元のExceptionでもtrueになるが、 instance_of? は生成したクラスのみにtrue反応をする

error.kind_of?(StandardError)
# => true
error.kind_of?(Exception)
# => true
error.is_a?(Exception)
# => true
error.instance_of?(Exception)
# => false
error.instance_of?(StandardError)
# => true

参考リンク

ActiveSupportにはモジュール名の一部やクラス名の部分だけを取り出すためのメソッドがある

モジュールの部分はいらないんだけどな…というときに文字列処理をしなくても用意してくれている。

環境

$ bin/rails -v
Rails 6.0.3.1

利用例

今回サンプルとして扱うのは以下のようなクラス

module Hoge
  module Piyo
    class Test
      def initialize(test: nil)
        @test = test
      end
    end
  end
end 

newするときは以下のようにする

::Hoge::Piyo::Test.new

クラス名だけを取り出したい場合

demodulize を使う。ただし Class オブジェクトでは使えないので、 to_s などをしてあげる必要がある。

object = ::Hoge::Piyo::Test.new
object.class.to_s.demodulize
# => "Test"

モジュール部分だけを取り出したい場合

deconstantize を使う。こちらも Class オブジェクトでは使えないので注意。

object = ::Hoge::Piyo::Test.new
object.class.to_s.deconstantize
# => "Hoge::Piyo"

参考リンク

[Rails5] Active Support::Inflectorの便利な活用形メソッド群|TechRacho(テックラッチョ)〜エンジニアの「?」を「!」に〜|BPS株式会社

テストダブルの種類をざっくりまとめる

自身の記憶整理の文脈でまとめる

出典

テストダブルについては書籍 xUnit Test Patterns にて取り上げられたテストに依存するコンポーネントを置き換えるためのパターンのこと。

Test Double at XUnitPatterns.com

なおダブルは2倍のほうの意味ではなく、「代役」や「替え玉」などの意味。

テストダブルのパターン

  • TestStub
  • TestSpy
  • MockObject
  • FakeObject

TestStub(テストスタブ)

テストスタブは「テスト対象の中で行われる外部要因の戻り値を偽装する」というような用途の内容になる。

クラス外のメソッドを実行してデータを行うような処理をもつクラスがある場合、その中のメソッドの戻り値をテストコード内を定義して、期待した動きを見るなどになる。

実際あるケースとしては「色々なAPIを叩いてデータを取得した結果を総合計する」等の場合にAPIからの戻り地をテストコードで定義して期待する結果を確認するなどのコードになると思われる。

TestSpy(テストスパイ)

テストスパイは「テスト対象の中で外部への実行の実行先をすり替えて、その実行メソッドの値が期待したものが返ってくるか」というような用途の内容になる。

実際にあるケースとしては「内容を集計して、ファイル書き出しなどをする」というような場合にファイル書き出しの部分をスパイとして置き換えて、実際に書き出される期待値がマッチするかを確かめる、というようなものになると思われる。

MockObject

モックオブジェクトは「予め期待値を設定し、テスト対象の中の外部への実行を見て、期待値担っているかを判断する」というような用途の内容になる。

テストスパイと似たような動きですが、違いとしてはテストスパイはテストの実行後に値を評価するのですが、モックは予め期待値をセットするので、その期待値どおりに動くかを見るという点に違いがあります。

FakeObject

フェイクオブジェクトはまま文字通り、「偽物」として本物と同様の動きをするためのものです。他のものとは異なり、あくまでも検証のための代用品であり、このオブジェクトそのものはテストをすることに使われるものではない。

関連リンク

CSSのロードが遅くてHTMLがちらつくFOUC(Flash of unstyled content)についてざっくりまとめる

日本語情報が無いのでざっくり書いてみる

出典元

Flash of unstyled content - Wikipedia

上記のWikipedia曰く

CSS @importルールを使用している一部のページでは、MS Internet ExplorerWindows版で、スタイル化されていないページのコンテンツが一瞬フラッシュするという奇妙な表示の奇妙な現象が発生します。私はこの現象を「スタイル化されていないコンテンツのフラッシュ(Flash of Unstyled Content)」、略して「FOUC」と呼んでいます。 - Flash of Unstyled Content (FOUC)

もともとはIEで発生する現象が期限で、そこからスタイルの影響のコンテンツのちらつきに関して「FOUC」と呼ぶようになった様子。

FOUCが起きるとき

FOUCの原因はケースバイケース、HTMLの記述の問題だったり、ブラウザの機能のせいだっったり、つかっているJSのライブラリのせいだったりさまざま。

確認ポイントとしては以下のようなものがある

関連リンク

伏せ字表現にはxxxではなく、アスタリスク(*)を使うとよさそう

xxxはスラングとしての意味合いが強いので他の用語を使おうという話

今回考えるケース

個人情報保護の観点で文字列を書き換える場合の話

例えば suzuki.hideo@example.com のようなメアドは個人情報になってしまうので、差し障りのないデータとして扱うときにドメイン部をどう表現するかというような話。

候補としては

  • xxx@example.com
  • ***@example.com

などがある。

TL;DR

  • xxxなどが使われることがあるが、これはキスを意味するスラングの地域もあるので避けるほうがいい
  • パスワードでも使われる * が万能
  • foobar などのメタ構文変数で表現するのも場合によってはあり

xxxは使わないほうがいい

おそらく「ぺけ」を表すバツマークからの発展でxを使うパターンが見られるが、xxxは英語圏スラングとしてあるので、意味としては不適当な場合があるので避けるのが良さそう。

参考:「xxx」とはどういう意味?SNSで使える英語の略語 [トラベル英会話] All About

困ったら *

アスタリスクは伏せ字としてはメジャーなものであり、対抗馬として挙げられるものが「●」「〓」「✗」などの全角文字が多い中半角で表現できるので*がよさそう。

ただし注釈でも使われる記号のため、注釈が多いものでは取り扱いには気をつけないと混同する恐れがある。

使い所によってはfoo,barなどのメタ構文変数でも良さそう

foobar などのメタ構文変数でも「何かが入る」ということは表現できるので、そちらを使うのも有効だと考えられる。ただしメタ構文変数と通じないとミスリードを招くので、ケースバイケース。

参考リンク

GoogleのSEOを鑑みたときにJavaScriptをどう使うべきかはガイドラインがある

SEOとか考えるとレンダリングちゃんとやらないと不利じゃないですか…みたいな話に対して、現状どうなっているのか調べてみた

出典

明確にGoogleがドキュメントを用意してくれている

JavaScript SEO の基本を理解する | Google 検索セントラル | Google Developers

サマリ

出典のリンクがかなりわかりやすく書かれているのでそこを呼んでもらえれば大体わかるのだが、あえてかくと以下の通り

  1. URLをクローラーが受け取るとrobots.txtを見て判断クローリング対象かを判断(URLがクローリングして問題なければHTMLを取得してhrefなどの他リンク際のURLをキューとして入れる)
  2. ページ内のrobotsメタタグ、ヘッダ情報を見て問題なければレンダリングを開始
  3. headless ChromiumJavascriptなどをレンダリングして、そのHTMLをindexに登録する

ということでJavascriptを登録する

Googlebot目線でレンダリングされるページの見方

Googlebotの互換性があるコードかを確認する方法もガイドがある。

検索関連の JavaScript の問題を解決する  |  Google 検索セントラル  |  Google Developers

こちらに記載があるが、実際Googlebotがレンダリングをした場合のチェックとしてモバイルフレンドリーテストが案内されている。これを使うとどのページでも実際にレンダリングされる結果を確認することができる。

モバイル フレンドリー テスト - Google Search Console

JavascriptでDOMを組み上げるタイプのサイトでも読み込み後のHTMLが表示されるので、公開されているサイトの場合はこちらで確認することで「意図したHTMLがクローリングされないのではないか?」などの杞憂を減らすことができそう

関連リンク