RailsにはRubyの知識も必要！Enumerableモジュールのメソッドを使ってみる


# Rubyって必要なの？ Ruby on Railsだけ知ってればいいと思ってた
Ruby on Railsを使い始めて1年半程になります。
`app/models`配下のファイルといえば、、同名のテーブルがあり、そのモデルのアソシエーション、バリデーションが書いてあるファイルでしょ。メソッドも定義できるらしいけど、テーブルありきだよね。という認識しかなかったのですが、 **テーブルとは関係のないクラスファイルを自由に作って良い**ということを最近改めて知りました。
今まで触ってきたアプリにあったのかもしれないが（いやきっとあった）、意識して見ていませんでした。

Rubyを通ってきていない私にとって、そのバリバリのRubyで書かれたクラスファイルを紐解くのはだいぶ困難を極め。。これはRubyを知らなければ立ち行かなくなってきました。
他でもRubyも知らないと対応できない場面が増えてきたので、最近学習し始めた知識をまとめておくことにしました (」`o´)」

# テーマ
- データベースから取得したデータを**Rubyのメソッドを使って**加工する

- 知っておくと便利だよと周りに教えてもらった [Enumerableモジュール](http://ref.xaio.jp/ruby/classes/enumerable)のメソッド達を使ってみることにします。



# なぜこのテーマなのか
最近よく直面する場面として、Modelを通じてデータベースから抽出した結果をControllerを介し、Viewを呼び出しデータを渡して、、というのが一般的な通信の流れなのですが、データベース取得したデータをそのまま渡すのではなく、あるデータと比較して**条件に合う結果のみを絞り込む**、**必要なカラムのデータのみを渡す**みたいなことが出てきました。

ActiveRecordのメソッドを使えばある程度まで絞り込んだデータを抽出できるのですが、その先で独自のことをしようとするとRubyのメソッドが必要になり。。
ここで**Rubyのメソッドを知っていることで、処理がスラスラ書けるだけでなく、実装の選択肢が自分の中で持てるのかなと思います。**
具体的にはActiveRecordのメソッドを使って取りたいデータぴったりのものを取得しようか、Rubyで加工できるからデータベースからはこのくらいの粒度のデータを取ろうかなどオプションを持て、次の工程をイメージしながら今の実装方法を考えられるようになるかなーと。

そして（実装後にテストを書く手法の場合）**次のステップであるテストをイメージし、テストが書きやすい実装ってどんな感じかな？ということを考えながら個々の実装を行うことで、検証しやすい実装ができる**ことにつながってくるのかな〜と若干想像も交えながらも実感しています。
とかとか、なんだか**Rubyを知っておくといいこと多そう**ということで、まずは基礎的なとこからRubyのメソッドを学んでいこうと思います！

# データベースから抽出したデータを使う
[Railsメソッドを使ったデータ抽出方法の記事](http://qiita.com/kaorina/items/ecf4cd89d7fc6f71d8b3)のために作成した、東京都の市区町村データを使った[サンプルアプリ](https://github.com/kaorina/jpaddress-rails)を使いながら実践していきます。

今回は、Rubyの話に焦点を絞りたいので**ActiveRecordのメソッドは極力使わず**、allメソッドで抽出したデータを中心に使っていきたいと思います。

## 1. ある配列と比較し、**含まれるデータのみ**を返す (select, include?)

Q. City一覧がある配列に含まれるかどうかをチェックし、含まれるcity_id, nameの配列を返す
ある配列として、今まで住んだことのある街`city_id`のリスト（lived_city_ids）を与える。

```ruby:
lived_city_ids = [13115, 13104, 13112]
cities = City.all.map { |city| [city.id, city.name] }
cities.select { |id, name| lived_city_ids.include?(id) }

# => [[13104, "新宿区"], [13112, "世田谷区"], [13115, "杉並区"]]
```

## 2. 含まれるデータ、含まれないデータを**一発で**取得する (partition)

Q. 今まで住んだことのあるCity, ないCityの配列を作成

```ruby:
lived_city_ids = [13115, 13104, 13112]
cities = City.all.map { |city| [city.id, city.name] }
lived_cities, non_lived_cities = cities.partition { |id, name| lived_city_ids.include?(id) }

# 結果
# lived_cities => [[13104, "新宿区"], [13112, "世田谷区"], [13115, "杉並区"]]
# non_lived_cities => [[13101, "千代田区"], [13102, "中央区"]...計59件
``` 

また、比較する配列が追加になった場合、**配列同士は + で結合できる**
（多次元配列の場合は[flattenメソッド](http://ref.xaio.jp/ruby/classes/array/flatten)など使う必要あり）

```ruby:
lived_city_ids = [13115, 13104, 13112]
additional_ids = [13101, 13106]
lived_city_ids + additional_ids  # =>  [13115, 13104, 13112, 13101, 13106]
```

## 3. **全ての要素**が条件に合うかをチェックする (all?)
Q. 与えられるcity_idの配列の要素が全て整数であることをチェックする

```ruby:
city_ids = ["13115", 13104, 0013112, nil]
city_ids.all? { |item| item.is_a?(Integer) } # => false
```

Q.全ての要素の桁数が5桁かどうかをチェックする

```ruby:
city_ids = ["13115", 13104, 0013112, nil]
city_ids.all? { |item| item.to_s.length == 5 } # => false
```

## 4. 含まれるデータを並び替える (sort, sort_by)

Q.今まで住んだことのあるCityをcity_idの昇順に並び替える

```ruby:
lived_city_ids = [13115, 13104, 13112]
cities = City.all.map { |city| [city.id, city.name] }
cities.select { |id, name| lived_city_ids.include?(id) }.sort
```

もしCityデータにローマ字のふりがながを持っていた場合、ふりがなのA->Z順に並べるにはsort_byを使用する

```ruby:
arr = [[13101, "千代田区", "chiyoda"], [13103, "港区", "minato"], [13105, "文京区", "bunkyo"]]
arr.sort_by{ |id, name, furigana| furigana }
=> [[13105, "文京区", "bunkyo"], [13101, "千代田区", "chiyoda"], [13103, "港区", "minato"]]
```

## 5. 配列と比較し、**情報を追加する** (map)

Q. City一覧がある配列に含まれるかどうかをチェックし、その結果をフラグで持つ。結果はハッシュで返す。

```ruby:
# 結果イメージ
[{:id=>13104, :name=>"新宿区", :lived_flg=>true}, #含まれる場合
{:id=>13102, :name=>"中央区", :lived_flg=>false}]　#含まれない場合
```

```ruby:
lived_city_ids = [13115, 13104, 13112]
cities = City.all.map { |city| [city.id, city.name] }
cities.map do |id, name|
  if  lived_city_ids.include?(id)
    { id: id, name: name, lived_flg: true }
  else
    { id: id, name: name, lived_flg: false }
  end
end

# => [{:id=>13101, :name=>"千代田区", :lived_flg=>false},
# {:id=>13102, :name=>"中央区", :lived_flg=>false},
# {:id=>13103, :name=>"港区", :lived_flg=>false},
# {:id=>13104, :name=>"新宿区", :lived_flg=>true}, ...計62件表示
```

# まとめ
Ruby on Railsを使い始めて少し慣れた頃に、Rubyを学ぶとグンと世界が広がり、知識が深くなる気がします。
実はRailsを学び始めてすぐの頃にRubyの本から入ったのですが、その際はふーんという感じで頭に残ることはなく、あえなく数ページで挫折しました(´-д-`)
Railsのお作法に慣れ、Rubyの使いどころや必要性が出てきたフェーズで改めて学ぶことでさらに身についてくる気がします！ 
実践でどしどし使えるよう、さらに学習を進めていきたいと思います〜(๑˃̵ᴗ˂̵)و