webエンジニアの日常

RubyやPython, JSなど、IT関連の記事を書いています

Rubyでどう書く?配列からターゲットの周囲5件を抜き出す

こんにちは、エンジニアのさもです。

仕事で次のような要件のメソッドを実装しました。

  • 配列[1,2,3,4,5,6,7,8,9]がある。
  • この配列から、指定した数字(実際は検索結果の配列に対して、一つのオブジェクトを指定)を含む周囲5件を抜き出した配列を作る

(具体例)

  • 1を指定した場合は、[1,2,3,4,5]
  • 2を指定した場合は、[1,2,3,4,5]
  • 5を指定した場合は、[3,4,5,6,7]
  • 8を指定した場合は、[5,6,7,8,9]
  • 9を指定した場合は、[5,6,7,8,9]

今回は、実装したメソッドの紹介と、Minitestでのテストコードを紹介します。

テスト駆動ではなかったので、後で完成したテストコードを載せています。

続きを読む

Rails入門者のためのQA~例外処理~

f:id:s-uotani-zetakansu:20171128150634j:plain

こんにちは、エンジニアのさもです。

2回目にしていきなり例外処理です。しかもQAじゃないです(笑)

入門したては、ガンガン機能を追加していき、サイトを作りこんで行きたいかと思うのですが、少し立ち止まって、例外処理について学んで下さい。

一度書くと、次に作るときにコピペでOKです!

スポンサーリンク

目次

Railsにおける例外処理とは?

Javaなどのプログラミング言語でも例外を投げる、キャッチする。なんて言いますよね。

Rubyにもraise, rescueという例外に関する仕様はあるのですが、今回はRailsで例外発生時の挙動をどうするか、について書いていきます。

webサイトを良く見る方は、「404 Not Found」みたいなページを見たことがあるでしょうか?URLが間違っていたり、久しぶりに訪れたらサイトが無くなっていたなんてときに表示されるページです。

「404」というのはwebページへアクセスしたときに、コンテンツと一緒についてくる、「HTTPステータスコード」の一つです。

正常にページが見れるときは、200が割り当てられています。サーバに障害があったときは、500が返ってきたりします。

詳しくはこちら

404はただのコードなので、webページの場合は、返ってきてもどうしようもないですよね。だから404ページと言われるものを返します。

自分でwebサイトを作るときも、間違ったURLにアクセスされたとき用に404ページは作っておかなければなりません。

それ以外に、例えば、/users/1 のように、idが1のユーザにアクセスするURLがあるとします。このとき、存在しないユーザーIDへアクセス(/users/999)した場合にも404ページを返さなくてはいけません。

なぜなら、RailsはRestful、つまりURLとリソースが1対1で結びついているからです。リソースというと、/views/users/show.html.erbのことを思い浮かべるかもしれませんが、実際は、「idが1のユーザー」の事を指しています。htmlファイルはあくまでも、リソースを見やすく整形したものです。

そのため、「/users/存在しないユーザーID」にアクセスされたときは、対応するリソース(ユーザー)が存在しないので、ページが存在しないという情報を返さなくてはなりません。この情報が、404ページであり、ステータスコード404です。

例外の発生方法

例外処理の基本は、例外が発生(raise)ー>例外をキャッチ(rescue)です。

まずは例外の発生について書いていきましょう。

具体的にどのように実装するのか、ですが、実はとても簡単です。

最も基本的な例ですが、UsersController#showで、存在しないユーザIDが指定された場合について考えましょう。

class UsersController < ApplicationController
  before_action :set_user, only: [:edit, :update, :show, :destroy]
  # index等省略
  def show
  end

  private

  def set_user
    @user = User.find(params[:id])
  end
end

はい、完了です。

いつもどおりのコントローラですね。

どこで例外が発生するかわかりますか?

正解は、findメソッドです。

findメソッドは、引数で渡したIDのユーザが存在しない場合に、ActiveRecord::RecordNotFoundという名前の例外を発生させます。

試しに、rails consoleで「User.find(999)」と打ってみてください(モデルはお使いの環境に合わせて、存在しているモデルに変えてください)。ActiveRecord::RecordNotFoundと表示されるはずです。

例外のキャッチの仕方

何もしません(笑)

404エラーや500, 422エラーの場合は、Railsがよしなにやってくれます。

表示されるエラーページ自体はpublicフォルダにあります。

ただし、デフォルトのエラーページは味気ないので、かっこよくカスタマイズしたい場合は、public/404.htmlなど、対応するhtmlファイルを編集すればOKです。

自分で例外を発生させる

ActiveRecord::RecordNotFoundの場合には自動的に例外を投げてくれましたが、「自分のサイトではこういう場合に404を発生させて、404ページを表示したいんだ」ということがあります。

そんなときは以下のようにします。(例えば、ユーザのemailカラムが未入力の場合に、まだユーザが存在していないかのように見せたいとき。)

class UsersController < ApplicationController
  before_action :set_user, only: [:edit, :update, :show, :destroy]
  # index等省略
  def show
    raise ActiveRecord::RecordNotFound.new("お試し例外だよ") if @user.email.nil?
  end

  private

  def set_user
    @user = User.find(params[:id])
  end
end

showアクションに1行追加しました。

raiseメソッドは、第一引数の例外を発生させるKernelクラスのメソッドです。

ちなみに、raiseメソッドに文字列を渡すと、その文字列をメッセージとしたRuntimeError例外を発生させます。

すべての例外に対応する

ActiveRecord::RecordNotFoundをはじめ、例外はたくさんあります。そこで、用意している例外以外の例外に対応するために、 復旧可能な実行時エラーの親クラスである、StandardErrorに対してrescueします。

エラーキャッチの定義は、application_controller.rbに書きます。

class ApplicationController < ActionController::Base

  rescue_from StandardError, with: :rescue_exeption

  def rescue_exeption(e = nil)
    if e
      logger.info "StandardError!: #{e.message}"
      logger.info e.backtrace.join("\n")
    end
    redirect_to root_path
  end
end

このように書いておくと、Railsが拾わなかった例外を、rescue_exeptionメソッドが処理してくれるようになります。rescue_exeption内では、エラー原因特定やデバッグのために、出来るだけ多くの情報を残しましょう。

Bagsnagというサービスを利用して、開発者へ通知するなどの処理を含めるのも有効です。

参考

より詳しく勉強したいという方のために、オススメの書籍を紹介します

  • ステータスコードやURLをどう設計するかなど、Rialsでも役に立つ知識がいっぱい載っています。

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

  • 定評のあるRails本

Ruby on Rails 5アプリケーションプログラミング

Ruby on Rails 5アプリケーションプログラミング

Ruby on Rails 4 アプリケーションプログラミング

Ruby on Rails 4 アプリケーションプログラミング

  • 最近出たRubyの本(チェリー本)すごくいい!先行販売してたので買いました。

  • Railsの例外について、とてもよくまとまっているエントリーです。

qiita.com

最後に

以上、Railsの例外処理でした。

いかなるユーザの操作に対しても応答できるwebサービスを目指して、ぜひ例外処理を書いてみてください。

読者登録をしていただけると、ブログを続ける励みになりますので、よろしくお願いします。

あと4日!!【50%OFF以上】Amazon 人工知能本フェア!

こんにちは、エンジニアのさもです。

2017年11月30日までAmazonで人工知能関連書籍が50%(以上)OFFになっています。

あと4日!!

  • ゲームを作りながら楽しく学べるPythonプログラミング(70%OFF)

ゲームを作りながら楽しく学べるPythonプログラミング (Future Coders(NextPublishing))

ゲームを作りながら楽しく学べるPythonプログラミング (Future Coders(NextPublishing))

などなど対象商品は111件ありました。

AmazonKindle雑誌99円セール!!11月30日まで

こんちには、エンジニアのさもです。

またセールやってないかなとAmazonのKindleストアをみると、雑誌99円セールというものをやっていました。

あんまり雑誌に興味がないなと思いつつも、みてみると、結構種類が豊富で、中には96%OFFの雑誌もあったので早速買っちゃいました(笑)

ちょっとだけ紹介します。

  • 楽しいガジェットを作る いちばんかんたんなラズベリーパイの本(96%OFF)

楽しいガジェットを作る いちばんかんたんなラズベリーパイの本

楽しいガジェットを作る いちばんかんたんなラズベリーパイの本

驚異の96%OFF!買いました。

  • FRIDAY (フライデー) 2017年11月17日号 [雑誌] FRIDAY

普段絶対に買いませんが、99円なら・・・

  • 一生使えるオレンジページVOL.4 収納&捨てワザで家じゅうすっきり!

  • デジモノステーション (2016年2月号)

デジモノステーション (2016年2月号) [雑誌]

デジモノステーション (2016年2月号) [雑誌]

  • 作者: エムオン・エンタテインメント
  • 出版社/メーカー: エムオン・エンタテインメント
  • 発売日: 2017/06/01
  • メディア: Kindle版
  • この商品を含むブログを見る

などなど、今のところ、対象商品は3,712 点ありました。

【Rails】画像アップロードでたまーに落ちるバグに注意!

こんにちは、エンジニアのさもです。

CarrierWaveを使った画像アップロードが実装済みの画面を改修(追加で画像をアップロードできるようにする修正)しているときに、なぜかたまに参照している画像が存在しないという旨のエラーで落ちていました。

自分のうっかりミスだったのですが、ちゃんと動くときもあり、陥りやすいミスなのでメモしておきます。

続きを読む

Androidを勉強し始めましたが、いい本見つけたので紹介します

こんにちは、エンジニアのさもです。

最近、Androidアプリを勉強&作り始めました。

webの情報も充実しているので、それだけでもAndroidアプリの開発は学べると思うのですが、一冊なにか書籍が欲しいなと思って、安くて評判のいい本をkindleで買いました。

その本がとても良かったので紹介します。

続きを読む