ためすう
Rails5 で rescue_from を使う
2019-05-12やったこと
Rails5 の rescue_from メソッドについて調べます。
確認環境
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]
$ rails --version
Rails 5.2.3
調査
app/controllers/tasks_controller.rb
class TasksController < ApplicationController
rescue_from Exception, with: :render_500
def index
raise Exception.new
end
def render_500
logger.debug('render_500')
end
end
※ 任意のコントローラに記述してください
注意点
ApplicationControllerクラスでは一部の例外についてrescueできないものがあります。その理由は、コントローラが初期化されてアクションが実行される前に発生する例外があるからです。
と説明があるので、コントローラが初期化される前に、例外が発生した場合は捕捉できない場合があります。
参考
Ruby でキーワード引数を使う
2019-05-12やったこと
キーワード引数を使ってみます。
確認環境
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]
調査
test.rb
class Sample
def initialize(params)
p params
# a を取りだす
p params[:a]
end
end
Sample.new(a: 111, b: 222)
出力結果
$ ruby test.rb
{:a=>111, :b=>222}
111
情報を探しても見つかりませんでしたが、関数の引数に ** を付きなくても キーワード引数のハッシュとして、扱えるようです。
Rails5 で try を使う
2019-05-12やったこと
try メソッドについて調べます。
確認環境
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]
$ rails --version
Rails 5.2.3
調査
レシーバーのクラスがnilの場合
$ rails c
irb(main):001:0> @number.try(:nest)
=> nil
irb(main):002:0> @number.try!(:nest)
=> nil
try, try! のどちらを使っても nil が返されました。
レシーバーのクラスが存在する場合
$ rails c
Running via Spring preloader in process 21611
Loading development environment (Rails 5.2.3)
irb(main):001:0> class Sample
irb(main):002:1> def nest
irb(main):003:2> p 3
irb(main):004:2> end
irb(main):005:1> end
=> :nest
irb(main):006:0> @number = Sample.new
=> #<Sample:0x00007f96c024adc0>
irb(main):007:0> @number.try!(:nest)
3
=> 3
irb(main):008:0> @number.try!(:nest_nothing)
Traceback (most recent call last):
1: from (irb):8
NoMethodError (undefined method `nest_nothing' for #<Sample:0x00007f96c024adc0>)
irb(main):009:0> @number.try(:nest)
3
=> 3
irb(main):010:0> @number.try(:nest_nothing)
=> nil
try だと存在しないメソッドを呼び出そうとしても nil が返されることが分かります。
try について
nilでない場合にのみオブジェクトのメソッドを呼び出したい場合、最も単純な方法は条件文を追加することですが、どこか冗長になってしまいます。そこでtryメソッドを使うという手があります。tryはObject#sendと似ていますが、nilに送信された場合にはnilを返す点が異なります。
tryメソッドは、NoMethodErrorを握りつぶして代わりにnilを返す点に注意が必要です。メソッド名の誤りを防ぎたい場合はtry!を使います。
try を使うには、 Active Support を読み込んでおく必要があります。
Rails の場合は、すぐに使えるようです。
Ruby on Railsアプリケーションでは、基本的にすべてのActive Supportを読み込みます。
参考
Ruby での参照渡しについて
2019-05-10やったこと
Ruby での参照渡しについて、調べてみます。
確認環境
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]
調査
関数に渡す引数の変数について、object_id を調べてみます。 また変数の代入もしてみます。
test.rb
def test(a, b)
p "a: #{a.object_id} in test"
p "b: #{b.object_id} in test"
end
a = 1
b = 2
c = b
p "a: #{a.object_id}"
p "b: #{b.object_id}"
p "c: #{c.object_id}"
test(a, b)
出力結果
$ ruby test.rb
"a: 3"
"b: 5"
"c: 5"
"a: 3 in test"
"b: 5 in test"
どうやら、引数として渡す前、渡した後のオブジェクトは同じもののようです。
つまり、引数に対して関数内で引数のオブジェクトに直接変更を加えると 関数を抜けた後も影響を受けます。
test.rb
def test2(a, b)
a.upcase!
end
a = 'abc'
b = 'jkl'
test2(a, b)
p a
p b
出力結果
"ABC"
"jkl"
参考
Rails5 でエラーページを表示する
2019-05-09やったこと
Rails5 にて、エラーページを表示する方法を調べました。
静的なページ、動的なページのどちらにするかで方法が変わります。
確認環境
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]
$ rails --version
Rails 5.2.3
調査
静的なページを表示
すでに用意されているものを利用します。
config/environments/development.rb
config.consider_all_requests_local = false
例えば存在していないページにアクセスした時、 public/404.html が使われます。
動的なページを表示
config/environments/development.rb
config.consider_all_requests_local = false
エラーページの view を用意します。
app/views/errors/error_404.html.erb
404 dayo
例外を制御します。今回は 404エラーの時の振る舞いを定義します
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
rescue_from ActionController::RoutingError, with: :render_404
def render_404
logger.debug(9999)
render template: 'errors/error_404', status: 404, layout: 'application', content_type: 'text/html'
end
end
最後にルーティングの一番下に下記を追加してください
config/routes.rb
get '*path', controller: 'application', action: 'render_404'
参考
Rails5 で日付のバリデーションを行う
2019-05-09やったこと
Rails5 で日付、日時をフォーマットする方法を調べます。
確認環境
$ ruby --version
ruby 2.6.2p47 (2019-03-13 revision 67232) [x86_64-darwin17]
$ rails --version
Rails 5.2.3
調査
やったこと
Rails5 ではデフォルトで日付のバリデーションがないようなので、実装方法を調べました。
task.expire_date という タスクの有効期限について、日付のバリデーションをかけます。
調査
app/models/task.rb
class Task < ApplicationRecord
validate :expire_date_is_valid?
private
def expire_date_is_valid?
begin
Date.parse self.expire_date.to_s if self.expire_date.present?
rescue ArgumentError
errors.add(
:expire_date,
'無効な日付です'
)
end
end
end
Date.parse の挙動も試してみました。
$ rails c
irb(main):001:0> Date.parse(888)
Traceback (most recent call last):
2: from (irb):1
1: from (irb):1:in `parse'
TypeError (no implicit conversion of Integer into String)
irb(main):002:0> Date.parse('20190509')
=> Thu, 09 May 2019
irb(main):003:0> Date.parse('2019-05-09')
=> Thu, 09 May 2019
irb(main):004:0> Date.parse('19-05-09')
=> Thu, 09 May 2019
irb(main):005:0> Date.parse('9919-05-09')
=> Fri, 09 May 9919
irb(main):006:0> Date.parse('11')
=> Sat, 11 May 2019
これをみると、厳密なチェックは出来ていないので、使用するときは注意してください。
参考
Rails5 の migration で追加するカラムの順番を制御する
2019-05-09やったこと
Rails5 の migration を利用してカラムを追加する時、追加する位置を制御する方法について調べました。
確認環境
$ ruby --version
ruby 2.6.2p47 (2019-03-13 revision 67232) [x86_64-darwin17]
$ rails --version
Rails 5.2.3
調査
$ rails g model Task2 name:string content:text
$ rails db:migrate
ここで、task2 テーブルに status カラムを content カラムの後に追加します。
$ rails g migration AddStatusAtToTask2s status:int
これが生成されたファイルです。
db/migrate/20190508233635_add_status_at_to_task2s.rb
class AddStatusAtToTask2s < ActiveRecord::Migration[5.2]
def change
add_column :task2s, :status, :int
end
end
※ 日時部分は実行時間によって変わります。
下記のように変更します。 デフォルトのままだと、カラムが一番後に追加されます。
class AddStatusAtToTask2s < ActiveRecord::Migration[5.2]
def change
add_column :task2s, :status, :int, after: :content
end
end
$ rails db:migrate
無事に意図した位置にカラムを追加することができました。
参考
&. で nil チェック (Ruby)
2019-05-09やったこと
&. を利用して nil のチェックをしてみます。
確認環境
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]
調査
$ rails c
irb(main):001:0> foo = 13
=> 13
irb(main):002:0> foo&.to_s
=> "13"
irb(main):003:0> nil&.to_s
=> nil
irb(main):004:0> nil.to_s
=> ""
irb(main):005:0> nil.hoge
Traceback (most recent call last):
2: from (irb):5
1: from (irb):5:in `rescue in irb_binding'
NoMethodError (undefined method `hoge' for nil:NilClass)
irb(main):006:0> nil&.hoge
=> nil
&. について
メソッド呼び出しで
.' の代わりに
&.’ を使うことができます。 この形式でメソッドを呼びだそうとすると、レシーバが nil の場合は 以下のように働きます。 - 引数の評価が行なわれない - メソッド呼び出しが行われない - nil を返すsafe navigation operator(通称「ぼっち演算子」)
参考
Rails5 で日付、日時をフォーマットする
2019-05-08やったこと
Rails5 で日付、日時をフォーマットする方法を調べます。
確認環境
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]
$ rails --version
Rails 5.2.3
調査
方法1. strftime
irb(main):001:0> Date.current.strftime('%Y/%m/%d')
=> "2019/05/08"
この方法は都度フォーマットを指定する必要があります。
方法2. config/locales
I18n の機能を利用します
デフォルトの言語を日本語にします
config/application.rb
config.i18n.default_locale = :ja
次に、yml でフォーマットを定義します
config/locales/ja.yml
ja:
date:
formats:
default: '%Y/%m/%d'
long: '%Y年%m月%d日'
short: '%m/%d'
I18n を使って日付をフォーマットします。
$ rails c
Running via Spring preloader in process 87044
Loading development environment (Rails 5.2.3)
irb(main):001:0> I18n.l(Date.today)
=> "2019/05/08"
irb(main):002:0> I18n.l(Date.today, format: :long)
=> "2019年05月08日"
irb(main):003:0> I18n.l(Date.today, format: :short)
=> "05/08"
参考
Ruby で引数にメソッドを渡す
2019-05-07やったこと
Ruby の関数で引数にメソッドを渡す方法を調べてみます。
確認環境
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]
調査
test.rb
def xxx(&yyy)
p yyy
yyy.call
end
def abc1
p 'abc1'
end
## ブロック付きメソッド呼び出し
## { ... }
p '{ ... }'
xxx {
abc1
}
## do ... end
p 'do ... end'
xxx do
abc1
end
出力結果
$ ruby test.rb
"{ ... }"
#<Proc:0x00007faa8a036588@ruby-block.rb:13>
"abc1"
"do ... end"
#<Proc:0x00007faa8a036358@ruby-block.rb:19>
"abc1"
最後の引数の直前に & がついている場合、その引数で指定した手続き オブジェクト(Proc)やメソッドオブジェクト(Method)がブロック としてメソッドに渡されます。