テクノロジー

2018年12月28日

Ruby、Railsのメソッド分類

Ruby、Railsのメソッド分類

メソッドとは

Railsにおいてメソッドは様々な種類が存在します。Rubyが用意してくれているメソッドもあれば、Railsが独自に用意しているメソッドもあり、さらに独自で定義したメソッドも存在しているのです。

私自身、メソッドという言葉に引っかかっておりました。そこで今回の核である「メソッドの分類」を行ったことにより、Railsに対する理解のスピードが数倍上がりました。

メソッドでモヤモヤしている方はぜひ読んでみてください。

※Railsコンソールを立ち上げておくと、より理解が深まると思います。

メソッドの基本

メソッドを分類する前にまずはメソッドの基本形を押さえておきましょう。Ruby(Rails)においてメソッドは「def - end」でメソッドを定義します。

def method_name

end

コントローラのアクション、モデルやヘルパーでの独自なメソッドを定義する時によく使われる形です。

しかしRailsにおいては、先ほど述べたようにすでに用意されているメソッドもあります。むしろその方が多いと言えます。

次節でそれらを分類して頭の中を整理しましょう。

メソッドの分類

Rubyが用意してくれるメソッド

1. newメソッド

これはインスタンスを生成するメソッドです。Railsのコントローラにてよく使われます。
以下のようにBlog.newと実行するとブログのインスタンスが作成されます。

 Blog.new
=> #<Blog:0x007fb0de54aa88 id: nil, title: nil, content: nil, created_at: nil, updated_at: nil>

2. eachメソッド

これは配列やハッシュの中身から値を取り出すメソッドです。

以下のようにarrayという名前の配列を用意して、eachで一つひとつの値をtextという変数に入れて表示することができます。

array = ['aaaa', 'bbbb', 'cccc']

array.each do |text|
  puts text
end

#=> 'aaaa'
#=> 'bbbb'
#=> 'cccc'

eachメソッドの良い点は、配列の中身を見て何回ループさせるかを自動で判断してくれる点です。ここではarrayの中に3つ値が入っているので3回ループします。Railsの中でもよく使われるメソッドの一つです。

3. sortメソッド

これは配列やハッシュの中身を昇順に並び替えるメソッドです。arrayという配列を用意してランダムに数字を入れます。
そしてsortメソッドを実行すると数字が昇順に並び替えられます。文字列であればアルファベット順やあいうえお順に並び替えられます。

array = [1, 4, 7, 3, 2]
array.sort

#=> [1, 2, 3, 4, 7]

Railsが用意してくれるメソッド

ここではRailsが提供しているメソッドについて紹介していきます。Railsが用意しているということは、Ruby単体では使えないメソッドです。
今回は「ActiveSupportコア拡張機能」「ActiveRecordのメソッド」の分類を行っていきましょう。

ActiveSupportコア拡張機能

これは「Rubyを拡張して開発に役立つように作られたメソッドの集まり」のことです。

1. present?メソッド

これは変数の中身や指定したクラスなどが存在していればtrue、そうでなければfalseを返すメソッドです。

if @blog.user.name.present?

対義語としてblank?というメソッドもあります。以下は上記コードと同じ意味になります。

unless @blog.user.name.blank?

2. tryメソッド

これはオブジェクトの中身がnilの場合nilを返し、そうでなければ引数で指定したメソッドを実行するメソッドです。

例えば@blogのユーザーを表示させたい時、通常なら@blogがnilならエラーが返ってきてしまいます。そのため以下のように条件分岐をする必要があります。

unless @blog.nil?
  @blog.user
end

しかしtryメソッドを使うと、nilの時に例外が発生しないため以下のように1行で済んでしまいます。

@blog.try(:user)

さらに複数のメソッドを実行するケースにも対応することができます。

if @user.followers && @user.followed_users

以下のようにtryでメソッドをつなげていくことで複数のメソッドを同時に行うことができます。

if @user.try(:followers).try(:followed_users)

3. 時間計算を行うメソッド

ActiveSupportには日付や時間を計算するためのライブラリがあります。例えば現在の時刻が知りたい時は以下のコードを実行します。

now = DateTime.current
#=> Sat, 15 Oct 2016 07:20:27 +0000

さらに現在時刻を基準に昨日の日時を知りたいときは以下のようになります。

now.yesterday
#=> Fri, 14 Oct 2016 07:20:27 +0000

時間計算を行うメソッドはこれらの他にも山ほど存在します。
詳しくはRailsガイドのActiveSupportコア拡張機能
http://railsguides.jp/active_support_core_extensions.html 】を参照してみてください。

ActiveRecordのメソッド

これは一言で表すと、「実行するとSQLが一緒に走るメソッド」です。

1. allメソッド
モデルに紐づくテーブルから全てのデータを取得するメソッド

以下のようにallメソッドを用いてblogsテーブルからすべてのデータを取得してみます。使い方はクラスに直接「.all」とメソッドを実行します。

Blog.all

上記を実行すると「SELECT」というSQLが一緒に走ります。

Blog Load (0.5ms)  SELECT "blogs".* FROM "blogs"

使用例としては、ブログ一覧機能が挙げられます。
blogsコントローラですべての値を引っ張ってきて、ビューにてeachメソッドを使って中身をblogという変数に入れて表示しています。

(app/controllers/blogs_controller.rb)

def index
  @blogs = Blog.all
end

(app/views/blogs/index.html.erb)

@blogs.each do |blog|
  blog.title
  blog.content
  blog.user.name
end

allメソッドはblogsテーブルにあるブログオブジェクトを配列で取得するメソッドです。そのため、ビューファイルではeachメソッドを用いて取り出す必要があるのです。

[#<Blog:0x007fb0de5ef740>, #<Blog:0x007fb0de5e7360>, #<Blog:0x007fb0de5e7220>]

2. saveメソッド

これはモデルから作成した一つのデータを、モデルに紐づくテーブルに保存するメソッドです。

@blog = Blog.new(title: 'あああ', content: 'いいい')
#=> #<Blog:0x007fb0de54aa88 id: nil, title: 'あああ', content: 'いいい', created_at: nil, updated_at: nil>

上記を実行すると「INSERT INTO (テーブル名)」と「COMMIT => true」というSQLが一緒に走ります。

(14.3ms)  BEGIN
  SQL (41.9ms)  INSERT INTO "blogs" ("title", "content", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["title", "あああ"], ["content", "いいい"], ["created_at", 2016-10-14 04:49:13 UTC], ["updated_at", 2016-10-14 04:49:13 UTC]]
(24.9ms)  COMMIT
=> true

saveメソッドを実行する前と実行した後での変数の中身は変化しています。

@blog
#=> #<Blog:0x007fb0de54aa88 id: 1, title: 'あああ', content: 'いいい', created_at: 2016-10-14 04:49:13, updated_at: 2016-10-14 04:49:13>

DBに保存された瞬間にid, created_at, updated_atの3つの値が挿入されます。

3. orderメソッド
引数で指定したカラムの昇順/降順で並び替えるメソッド

Blog.all.order(title: :asc)

上記を実行すると「ORDER BY」というSQLというが一緒に走ります。

Blog Load (25.3ms)  SELECT "blogs".* FROM "blogs" ORDER BY "blogs"."title" ASC

先ほどに紹介したsortメソッドに似ていますが、orderメソッドは配列に対しては実行できない一方で、sortメソッドはオブジェクトに対して実行することはできません。

オブジェクト自身が持っているメソッド

例えばfindメソッドでidが1のブログデータを取り出します。

@blog = Blog.find(1)

すると以下のようなものが表示されるでしょう。

#<Blog:0x007fa978322610
 id: 1,
 title: "aaaa",
 content: "bbbb",
 created_at: Fri, 30 Sep 2016 06:28:00 UTC +00:00,
 updated_at: Mon, 03 Oct 2016 11:19:56 UTC +00:00>

このようにBlog1つのデータのことを「オブジェクト」と呼びます。ここではBlogモデルに所属しているオブジェクトなので、「Blogオブジェクト」ということになります。

ディープロに所属している受講生が1人いるとして、その人にいくつか質問を投げかけます。

https://diveintocode.gyazo.com/002be29a25732916b98b26c179eb2e58

このように、自身のことを問い合わせることができるのは当然のことですが、これをオブジェクトに置き換えても同じことが起こります。

例えばコンソール上で以下のようなコードを実行します。

@blog.title

これは「ブログのタイトルは?」と質問しているのと同じことになります。それに対する答え「aaaa」が返ってきます。

=> "aaaa"

他にもそのオブジェクトがどこに所属しているかを尋ねることもできます。

@blog.class

今回の場合、BlogオブジェクトなのでBlogクラスに所属しています。そのため上記を実行すると以下のようなレスポンスが返ってきます。

 => Blog(id: integer, title: string, content: text, created_at: datetime, updated_at: datetime)

このようにオブジェクト自身が持っているメソッドも存在しているのです。

https://diveintocode.gyazo.com/fab8f35c9c3f2069ef40db4addb939a9

メソッド分類表

最後に今回取り上げたメソッドを表にまとめてスッキリしましょう。

https://diveintocode.gyazo.com/9bbe5fe3bd23e5a2fd0525931fd45710

いかがでしたでしょうか?メソッドをきちんと把握することでRailsに対する理解がさらに深まると思います。
正しくメソッドを使いこなすことにもつながるので、

ダイビックのことをもっと知ってみませんか?