Rubyって必要なの? Ruby on Railsだけ知ってればいいと思ってた
Ruby on Railsを使い始めて1年半程になります。
app/models
配下のファイルといえば、、同名のテーブルがあり、そのモデルのアソシエーション、バリデーションが書いてあるファイルでしょ。メソッドも定義できるらしいけど、テーブルありきだよね。という認識しかなかったのですが、 テーブルとは関係のないクラスファイルを自由に作って良いということを最近改めて知りました。
今まで触ってきたアプリにあったのかもしれないが(いやきっとあった)、意識して見ていませんでした。
Rubyを通ってきていない私にとって、そのバリバリのRubyで書かれたクラスファイルを紐解くのはだいぶ困難を極め。。これはRubyを知らなければ立ち行かなくなってきました。
他でもRubyも知らないと対応できない場面が増えてきたので、最近学習し始めた知識をまとめておくことにしました (」`o´)」
テーマ
-
データベースから取得したデータをRubyのメソッドを使って加工する
-
知っておくと便利だよと周りに教えてもらった Enumerableモジュールのメソッド達を使ってみることにします。
なぜこのテーマなのか
最近よく直面する場面として、Modelを通じてデータベースから抽出した結果をControllerを介し、Viewを呼び出しデータを渡して、、というのが一般的な通信の流れなのですが、データベース取得したデータをそのまま渡すのではなく、あるデータと比較して条件に合う結果のみを絞り込む、必要なカラムのデータのみを渡すみたいなことが出てきました。
ActiveRecordのメソッドを使えばある程度まで絞り込んだデータを抽出できるのですが、その先で独自のことをしようとするとRubyのメソッドが必要になり。。
ここでRubyのメソッドを知っていることで、処理がスラスラ書けるだけでなく、実装の選択肢が自分の中で持てるのかなと思います。
具体的にはActiveRecordのメソッドを使って取りたいデータぴったりのものを取得しようか、Rubyで加工できるからデータベースからはこのくらいの粒度のデータを取ろうかなどオプションを持て、次の工程をイメージしながら今の実装方法を考えられるようになるかなーと。
そして(実装後にテストを書く手法の場合)次のステップであるテストをイメージし、テストが書きやすい実装ってどんな感じかな?ということを考えながら個々の実装を行うことで、検証しやすい実装ができることにつながってくるのかな〜と若干想像も交えながらも実感しています。
とかとか、なんだかRubyを知っておくといいこと多そうということで、まずは基礎的なとこからRubyのメソッドを学んでいこうと思います!
データベースから抽出したデータを使う
Railsメソッドを使ったデータ抽出方法の記事のために作成した、東京都の市区町村データを使ったサンプルアプリを使いながら実践していきます。
今回は、Rubyの話に焦点を絞りたいのでActiveRecordのメソッドは極力使わず、allメソッドで抽出したデータを中心に使っていきたいと思います。
1. ある配列と比較し、含まれるデータのみを返す (select, include?)
Q. City一覧がある配列に含まれるかどうかをチェックし、含まれるcity_id, nameの配列を返す
ある配列として、今まで住んだことのある街city_id
のリスト(lived_city_ids)を与える。
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の配列を作成
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メソッドなど使う必要あり)
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の配列の要素が全て整数であることをチェックする
city_ids = ["13115", 13104, 0013112, nil]
city_ids.all? { |item| item.is_a?(Integer) } # => false
Q.全ての要素の桁数が5桁かどうかをチェックする
city_ids = ["13115", 13104, 0013112, nil]
city_ids.all? { |item| item.to_s.length == 5 } # => false
4. 含まれるデータを並び替える (sort, sort_by)
Q.今まで住んだことのあるCityをcity_idの昇順に並び替える
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を使用する
arr = [[13101, "千代田区", "chiyoda"], [13103, "港区", "minato"], [13105, "文京区", "bunkyo"]]
arr.sort_by{ |id, name, furigana| furigana }
=> [[13105, "文京区", "bunkyo"], [13101, "千代田区", "chiyoda"], [13103, "港区", "minato"]]
5. 配列と比較し、情報を追加する (map)
Q. City一覧がある配列に含まれるかどうかをチェックし、その結果をフラグで持つ。結果はハッシュで返す。
# 結果イメージ
[{:id=>13104, :name=>"新宿区", :lived_flg=>true}, #含まれる場合
{:id=>13102, :name=>"中央区", :lived_flg=>false}] #含まれない場合
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の使いどころや必要性が出てきたフェーズで改めて学ぶことでさらに身についてくる気がします!
実践でどしどし使えるよう、さらに学習を進めていきたいと思います〜(๑˃̵ᴗ˂̵)و