fv17の日記

Webエンジニアの備忘用ブログです。主にWeb界隈の技術に関して書いています。

ゼロから学ぶ正規表現

文字列の検索や置換を行うための技術、ミニ言語的な立ち位置としての正規表現を学ぶ。

アプリにおけるユーザーの入力制御、クローラーを使ったWebスクレイピングでの情報抽出、開発途中におけるテストデータの一括修正など、利用場面が多い。エンジニア1~3年目までには身につけておきたい技術。

元同僚に、エンジニアで正規表現できない奴は終わってると公言している方が複数名いて、一時危機感すごかった思い出。まぁ必要になれば学べばいいじゃない。(必要になった時には学ぶ時間がないという罠)

正規表現を学ぶ意味、メリットは何か?

下記の記事参照。

codezine.jp

正規表現とは何か?

まずはハンズオンでそもそもどんなものかを知る。

qiita.com

演習問題で身につける

一通り理解したらあとは復習と演習で身につける。

正規表現パズル

ゲーム感覚で学びたい場合は Regex Crossword

regexcrossword.com

私は「実際の利用場面と掛け離れすぎている」と感じてしまい、「正規表現パズル」の方が取り組みやすかった。

あなたの正規表現のスキルレベルをチェックする

ある程度できるなとなったら、こういう問題でチェック。

language-and-engineering.hatenablog.jp

正規表現の内部を知る

そもそもどういう原理で動いているのか等、技術的背景を詳細に知りたい場合は下記の書籍が詳しいらしい。(私は未読)

正規表現技術入門 ――最新エンジン実装と理論的背景 (WEB+DB PRESS plus)

RubyMine - No Ruby interpreter configured for the projectの解決方法

稀にエラーとなり、外部ライブラリが見えなくなる。

解決方法

  • RubyMineを閉じる
  • .idea/ フォルダーを削除する
  • 再度RubyMineで該当のプロジェクトを開く

git管理している場合の .idea/ 削除方法

git statusでUntracked filesに

.idea/

と出てきたら下記コマンドで削除できる

git clean -fd .idea/

N+1問題とは

N+1問題とは、必要以上にSQLクエリが発行され、その結果、速度低下に繋がりユーザビリティが悪くなる問題のこと。
N+1問題とか名前しらなかっただけで当たり前。

具体的には?

下記の記事を参照。
ruby-rails.hatenadiary.com

もしくは、Rails ガイドの「13 関連付けを一括読み込みする」に「N + 1クエリ問題」とズバリ。
railsguides.jp


どう解決するか?

includes、eager_load、preloadを使い

  • SQLの発行数を必要最低限に抑える
  • 取得したデータをキャッシュしておき、必要に応じて取り出す

下記の記事を参照。

qiita.com

英語が読める場合はこちらの方が具体例が多くて分かりやすい

blog.arkency.com

inner joinでeager loadingしたいはどうすれば?

ズバリの記事があった。
qiita.com

N+1問題にどう気づくか?

  • 実行時にコンソールのログに似たようなSQLが複数回発行されていたら要注意
  • Bullet gemを入れる (使いづらく感じるので微妙...)

なぜ何回もSQLを発行すると速度低下に繋がるのか?

こちらの書籍が詳しい。

SQL実践入門 ──高速でわかりやすいクエリの書き方
https://www.amazon.co.jp/dp/B07JHRL1D3/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

SQLが発行される時に内部で何が行われているかを説明してくれる。ただし、基本的なSQLを生で書けるレベルでないと読むのが難しいかも。

N+1を放置するとどれくらい遅くなるのか?

サンプルプログラムだとデータ数が数百かつ関連も少ないため、正直遅くないし、問題だと思わない。

しかし、本番プログラム、本番データになると数万、数十万とかの話になってくるので、性能の悪いPCやスマホだとカクカクして動かなくなる

マジでそんな遅くなるの?という場合は、ピクスタさんの記事
texta.pixta.jp

【パーシャル】:collectionオプションによる複数オブジェクトのレンダリング

パーシャルにオブジェクトの複数形を渡し、見やすいコードにする

基本の使い方

collectionオプションにより、コレクションのメンバごとにパーシャルをレンダリングする

<%= render partial: "product", collection: @products %>

具体的な使い方

Before Refactor

<ul>
  <% @users.each do |user| %>
    <li>
      <%= link_to user.name, user %>
    </li>
  <% end %>
</ul>

After Refactor

<ul>
  <%= render partial: "user", collection: @users %>
</ul>

_user.html.erb

<li>
  <%= link_to user.name, user %>
</li>

Further refactor (さらにリファクタリング)

<ul>
  <%= render @users %>
</ul>

_user.html.erbには変更なし。

上記のように書くと、

  • Railsは @users をUserのオブジェクトであると認識
  • @users のメンバであるそれぞれの user オブジェクトを _user.html.erb に出力
  • パーシャル側では user 変数で user オブジェクトを参照できる

パーシャルにおいて、ローカル変数の名称を変更したい

パーシャル側で :collection オプションで渡されたオブジェクトに好きな名称を付けたい場合は :as オプション を使う

<ul>
  <%= render partial: "user", collection: @users, as: :owner %>
</ul>

上記により、パーシャルにおいて変数 owner で user オブジェクトを扱えるようになる。

_user.html.erb

<li>
  <%= link_to owner.name, owner %>
</li>

Ruby - if文を一行にまとめる技

ある値がnilかどうかでif文を分岐させる場合、引数で || 記法が使えないかを検討する

if文で分岐させる書き方

def redirect_back_to(default)
  if session[:forwarding_url].nil?
    redirect_to default
  else
    redirect_to session[:forwarding_url]
    session.delete(:forwarding_url)
  end
end

|| を使うことで動的に引数を指定する書き方

def redirect_back_to(default)
  redirect_to(session[:forwarding_url] || default)
  session.delete(:forwarding_url)
end

Rails - delegateはなぜ必要なのか

delegateの基本的な使い方

基本的な使い方は公式ドキュメントか、日本語の場合はググればいっぱい出てきます。
https://api.rubyonrails.org/classes/Module.html#method-i-delegate

なぜ必要か?

オブジェクト指向の「デメテルの法則」(最小知識の原則)に反している書き方を正すため。

Wikipediaの「オブジェクト指向における適用」に理由が記載されている。
デメテルの法則 - Wikipedia

もっと深く知りたい場合は書籍

StackOverflowを漁ったところ、詳細に知りたい場合は「Practical Object-Oriented Design in Ruby」のChapter 4を読めばいいよ!と提案されていた。

日本語版出ている「オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方」
https://www.amazon.co.jp/dp/477418361X/ref=sr_1_1?s=books&ie=UTF8&qid=1541035982&sr=1-1

参考にした記事

qiita.com

stackoverflow.com

Tips

デメテルの法則」のデルメルは、あるプロジェクトの名前に由来し、さらに元を辿ると農業の女神デーメーテールに由来する。古典ギリシア語で「母なる大地」を意味する。なんだか凄い名前。