コード日進月歩

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

HTMLのaタグで別ウィンドウまたは別タブを開くtarget=“_blank”の記述をする際は合わせてrelの記述も確認する

いろいろなところで語られているのでまとめる

問題となるポイント

昔から別ウィンドウや別タブを開くときに書くHTMLは以下の通り

<a href="https://example.com" target="_blank">ここを押すと新しいウィンドウが開きます</a>

この target="_blank" だが、開かれたページ(上記で言うところの https://example.com から window.opener を使うとaタグを埋め込んだ側のページの情報が取得できるため、遷移元のサイトに関して処理を加えることができる。

解決策

openerを無効化するリンク種別情報をつける

aタグはその相手との関係性を rel を用いてリンク種別情報がつけられるタグです。そのためこの relnoopener をつけることで window.opener の設定を無効化することができます。

<a href="https://example.com" target="_blank" rel="noopener" >ここを押すと新しいウィンドウが開きます</a>

詳しい説明をMDNより引用すると以下の通り

これは信頼できないリンクを開く際、 Window.opener プロパティでリンク元の文書を変更できないようにするために特に役に立つリンク種別です。ただし、 Referer HTTP ヘッダーは(noreferrer を使用しない限り)提供します。 - リンク種別 - HTML: HyperText Markup Language | MDN

これは各ブラウザ側が対応するものとなっていますが、最新のブラウザは概ね対応をしています。

ただし古いブラウザでは対応できていないものではあるため、そこまで視野に入ったWebアプリケーションの場合はどうすればいいかというときに出てくるのが noreferrer です

noreferrerをつけてリファラー情報をすべて渡さない

noreferrerの意味は以下の通り

別のページへ移動する際にリンク元ページのアドレスなどの値を、ブラウザーReferer: HTTP ヘッダーでリファラーとして送信しないようにします。 - リンク種別 - HTML: HyperText Markup Language | MDN

こちらは全般的に元ページの情報を渡さないため、前述の noopener 相当の効力を持つことができます。また noreferrer のほうがブラウザのバージョンのカバー率が高いので特にリファラなどを渡さないことに問題ない場合はこちらを使ったほうが良い。

どちらを書くと良さそうか

情報を統合すると

  • リファラ情報などが喪失すると問題がある場合は noopener
  • リファラ情報が遷移先ページで喪失しても問題がない、それよりも多くのブラウザバージョンをカバーしたい場合は noreferrer

という形になると思われる。

余談:主要ブラウザの動き

ChromeFirefoxもrel属性が未指定の場合は noopener 相当の挙動をするのがデフォルトになっているのが昨今の動向なので、この点を意識しなくても問題なくなりつつあるが、認識をしておかないと痛い目を見ることがありそうなので明示的に書いておいたほうがよさそうである。

「Firefox 79」からtarget=“_blank”なリンクの挙動が変更、より安全な仕様に - 窓の杜

参考リンク

Railsのfind***by系のメソッドを軽くまとめる

以下のツイートが気になったの調べた。

環境

$ bin/rails -v
Rails 6.0.3.1

一覧

メソッド名 説明
find_or_create_by 対象を検索して、ない場合はCREATE(INSERT文の発行)をする
find_or_initialize_by 対象を検索して、ない場合はオブジェクトを作成(.new相当)をする
create_or_find_by 新規作成を試みて、 ActiveRecord::RecordNotUnique の場合は既にあるのでfindをする

find_orcreateinitialize の違い

実装を見てもらってもわかりやすい話だが、実際にcreateまで実行してしまうか、オブジェクト生成のみ留めるかの違い。

def find_or_create_by(attributes, &block)
  find_by(attributes) || create(attributes, &block)
end

def find_or_create_by!(attributes, &block)
  find_by(attributes) || create!(attributes, &block)
end

create_or_find_by について

このメソッドに関しては実態のソースに以下のようなコメントがある

1つまたは複数の列に一意の制約を持つテーブル内に、指定された属性を持つレコードを作成しようとします。これらの属性を持つ行が既に存在する場合は のような一意の制約がある場合、そのような挿入が通常発生するであろう例外が捕捉され、それらの属性を持つ既存のレコードがfind_byを使用して発見されます。

これはfind_or_create_byに似ていますが、SELECTとINSERTの間の古い読み込みの問題を回避します。

しかし、create_or_find_byにはいくつかの欠点があります。

  • 基底となるテーブルは、一意の制約で関連する列を定義していなければなりません。
  • 一意な制約違反は、与えられた属性のうち1つだけ、または少なくともすべての属性よりも少ない属性によってトリガされる可能性があります。これは,後続のfind_byが一致するレコードの検索に失敗する可能性があることを意味し,与えられた属性を持つレコードではなく,ActiveRecord::RecordNotFoundの例外を発生させます.
  • find_or_create_byからSELECT -> INSERTの間の競合状態を回避していますが、実際にはINSERT -> SELECTの間に別の競合状態があり、これら2つのステートメントの間のDELETEが別のクライアントによって実行された場合にトリガーされます。しかし、ほとんどのアプリケーションでは、これはヒットする可能性がかなり低い条件です。
  • このメソッドは、制御フローを処理するために例外処理に依存しており、多少遅くなるかもしれません。

このメソッドは、すべての与えられた属性が一意の制約によってカバーされている場合(INSERT -> DELETE -> SELECTの競合条件がトリガされない限り)、レコードを返しますが、作成が試みられ、検証エラーのために失敗した場合、それは永続化されません、あなたはそのような状況でcreateが返すものを取得します。

https://github.com/rails/rails/blob/bca6f7f57693dc4244870f7bd7f37a4f5cbf1976/activerecord/lib/active_record/relation.rb#L178

というように、既存レコードが存在することが設定された値からユニーク成約で発覚するケースにおいては利用することができる。

参考リンク

『銀座Rails #26』をみたよメモ

【オンライン開催】銀座Rails#26@リンクアンドモチベーション - connpass をZoomで視聴したのでそのメモ

各発表の感想

※資料スライドは見つけたら貼ります。


大量データでもサクサク動くRailsになるために

スライドはなさそうなので、発表のメモだけ

発表メモ

SaaSのプロダクトが大企業にも注目され大手顧客対応としてパフォーマンス向上が課題になってきており、そこに関しての取り組みに関しての体験談のお話。

ActiveRecordのValidation問題

validationで他のモデルを参照していると一気に更新処理をかける場合、1件ごとに確認がかかるのでN+1がかかる。 この場合は、一気に処理できるような記述に切り替えると良い。

callback関数の問題

dependnet: destory などがあると一個ずつdeleteがかかるので重くなる。 こちらも、一括で処理できるような処理をする。

ActiveRecordのオブジェクトがでかい問題

何も指定しないと該当レコードのすべてのカラムを撮ってきてしまう。そのためメモリを逼迫してしまう。

selectでカラム名を指定することで参照する時間を減らしたり、pluckでarrayにすることで早くすることができる。

n+1問題

関連レコードをn+1で取得してしまうことがあるので、includeなどを使う。

あぶり出すときにはbulletなどを活用する。ただし鵜呑みにしすぎるとよくないので参考程度にするといい。

DBへのindex問題

リリース重視で開発すると、indexを使わない状態になりがち。

見つけ方としては

  1. slow.logをみる
  2. EXPLAINで検証しつつ、適切なindexをつくる

その他問題になった箇所の問題

  • 仕様を変える、設計をかえる

パフォーマンス改善でやっていて感じること

コードだけで解決できる問題は少ない。DB設計を変更しないといけないケースが3割。

感想

  • 約9ヶ月かけてすごいパフォーマンス改善をした地道なレベルの話
  • activerecord-importにvalidationがあったとは知らなかった…ので勉強になった。

関連リンク


これからの Ruby と今の Ruby について

感想

  • Ruby3.0の新しい機能のひとくち紹介的なスライド
  • 型定義とかどういう風になっていくのかすごく楽しみになった
  • 新しい機能を見ていくと、Rubyのカッコ省略を空スペースで表現できるのがかなり混乱の種だな…と思った。

関連リンク


タイトル

感想

  • DDDのコアドメインに関する話とそれを基軸にRailsでどういう改善活動をしたかのお話
  • ドメイン駆動設計」の「(コア)ドメイン」に重きがおかれており、ドメインってURLの前の部分でしょ?みたいな認識度合いの人に読んでもらうには良さそうな形の内容でした。
  • ここから発展して「MVCのModelとドメインモデルというのは切り口が違う」とか「ドメインが重要なのはわかったけどなんで密結合だと駄目なの?」とか「ドメインの処理とActiveRecord一緒にしちゃ駄目なの?」とかを整理してしゃべれるといいのかもしれない。
  • 疎にするということはコードが増える、コードが増えるということは動作を保証するための作業も増える、その際にRubyはテストコード頼りだが、静的型付けは型でもカバーしてくれる。そういうところが疎に切り離す壁になっている部分は多いなと感じる。
  • 作中で話が上がっていたが「ユースケース」という形に着目してRailsに乗ってみる開発に関してはしたことがあるので、業務の話がでない体験談レベルで切り出してアウトプットしてみたくなりました。

関連リンク


全体を通しての感想

  • DDDの話とRuby3の新しい機能というRailsの直球なお話というよりも取り巻く内容の話が濃い回でした。
    • Ruby3の型が登場する話と、静的型付けじゃない言語は不得手という話が出てきて、地味なコラボレーションがある回でもあるきがしました
  • 自分自身もDDD+Railsには色々思うところがあり、実践できる場面では実践してきたしまだまだ学びが足りない部分もあるので補強してブログなりにしたためていきたいと思いました。
  • 家事の合間に聞けるのですごいありがたいリモート開催。最近懇親会参加できないのを悔やみまくってますが、リアルでできるようになっても中継があると嬉しいなと思います。。

関連リンク

混乱した代理(使節)問題をざっくりまとめる

普通に日本語情報がないし、大体AWSの話になるので噛み砕いて書く。

元ネタ

1988年の論文 The Confused Deputy: (or why capabilities might have been invented) より

考え方

登場人物は大きく3人

  • クライアント
  • 代理(Deputy/使節)サービス
  • 機能提供者

クライアントは機能提供者に直截依頼をするのではなく、代理に関して依頼を行う。

f:id:shinkufencer:20201023224922p:plain
代理の使われ方

この作りの場合、クライアントは代理サービスを介して、機能提供者の機能を利用する。機能提供者はクライアントのことは知らず、機能提供者は代理サービスしか知らない。

そのため、不正な相手が代理サービスを騙して、正当なクライアントを装って機能を使う、不正な相手であるかというのは機能提供者はわからないため使わせてしまう。

f:id:shinkufencer:20201023224956p:plain
悪意のある人が不正に使った場合

このこのように不正な相手が代理サービスを仲介して本来使うことができない機能を使えることを 「混乱した代理問題」 という。

対策方法

この問題は正当なクライアントを装うことが問題なので、それを防ぐことが肝になる。ただし一概にこうすればいいという解決策はあるわけではなく、代理とクライアントの関係性を見て考える必要がある。

AWSのAssumeRoleではこの問題に関して、クライアント側にIDを降り出して、そのIDをアクセス時に合わせて送ってもらうことで正当な利用者かどうかを判断している。

参考リンク

マイクロサービスアーキテクチャ

マイクロサービスアーキテクチャ

  • 作者:Sam Newman
  • 発売日: 2016/02/26
  • メディア: 単行本(ソフトカバー)

リチャードソン成熟度モデルに関してざっくり調べる

書籍マイクロサービスアーキテクチャに出てくるワード。

出典

ベースの出典は以下

JWTUMOIM: Act 3

マーティンファウラー氏のブログにまとめ記事がある。

Richardson Maturity Model

どういうものか

WebAPIに関してRESTfulな形になっているかの判断を行うためのモデルです。

レベル0

レベル0はひとつのURLで、ひとつのHTTPメソッドを使ってアクセスをする。中身はXMLなどで送ってXMLの中身で内容を判断するような形です。

レベル1

レベル1は複数のURL、ひとつのHTTPメソッドのイメージ。URLによって処理がわかれるが、メソッドは変わらない、というかたちです。

レベル2

レベル2は複数のURLで、複数のHTTPメソッドを使う形のつくりです。現状でよく語られるRESTの形で、書くHTTPメソッドを使い分けて表現する形になりあす。

レベル3

通常のAPIはレベル2が一般的だが、ここで定義するレベル3はハイパーメディアであるということ。レベル2までの通常のRESTだと、次に取得すべき情報などは含まれていないが、ハイパーメディアなAPIでは次に越族すべき情報などが含まれる。

参考リンク

マイクロサービスアーキテクチャ

マイクロサービスアーキテクチャ

  • 作者:Sam Newman
  • 発売日: 2016/02/26
  • メディア: 単行本(ソフトカバー)

『Kaigi on Rails』をみたよメモ

Kaigi on Rails はリモート開催でしたので、それの見ましたよメモです。

各発表の感想

※資料スライドは見つけたら貼ります。

Viewがレンダリングされるまでの技術とその理解

動画をどうぞ

発表メモ

  • Railsがリクエストを受けてから結果を返すまでをパートごとに分けて、わかりやすいコードを添えながら説明してもらった。内容は以下。
    • Request
    • WebServer
    • Rack
    • Middleware
    • Router
    • Controller
    • View
  • Rackはどんなことをしているか、Routeはどういう動き方をしているか、ControllerはViewのrenderにどうやってつなげているのか

感想

  • なんとなく理解しているを改めてリクエストの流れをおうことでキレイな理解ができた。
  • bin/rails r 'File.binwrite "out.html", {{アプリケーション名}}::Application.routes.router.visualizer' で画像で見ることができるので、機能があるのは知らなかったのでぜひとも仕事でつかっているアプリでつかってみたい

関連リンク


Railsパフォーマンス・チューニング入門

感想

  • DBを中心にパフォーマンスでネックになるところを解説した話。
  • MySQLの気持ちになって考えてみよう」という考え方はシンプルに考えやすくてよかった
  • この手の話は大体N+1や発行クエリが増えまくる話が多かったけど、正しいindexを作ろうという(当たり前なんだけど)新しい切り口だった

関連リンク


FactoryBot the right way

感想

  • 何も考えずにcreateしてたけど、言われてみればbuildでいいじゃないかということを普通に思わされた話。
  • build_stubbedevaluator での数の制御 は初見の情報だったので今後有効活用していきたい

関連リンク


Rails 6.1's ActiveModel#errors Changes

感想

  • Rails6.1からerrorsの中身が変わるよ!という話でした。
  • いままで独自validationの結果をmessagesに直截足したりするバリデータ作ってたりするのでそこらへんが大変になりそうな変更だった。
  • 地味につらさがある変化なので来たるべきときに備えて対応できるようにしておきたい

関連リンク


Railsワンマン運転の手引き

speakerdeck.com

ざっくり発表内容メモ

  • Railsはサービスではない、そのためサービスとして成立させるためにはどういう要素が必要か?というのをRailsにちなんで鉄道にまつわる要素で説明
  • サーバを電車、駅はロードバランサー、駅名(駅看板)を(DNSのほうの)ドメインとして例えた

感想

  • 初学者向けの内容ではあったが導入やたとえ話の構成がいい感じになっており、とても楽しく聞けた。
  • Railsのコードを書く、というような分業スタイルの人は見えないところなのかなと思うので俯瞰的な視点で考える力を持つことは大切だよなとしみじみ
  • 車掌さんの帽子をかぶったりとリアル会場でなかったのが惜しまれるネタ仕込みだった

関連リンク

Railsはおまかせ(Rails is omakase翻訳) | blog.tai2.net - Rails周りのたとえ話といえばこちらも


継承とメタプログラミング満載なアプリケーションコードでもアクションとフィルタに悩まないためのGemを作った話

感想

  • 継承されまくっているControllerのCallback類を把握するためのgemを作った際に得られた知見の話で、午後の昼後だったのもあり一発では理解するのが難しい話だった。が、とてもcallback実装の丁寧な説明だったので、読み直したい話でした。
  • 地獄のような状況を打破するために自らでgemをつくるというのはよい話だし、業務だったりしたのかな…とか思った。

関連リンク


Action Mailbox in Action

感想

  • 注意を払う必要がすごくあるSMTPの話とActionMailboxの話。
  • 昨今メールサーバーを建てるようなシーンもないし、SaaSのほうがちゃんとやってくれるのでそこに乗っかるべきだなと切に感じた。
  • しかしActionMailbox使うようなシーンって一体…

関連リンク


コードレビュー100本ノックで学んだRailsリファクタリング

スライドは見つけたら貼ります

発表メモ

  • コードレビューを通して得た知見に関しての話、トピックごとに説明があった
    • 命名
    • クエリ
    • 不安定テスト・スローテスト
    • コミットへの意識

感想

  • sleep使うな、findつかえ、というのは心に刻みたい
  • コミットメッセージには理由を添えるというのは案外やってくれないんですよね…と思うのでこうやって定着化しているところはすごいいいなと思っている
  • このあとのkoicさんの話にも繋がりますが、独立した変更単位のコミットを作るというのは大変大事だなと思った
  • ただRailsの場合、Model+Controller+Viewでコミットつくるともりもりになるので、そのもりもり具合でやるのがいいのか悪いのかなどの見解を知りたい感じではあった

関連リンク


育てるSinatra

動画は以下

発表メモ

  • SinatraをベースにRailsライクなものを実装することでRailsを理解する
  • ModelなどはActiveRecordを使うが、Railsがデフォルトでやってくれている設定なども自前で作る必要がある。
  • RailtieというRails本体とも言えるようなものが存在する

感想

  • Sinatra自体存在は知っているが、全然触れたことがなかったので、SinatraのシンプルさとRailsが色々やってくれているというのを改めて感じる話。
  • スライドが再度見れるようになったら見直したい話。

関連リンク


ミドルウェアActionDispatch::HostAuthorizationと学ぶDNSのしくみ

感想

  • ESM第2の刺客、DNSの基礎的な説明からそれを悪用した話、そしてRailsがどうやって防ぐ機構を設けているかという話
  • このスライドで大体理解できる + トラブルシュート集もついていて他の人への情報共有力が高い発表でした。
  • 内容ももちろんですが、スライドのビジュアルも素敵でした。イラストは手書きなんだろうけど、丸の囲みとかも手書きなんだろうか…

関連リンク


Rubyで書かれたソースコードを読む技術

感想

  • Railsにおいてソースコードを読み解いていくテクニックを語るスライド
  • 便利なソース検知 source_location をはじめ、 puts caller で呼び出し元を探る、 gemに動作確認コードを入れていき、戻すときは bundle pristine などの豆知識満載だった

関連リンク


ActiveRecordの歩み方

感想

  • ActiveRecordRubyだから読める!という話でActiveRecordの読み方の話。
  • かなり読むのに根気がいるのがActionRecordなのでライブリーディングもその辛さが出てました。
  • 迷子になるので迷子にならないように目標をもつのが大事そう

関連リンク


Ruby 3.0におけるドキュメンテーションと端末制御の未来

スライドなどではなかったので発表メモだけ… 動画は以下

発表メモ

  • RubyAPIを調べる方法は用意されているが、Googleで調べる利便性には負けるので、そこに対してirb側にドキュメント閲覧できる機能をirbの実装見直しに合わせて組み込んでいる話
  • 上記の話に合わせて豊かな自然の映像とエモい話が要所要所に挟まる。

感想

  • 話のネタ映像が凝り過ぎてて内容が素通りする発表でした。
  • irbとpry、RDocとYARDの関係性に関して手堅くやるべきものと先進的なものとの切り分けをしているという話はなるほどなという感じだった。
  • とにかくビデオプレゼンという形を最大限に利用したプレゼンだった…岸壁登ったり沢下りの映像と技術の話を交えて最後に深い話で閉めるのは印象の強さがすごかった

関連リンク


ひみつきちを作りたい 〜「こどもれっどまいん」テーマ作りでの学び

感想

  • 子供向けのものを作りたい、という形からメッセージカスタムプラグインを作り上げた話
  • i18nを子供向け言葉の変換に使うという発想はなかった
  • フォントの力は本当にあるよなーと思いつつ聞いてました。

関連リンク


快適なリモートワークを実現するために〜RailsでSSOを実現する3パターン

感想

  • 社内ツールのセキュリティ封じ込めアイデア「IP制限」がリモート時代で使えなくなってきたのでそこをどうカバーするかという話
  • 社内的なツールのアカウント管理って会社組織やサービスの拡大に伴って絶対ぶつかる壁なので、この知見はすごく活きる発表だった

関連リンク


TDD with git. Long live engineering.

感想

  • TDDの考え方、GitHub登場前後の状況などの歴史を含めてどういう形でGitHubのPRやコミットはあるべきかという話。
  • 「誰のためのコード?個人のためのコードではなくチームのためのコードだよね」という旨の話は感銘を受けた
  • rebaseとかsquashをちゃんと使いこなせてないので、これを期につかってみたいなと思った。

関連リンク


Sidekiq to Kafka 〜ストリームベースのmicroservices〜

感想

  • ActiveJobの特性から、非同期処理からKafka基盤の利用につながる話
  • Railsでつくったものをいかに置き換えていくかという部分でも知見あるし、ストリームイベントに対しての戦い方みたいな意味でも聴き応えのある話でした。

関連リンク


Coming Soon... 💎

発表メモ

  • OSSをやりたいというが、そのやるに至らないのは技術力不足ではなくきっかけではないかというところからのお話
  • 直したいコードがあったときにすぐ動けるようにするのが大事、そのためにgem-srcなどを準備しておく
  • gemとRailsPluginの違いに関しても当時の状況を交えて説明
  • その後は松田さんが作っているRailsまわりのgemに関してのお話

感想

  • 松田さんの作ってきたものの話といままでの歴史を交えたようなお話。
  • kaminariが出来上がった話はいろいろなところで聞くことはありますが、作者の想像以上に使われたというお話は初めて聞いた感じでした。
  • 「手触り」というのを普通のRubyモジュールを素直に使い、特殊な基底クラスを継承しないなど言語化されていてこの点参考にしようと思った

関連リンク


全体を通しての感想

  • Railsの技術的な取り組み寄りの話多い感じでした。
  • トップバッターのアーロンさんの話が中盤のRackを踏まえた話の前段として機能したり、ソースコードリーディング系の話から最後のOSS貢献の話へつながったりと、かぶっている部分が多少ありながらも
  • 今回リモートということで、Liveでやるひとはもちろん、当日予定があるから録画で対応してくる人、映像交えてやりたいからビデオを出してくる人など色々なものがあってとてもバラエティに富んでいてよかった。
  • スポンサー表示の仕組みなどはすごい旨味あるなーと思いながらみてました。
  • リアルとは違うトラブルなどもあって大変そうでしたが、リアル現場にいけない生活環境の人たちにはすごい良いカンファレンスでした(懇親会とかもいきたかった…)運営の皆様お疲れさまでした!

他の方の感想ブログなど

Railsの raw は <%== と同じ

小ネタ

そもそもrawとは

通常、erbにて変数出力をするときは以下のような構文を用いる

<%= @hoge_var %>

この @hoge_var にHTMLが含まれる場合はRails側でよしなにエスケープ処理がかかり、文字列として表現されるようになる。

ただし、ただのまま変数の文字列をHTMLとして解釈してほしい場合もあるので、その場合はrawを使う

<%= raw @hoge_var %>

rawと同義の記号

Railsガイドに以下のように記述がある通り <%== と同義

rawと同等の<%==を使います。 - Active Support コア拡張機能 - Railsガイド

html_safeではなくraw

似たようなものとしてhtml_safeを使うのがいいかもしれないと思う場面がありますが、内部実装としてはhtml_safeを使っているrawを使ったほうがいい

def raw(stringish)
  stringish.to_s.html_safe
end

関連リンク