【Rails初心者必見！】ひたすら丁寧にデータ取得を説明(find, where)


Railsをとりあえず学び始めたという方が、とりあえずよくわからず使っても動くけど、結局理解があいまいになりがちなのがこのデータの取得部分だと思います。

データを取得しないアプリは無いと言っても過言ではないと思うので、しっかり理解しておきましょう。
今回はここをひたすら初心者目線で丁寧に解説したいと思います！
（わかりにくいところがあったら是非遠慮なくコメントくださいm(_ _)m）

- - -

# データを1つだけ取得する
## 特定のIDのデータを取得したい

* 使用例：IDがわかっているデータをあるモデルから取得したい時
* よくある利用ケース：RailsのshowアクションであるIDのデータを取得
* 複数条件：不可

```ruby
class ArticlesController < ApplicationController

  def show
	@article = Article.find(params[:id])  
  end
end

# URLは例えば http://localhost:3000/articles/1
```

***findは指定したモデルのインスタンス（すぐに利用できるデータ）を返す***ので、例えば「@article.title」のように使えます。取得したデータがインスタンスかどうかというのは非常に重要なので頭に入れておいてください。


## 特定のカラムの値から1つのデータを取得したい

* 使用例：ID以外のカラムデータから1つのデータを取得したい時
* よくある利用ケース：Emailからユーザーを取得したい時
* 複数条件：可

```ruby
class UsersController < ApplicationController
  
  def edit
    @user = User.find_by(email: params[:email])
  end 
end


# URLは例えば http://localhost:3000/articles/1/edit
```

find_byも ***指定したモデルのインスタンス（すぐに利用できるデータ）を返します***ので、「@user.email」などの使い方ができます。
また、下記のように複数条件の指定も可能です。

```ruby
@user = User.find_by(email: params[:email], name: '田中太郎')
```

実は別にidを指定することも可能ですし、使われることもしばしばありますが、少し挙動に違いがあります。これについては後で説明します。


## ある条件にあてはまるものの最初の1つを取得する

* 使用例：ある条件下のリストを取得してそのうち一番初めのものを取得したい時
* よくある利用ケース：新着記事などでとりあえず最初のものを見せたい時
* 複数条件：可

```ruby

class HomeController < ApplicationController

  def index
    Article.where('created_at > ?', 1.day.ago).first
  end
end

```

ちょっと利用ケースが適切で無いかもしれません。。（思いつかなかった、、）
ここで重要なのは ***whereメソッドを使った場合、指定したモデルのインスタンスではないのでそのままデータを利用できない***ということです。

***whereは範囲を絞っただけ***なので、その範囲の中のどれを使うかを指定する必要があります。今回はfirstメソッドを後ろにつけて、絞った中の一番はじめのものを取得しています。

よく初心者の方が間違えるのが

```ruby
class HomeController < ApplicationController

  def index
    @article = Article.where(id: 1)
  end
end

# 以下はViewの中でのお話
<h1><%= @article.title %></h1>

```
こういうことはできません。これは私の経験上、初心者によくあるかなと思っています。whereで取得できるものが最初から1つだとわかっていたりした場合に、そのまま使えると勘違いしてしまうのですね。あくまで ***whereは範囲を絞っただけ***と覚えるようにしておいてください。


# 複数データの取得

## ある条件にあてはまるものを複数取得

* 使用例：全データをリストで表示したい時
* よくある利用ケース：indexアクションでモデルのデータをリスト的に表示したい時

```ruby
class ArticlesController < ApplicationController

  def index
    # 有効な全記事を取得してきています
    @articles = Article.where(active: true)
  end
end
```
この場合も先ほどあったように、whereは範囲を絞っただけなのでどれを使うか指定してあげなければいけません。そこで、ここでよく使うのがeachですね。例えばViewは下記の感じです。

```erb
# app/views/articles/index.html.erb

<% @articles.each do |article| %>
  <ul>
    <il>タイトル：<%= article.title %></li>
    <il>内容：<%= article.content %></li>
    <il>投稿日：<%= article.created_at %></li>
  </ul>
<% end %>
```
ここで重要なのは、 ***eachで回っている時（ブロック変数のarticleにデータが入る時）には、Articleのインスタンスになっている***ということです。これによって、もともとはwhereで範囲を絞っただけのものだったのに、「article.title」などというように利用できるわけです。

# 補足 (findとfind_byの違い)

先ほど上で少し書きましたが、find_byでもfind_by(id: 1)のような使い方はできます。では何が違うかというと

```ruby
# 前提：Userはidが1のものしか存在しない

# これは完全に同じ
@user = User.find(1)
@user = User.find_by(id: 1)

# ココがポイント！
@user = User.find(2)
#=> ActiveRecord::RecordNotFound: Couldn't find User with 'id'=2

@user = User.find_by(id: 2)
#=> nil
```

わかりましたか？？findメソッドは、もしデータが無かった場合、エラーになります。よくraiseするとか言われますね。なので、確実にデータを取得できる場合に使いましょう。逆にfind_byはデータが無くてもnilを返してくれます。
なので、例えば

```ruby
if User.find_by(id: 2)
  @user_existance = true
else
  @user_existance = false
end
```
こういうことができます。

# まとめ
いろいろあって難しいかもしれませんが、私の結論としては

| 取得したいデータの数 | 使用メソッド
|:-----------|------------:|
| 1つ（idがわかっている）| find |
| 1つ（idがわからない） | find_by |
| 複数 | where |

最初のうちはこの理解で十分ではないかと思います。


# おまけ（初心者の方におすすめの勉強方法）

## 書籍
### [たのしいRuby](http://www.amazon.co.jp/%E3%81%9F%E3%81%AE%E3%81%97%E3%81%84Ruby-%E7%AC%AC4%E7%89%88-%E9%AB%98%E6%A9%8B-%E5%BE%81%E7%BE%A9/dp/4797372273/ref=sr_1_1?ie=UTF8&qid=1441271875&sr=8-1&keywords=%E3%81%9F%E3%81%AE%E3%81%97%E3%81%84Ruby)
アフィリエイトじゃないですよ笑　
私自身、Rubyはこれで学びました。解説がわかりやすく、進めて行きやすいです。ですが、例えば数値の型まわりなど、初心者のうちはそれほど必要ない部分もけっこうあるので、さらっと全体をなめてからよく使いそうな場所を重点的に勉強していくのが良いのではないかなと思います。

## オンライン学習
### [Progate](http://prog-8.com/lessons/rails/beginner)
動画学習のサービスの中では非常にわかりやすいと思います。英語がわかるかたはCodeAcademyとかもいいかもしれません。

## アプリ学習
### [Pocket Programming](https://play.google.com/store/apps/details?id=ffab0.pocketprogramming)
初心者が混乱しないように、本当に必要な部分に特化した問題を解いて知識を定着できます。スマホアプリなので、電車の中やテレビ見ながら、あるいはリラックスタイムなどに、上記の書籍やオンライン学習の理解をチェックしてみるのもいいですね。