Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ErrorBoundaryを導入して 画面全体がエラーになることを防ぐ

Avatar for nakano-shingo nakano-shingo
June 17, 2024
66

ErrorBoundaryを導入して 画面全体がエラーになることを防ぐ

Avatar for nakano-shingo

nakano-shingo

June 17, 2024
Tweet

Transcript

  1. 名前
 中野 伸吾
 役割
 WEBアプリ開発エンジニア
 住まい
 東京都
 直近の経 歴
 受託開発PHPエンジニア

    → Webメディア開発エジニア(Rails)
 去年の8月にAsobica入社
 自己紹介
 Profile 
 家族
 妻、猫2匹

  2. 導入に至った経緯 本来のGitFlow 14 master develop hotfix的な対応 feature1 (nilチェック対応) feature2 (feature1で対応した

    同一ファイルの追加) release 今回やってしまった対応 急ぎリリースしたい事情で feature2のcommitを cherry-pickしてしまった
  3. 導入に至った経緯(developブランチの状態) 15 <% if flag.enabled? && @current_user.present? %> <%= @current_user.url_name

    %>', <%= @current_user.name %>' // 追加された行 <% end %> ※ エラーにならない
  4. 導入に至った経緯(masterブランチの状態) 16 <% if flag.enabled? %> <%= @current_user&.url_name %>', <%=

    @current_user.name %>' // 追加された行 <% end %> ※ エラーになる(current_user.present?がない)
  5. 参考:Null Objectデザインパターンについて 20 参考:https://zenn.dev/ytnk531/articles/4719dd13bab3ff class License Nothing = NullLicense.new end

    class NullLicense def name '免許なし' end end class Customer def initialize(license=nil) @license = license end def license @license || License::Nothing end end driving_license = License.new('運転免許') customer1 = Customer.new(driving_license) customer2 = Customer.new puts customer1.license.name # => 運転免許 puts customer2.license.name # => 免許なし
  6. 参考:Null Objectデザインパターンについて(別パターン) 21 class LogoutUser < UserInterface def name nil

    end end class LoginUser < UserInterface def name db_user.name end end # application_controller def current_user @auth.login? ? LoginUser : LogoutUser end
  7. 導入例(ヘルパー) 23 # app/helpers/application_helper.rb module ApplicationHelper def error_boundary content =

    capture { yield } raw content rescue => exception # 適宜エラートラッキングツールに通知するなり、ログを吐くなりする Rails.logger.error exception # 最後に評価したものが画面に出力されないようにnilを返す nil end end
  8. 導入例(erb) 24 <!DOCTYPE html> <html> <head> <%= csrf_meta_tags %> <%=

    javascript_pack_tag "application", "data-turbolinks-track": "reload" %> <%= stylesheet_pack_tag "application", media: "all", "data-turbolinks-track": "reload" %> <%= error_boundary do %> <% if @current_user.present? %> <%= render 'shared/custom_script' %> <% end %> <% end %> </head>
  9. 導入例(RSpec) 25 describe "#error_boundary" do context "エラーが発生しない場合" do it "ブロック内のコンテンツをキャプチャして返す"

    do result = helper.error_boundary { "test text" } expect(result).to eq "test text" end it "HTMLコンテンツを正しくレンダリングする" do result = helper.error_boundary { "<div>test html</div>".html_safe } expect(result).to eq "<div>test html</div>" end end ~中略~
  10. 導入例(RSpec) 26 ~中略~ context "エラーが発生した場合" do before { allow(Asobica::ErrorLogger).to receive(:error)

    } it "nilを返し、通知用のメソッドが呼び出されること" do # エラーを発生させて例外オブジェクトを取得 begin raise StandardError, "Test error" rescue StandardError => e error = e end result = helper.error_boundary { raise error } expect(Asobica::ErrorLogger).to have_received(:error).with(error) expect(result).to be_nil end end end
  11. プロダクト開発部カルチャー “大人な開発組織” 
 行動目標 
 カルチャー 
 Professional 
 価値を創出し、最大化する

    パフォーマンスを出す(システム・個人の生産性) Breakthrough 
 エンジニアリング観点で新しい挑戦をする エンジニア目線で提案ができる 
 Synergy 
 お互いに気持ちの良いコミュニケーション取る 
 Speed 
 価値の提供を早め、トライの回数を増やす 
 Asobigokoro 
 技術を好きになれること 

  12. プロダクト開発部 組織構成予定 ブランド
 デザインG 
 
 7名
 Insight 
 開発G


    
 5名
 データ
 エンジニア リングG
 
 1名
 
 Web
 アプリG
 
 15名
 
 PMG
 
 
 2名
 技術顧問
 
 
 3名
 モバイル
 アプリ
 
 1名
 インフラG 
 
 4名
 プロダクト開発部 
 SRE
 
 2名
 メディア
 開発
 
 2名
 共通基盤チーム 
 新規事業
 開発G