Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

201810 study ruby_for_compass

263 views

Published on

2018/10 Connpass
【Ruby基礎】学習で躓きそうなポイント解説 資料

Published in: Engineering
  • Be the first to comment

  • Be the first to like this

201810 study ruby_for_compass

  1. 1. 【Ruby基礎】 学習で躓きそうなポイント解説 株式会社Rosso システムソリューション事業部 アプリケーション開発部 第二グループ 野村俊介
  2. 2. 構成 1.自己紹介 2.勉強会の目的 3.(ほぼ)すべてがオブジェクトっ てどういうこと? 4.selfって何ですか? >ひとことで言うと >クラスメソッドと インスタンスメソッド >クラスメソッドについて >特異メソッドについて 5.blockって何ですか? >ひとことで言うと >yieldとは >block、yieldを使うと、 何がうれしいのか。 6.ダックタイピング >コード解説 7.まとめ
  3. 3. 自己紹介
  4. 4. 自己紹介 名前: 野村俊介 エンジニア歴: 約7年半 これまでの経歴: javaを使ったWEBアプリ機能、画面開発など。 Prjの品質管理や構成管理などを経験。 Rubyを使った開発経験: 約10か月 ・某プロ野球球団向け、球団情報一元管理WEBシステム開発(4か月) ・某メーカー向け、品質管理システム開発(~現在)
  5. 5. 勉強会の目的
  6. 6. 勉強会の目的 Ruby初心者や勉強中の方の 学習のヒントになれば!
  7. 7. 目的(イメージ) self? block? オブジェクト? つまづきポイント 解説/ 実例 理解 次のステップ Ruby on Rails メタプログラミング etc...
  8. 8. (ほぼ)すべてがオブジェクトって どういうこと?
  9. 9. ・Rubyのオブジェクトとは ● Rubyではほぼすべてのデータはオブジェクト (クラスからできた実体)です。 ● なんのクラスに属しているかはRubyが自動で 判別します。 ※classもClass クラスのオブジェクトです。ただし、 メソッドとblockはオブジェクトではありません。
  10. 10. ・例 変数の中身によるクラスの違い 変数 a、b、c、dに様々な値を代入後、クラスを表示 <output>
  11. 11. ・例 変数の中身によるクラスの違い 変数 a、b、c、dに様々な値を代入後、クラスを表示 <output> Rubyが自動でクラスを判別!
  12. 12. ・例 クラスのクラスは? 前のスライドのOutputのクラスを調べる <output>
  13. 13. ・例 クラスのクラスは? 前のスライドのOutputのクラスを調べる <output> 各classはClassクラスのオブジェクト!
  14. 14. オブジェクトの中身を 見てみましょう!
  15. 15. 例 オブジェクトの中身を確認する 1/3 Kurasuクラスのオブジェクト「kurasu」の中身を確認! <output>
  16. 16. 例 オブジェクトの中身を確認する 2/3 kurasuオブジェクト
  17. 17. 例 オブジェクトの中身を確認する 2/3 kurasuオブジェクト 自分のクラスの参照情報
  18. 18. 例 オブジェクトの中身を確認する 2/3 kurasuオブジェクト インスタンス変数
  19. 19. 例 オブジェクトの中身を確認する 2/3 kurasuオブジェクト 自分のクラスの参照情報 インスタンス変数 オブジェクト=自分のクラスの参照情報 + インスタンス変数
  20. 20. 例 オブジェクトの中身を確認する 3/3 インスタンス変数は「ない」場合もある <output>
  21. 21. 例 オブジェクトの中身を確認する 3/3 インスタンス変数は「ない」場合もある <output> インスタンス変数がない! ⇒ my_methodが 呼び出されていないから
  22. 22. 例 オブジェクトの中身を確認する 3/3 インスタンス変数は「ない」場合もある <output> インスタンス変数がない! ⇒ my_methodが 呼び出されていないから では、メソッドはどこにあるのでしょうか?
  23. 23. ・例 メソッドはどこにあるのか kurasuオブジェクトが使えるメソッドを表示してみる <output>
  24. 24. ・例 メソッドはどこにあるのか kurasuオブジェクトが使えるメソッドを表示してみる <output> どこに持っているのか?
  25. 25. A.「クラス」が持っている!
  26. 26. オブジェクトとクラス、メソッドの関係はこのようになっています。 Kurasu my_method instance_of? public_send ・ ・ ・ クラス 持ってるメソッド
  27. 27. オブジェクトとクラス、メソッドの関係はこのようになっています。 Kurasu my_method instance_of? public_send ・ ・ ・ クラス 持ってるメソッド .new kurasu オブジェクト Kurasuへの参照情報
  28. 28. オブジェクトとクラス、メソッドの関係はこのようになっています。 Kurasu my_method instance_of? public_send ・ ・ ・ クラス 持ってるメソッド kurasu オブジェクト Kurasuへの参照情報
  29. 29. オブジェクトとクラス、メソッドの関係はこのようになっています。 Kurasu my_method instance_of? public_send ・ ・ ・ クラス 持ってるメソッド kurasu オブジェクト Kurasuへの参照情報 あるよ! def my_method @value = 2 end
  30. 30. オブジェクトとクラス、メソッドの関係はこのようになっています。 Kurasu my_method instance_of? public_send ・ ・ ・ クラス 持ってるメソッド kurasu オブジェクト Kurasuへの参照情報 あるよ! def my_method @value = 2 end @value = 2 荷物になるから 結果だけもらうわ
  31. 31. ここまでのまとめ ● オブジェクトは、なんらかのクラスに属する (Rubyが自動でクラスを判別) ● オブジェクトの中身は、 自クラスの参照情報 + インスタンス変数 ● メソッドはクラスが持っている ● オブジェクトは自分のクラスにメソッドを 問い合わせる
  32. 32. ・人間的には整数に見えても・・・ 人間的にはただの数字の「3」ですが、Rubyにとってはオブジェクト <output>
  33. 33. ・人間的には整数に見えても・・・ 人間的にはただの数字の「3」ですが、Rubyにとってはオブジェクト <output> 「3」はFixnumクラスの オブジェクト
  34. 34. 3 オブジェクト Fixnumへの参照情報 3.times do endの処理の流れ Integer times next to_i upto ・ ・ 親クラス 持ってるメソッド Fixnum % & between? to_s ・ ・ クラス 持ってるメソッド timesメソッド ある?
  35. 35. Fixnum % & between? to_s ・ ・ クラス 持ってるメソッド 3 オブジェクト Fixnumへの参照情報 3.times do endの処理の流れ timesメソッド ある? あるかな? Integer times next to_i upto ・ ・ 親クラス 持ってるメソッド 持って なかった!
  36. 36. Fixnum % & between? to_s ・ ・ クラス 持ってるメソッド 3 オブジェクト Fixnumへの参照情報 3.times do endの処理の流れ timesメソッド ある? Integer times next to_i upto ・ ・ 親クラス 持ってるメソッド timesメソッド ある?
  37. 37. Fixnum % & between? to_s ・ ・ クラス 持ってるメソッド 3 オブジェクト Fixnumへの参照情報 3.times do endの処理の流れ timesメソッド ある? Integer times next to_i upto ・ ・ 親クラス 持ってるメソッド timesメソッド ある? Helloが3回 表示された!
  38. 38. クラスを意識することで、メソッドチェインが可能です。 チェインしたメソッドは左から順番に処理され、メソッドの実行結果を オブジェクトとして次のメソッドが処理する流れになっています。 例 文字列を「_(アンダーバー)」で区切った最初の単語を大文字で出力する メソッドチェイン output
  39. 39. ・クイズ 例2では「undefined method 」エラーになります。 なぜエラーになるか分かりますか?
  40. 40. 例1の処理 ‘Hello_world’が String Classと認識される
  41. 41. 例1の処理 「hello_world」に対し、String Classのsplit メソッドに「_」が渡され実行される
  42. 42. 例1の処理 Splitメソッドの実行結果[hello, world]が Array Class で返る
  43. 43. 例1の処理 [hello, world](Array Class)に対して Array Classのfirstメソッドを 使い、先頭の’hello’を取り出す ここまでの実行結果 [hello, world](Array Class)
  44. 44. 例1の処理 ‘hello’(String Class)に対して String Classのupcaseメソッドを 実行、結果の’HELLO’が返る ここまでの実行結果 ‘hello’(String Class)
  45. 45. 例2の処理 Splitメソッドの実行結果[hello, world]が Array Class で返る (ここまでは例1と一緒)
  46. 46. 例2の処理 [hello, world](Array Class)に対して String Classのupcaseメソッドを 実行 実行結果[hello, world](Array Class)
  47. 47. 例2の処理 [hello, world](Array Class)に対して String Classのupcaseメソッドを 実行 Splitメソッドの実行結果[hello, world]が Array Class で返る (ここまでは例1と一緒) 実行結果[hello, world](Array Class) undefined method エラー >Array Classにupcase メソッドはないよ!
  48. 48. まとめ 1/2 ・Rubyではほぼすべてのデータはオブジェクト(クラスか らできた実体)。 >オブジェクトは、なんらかのクラスに属する(Rubyが自動でクラスを判別) >オブジェクトの中身は、自クラスの参照情報 + インスタンス変数 >メソッドはクラスが持っている (ほぼ)すべてがオブジェクトってどういうこと?
  49. 49. まとめ 2/2 ・オブジェクトだからこそ、クラスを意識することで メソッドチェインが可能! >まずは自分のClassにメソッドの有無を問い合わせ、なければ親クラス、 なければその親クラス・・・のようにさかのぼって問い合わせ (どのクラスにもメソッドがなければNo Method Error) >メソッドの実行結果もオブジェクト。結果のクラスに属しているメソッド なら追加でチェイン出来ます。 (ほぼ)すべてがオブジェクトってどういうこと?
  50. 50. selfって何ですか?
  51. 51. 「self」とは、 カレントオブジェクト。 ひとことで言うと。
  52. 52. カレントオブジェクトとは。 1.クラスやモジュールの定義の内側(メソッドの外側)では ⇒ クラスやモジュールそのものがself 2.メソッドを呼び出すときは ⇒ メソッドのレシーバがself
  53. 53. 呼び出す位置に応じたselfの例 1/2 クラスやモジュールの定義の内側(メソッドの外側)では ⇒ クラスやモジュールそのものがself MyClass が表示される MyModule が表示される
  54. 54. 呼び出す位置に応じたselfの例 2/2 メソッドを呼び出すときは ⇒ メソッドのレシーバがself <MyClass:0x00000001193100> (MyClassオブジェクト) が表示される ※レシーバとは・・・そのメソッドを 呼び出したオブジェクトのこと
  55. 55. ・「def self.メソッド名」のようなメソッド定義を見て、 ビビったご経験はありませんか? (私は現場に出てからもしばらく意味が解らず嫌でした(笑)) この記述はクラスメソッドと呼ばれています。 ・一方、self.がついていないメソッドは、インスタンスメソッドと 呼ばれます。 クラスメソッドとインスタンスメソッド
  56. 56. クラスメソッドとインスタンスメソッドの使用例 1/3 インスタンスメソッドを呼び出してみる 「インスタンスメソッド」 が表示される 「NoMethodError」 が表示される
  57. 57. クラスメソッドとインスタンスメソッドの使用例 2/3 クラスメソッドを呼び出してみる 「クラスメソッド」 が表示される 「NoMethodError」 が表示される
  58. 58. インスタンスメソッド ⇒ obj = MyClass.new obj.my_instance_method > MyClassクラスのオブジェクトから呼び出した クラスメソッド ⇒ MyClass.my_class_method > MyClassから直接呼び出した クラスメソッドとインスタンスメソッドの使用例 3/3 ように見えた 次のスライドでもう少し詳しく見てみましょう!
  59. 59. クラスメソッドについて 1/4 selfとは「カレントオブジェクト」でした。 左図の場合、 「Classクラスのオブジェクト」 を指しています。 定義したクラスは、Classクラスの オブジェクトでしたね。 「Class」が出力される クラスメソッドにおけるself
  60. 60. クラスメソッドについて 2/4 復習 <output> 各classはClassクラスのオブジェクト!
  61. 61. では左図の場合は、どうしてエラーになるので しょうか。 これは、「obj」が 「MyClassのオブジェクト」であり、 Classクラスのオブジェクトではないからです 。 クラスメソッドについて 3/4 エラーパターン No Method Error
  62. 62. selfとobj(MyClass.new)の継承関係の違いについてみてみます。 selfの継承関係 obj(MyClass.new)の継承関係 No Method Error オブジェクトが違うから 継承関係も違う クラスメソッドについて 4/4
  63. 63. もう少し詳しく流れを追うために、 「特異メソッド」について説明します。
  64. 64. 特異メソッドについて 1/2 ● Rubyの特異メソッドは、 ある特定のオブジェクトにのみ存在するメソッドです。 「def オブジェクト名.メソッド名」で定義できます。 ● 特異メソッドを定義する場所として、特異クラスが存在します。 (Rubyが裏で定義しています。) ● オブジェクトが特異メソッドを持っている場合、 Rubyは通常のクラスより先に、特異クラスのメソッドから探索します。
  65. 65. 特異メソッドについて 2/2 self.my_class_method生成の流れ(イメージ) MyClass クラス 持ってるメソッド self.my_class_method 定義 Class 親クラス Mod ule さら に親 Obj ect さら に親 Ker nel さら に親 ・・
  66. 66. 特異メソッドについて 2/2 self.my_class_method生成の流れ(イメージ) MyClass クラス 持ってるメソッド SingletonClass 特異クラス self.my_class_method 定義 Class 親クラス Mod ule さら に親 Obj ect さら に親 Ker nel さら に親 ・・ MyClassに紐づいた 特異クラスをRuby が裏で作成
  67. 67. SingletonClass 特異クラス 持ってるメソッド 特異メソッドについて 2/2 self.my_class_method生成の流れ(イメージ) MyClass クラス 持ってるメソッド Class 親クラス my_class_method インスタンスメソッド として定義 Mod ule さら に親 Obj ect さら に親 Ker nel さら に親 ・・
  68. 68. なぜ「obj.my_class_method」がエラーになったか MyClass オブジェクト MyClass 自分のクラス 持ってるメソッド Obj ect 親ク ラス Basic Object さらに親 Ker nel さら に親 self.my_class_ method ある?
  69. 69. なぜ「obj.my_class_method」がエラーになったか MyClass オブジェクト MyClass 自分のクラス Obj ect 親ク ラス Basic Object さらに親 Ker nel さら に親 特異クラスの中にあるので 存在しない 持ってるメソッド self.my_class_ method ある?
  70. 70. なぜ「obj.my_class_method」がエラーになったか MyClass オブジェクト MyClass 自分のクラス Obj ect 親ク ラス Basic Object さらに親 Ker nel さら に親 持ってるメソッド メソッド探索 self.my_class_ method ある?
  71. 71. なぜ「obj.my_class_method」がエラーになったか MyClass オブジェクト MyClass 自分のクラス 持ってるメソッド Obj ect 親ク ラス Basic Object さらに親 Ker nel さら に親 メソッド探索 self.my_class_ method ある? No Method Error!
  72. 72. クラスメソッドはどんな時に使うのか 1/2 クラスメソッドは「外部からデータを取得する場合」 に使用します。 そして、自身に関する情報の変更や参照をする役割 を担います。
  73. 73. クラスメソッドはどんな時に使うのか 2/2 例えば、以下のような処理に使われます。 ・DBからデータを読み出して新たにオブジェクトを作成する処理 ・ファイルからデータを読み出して、新たにオブジェクトを作成する処理 ・オブジェクトを参照して、新たにインスタンスを作成する処理 ・クラスアノテーションとして。 (attr_xxx 系の、クラス定義に直接記述する処理) 次のスライドで、実際にクラスメソッドを使ってDBのレコードを作成してみます 。
  74. 74. クラスメソッドを使ったDBのレコード作成の例 1/2 <やりたいこと> 読み込んだデータ配列をDBに登録したい。 すでにテーブルに存在していた場合はテーブルのレコードを取得し、 なければ登録する処理を実装する。DBには検索用カラムがあるので、入力データ 情報の有無はそれを使って検索する。 (Bookテーブルのbook_name_for_searchには、book_nameの小文字が入 る。)
  75. 75. クラスメソッドを使ったDBのレコード作成の例 2/2 <イメージ> No, Book, Value 1 , BOOK1, 2000 2 , BOOK2, 3000 3 , BOOK3, 3500 BOOKデータ配列 Bookテーブル id book_ name book_name_for _search value regist 検索用カラム (book_nameの 小文字が入る)
  76. 76. クラスメソッドを使ったDBのレコード作成の例 1/8 BookController Bookのクラスメソッドを 呼び出す bookレコードのカラム を配列に格納 データ 数分ル ープ
  77. 77. クラスメソッドを使ったDBのレコード作成の例 2/8 <メリット> ・可読性/保守性向上 >レシーバ側(今回はController)で、検索用カラムを意識することなく 引数を渡すことができる >小文字への変換は上記メソッドがやってくれるため、小文字変換の処理が レシーバ側に分散しない BookClass クラスメソッドを定義して find_or_initialize_byをラップ 引数(label)の小文字を カラムに格納
  78. 78. クラスメソッドを使ったDBのレコード作成の例 3/8 find_or_initilalize_byはRailsのメソッドで、引数の条件でそのテーブルを検索 し、あれば初期化、なければcreateします。 本来であれば「モデル名.find_or_initialize_by」のように使うため、 これも実はクラスメソッドです。 今回はselfメソッドの中で使っているため、特異クラスのインスタンスメソッド 扱いとなり、メソッド名単体で動作しています。 次のスライドでもう一度特異メソッドの動きを確認しましょう。 <参考 5行目について>
  79. 79. クラスメソッドを使ったDBのレコード作成の例 4/8 self.find_or_initialize_by_book_nameと self.find_or_initialize_by生成の流れ(イメージ) BOOK クラス 持ってるメソッド self.find_or_initialize_by_ book_name 定義 Class 親クラス
  80. 80. SingletonClass 特異クラス 持ってるメソッド BOOKに紐づいた特 異クラスをRubyが 裏で作成 クラスメソッドを使ったDBのレコード作成の例 4/8 self.find_or_initialize_by_book_nameと self.find_or_initialize_by生成の流れ(イメージ) BOOK クラス 持ってるメソッド self.find_or_initialize_by_ book_name 定義 Class 親クラス find_or_initialize_by 元々持ってる
  81. 81. SingletonClass 特異クラス 持ってるメソッド クラスメソッドを使ったDBのレコード作成の例 4/8 self.find_or_initialize_by_book_nameと self.find_or_initialize_by生成の流れ(イメージ) BOOK クラス 持ってるメソッド Class 親クラス find_or_initialize_by_ book_name インスタンスメソッド として定義 find_or_initialize_by
  82. 82. クラスメソッドを使ったDBのレコード作成の例 5/8 クラスメソッド内でのメソッド探索 self (BOOK) オブジェクト SingletonClass 特異クラス 持ってるメソッド find_or_initialize_by_ book_name find_or_initialize_by Hit! Hit!
  83. 83. クラスメソッドを使ったDBのレコード作成の例 6/8 デバッグして「self」を表示してみる self=Book (カレントオブ ジェクト) self(=Book)は Classクラスのオブジェク ト
  84. 84. クラスメソッドを使ったDBのレコード作成の例 7/8 Rubyのメソッドは最後に実行された処理の結果が戻り値となるので、 今回はControllerにBookレコードが返ります。 find_or_initialize_byの実行 Bookレコード ができた!
  85. 85. クラスメソッドを使ったDBのレコード作成の例 8/8 取得したBookレコード (new_or_exists_book) に対して残りのカラムを 入れれば完成 Controllerに戻る 各カラムに値が 入った!
  86. 86. selfって何ですか? まとめ 1/2 ・「self」とは、 カレントオブジェクトのこと! >クラスやモジュールの定義の内側 (メソッドの外側)では、クラスやモジュールそのもの! >メソッドを呼び出すときは、メソッドのレシーバがself! ・「def self.メソッド名」の定義 = クラスメソッド > selfがついていないメソッド = インスタンスメソッド
  87. 87. selfって何ですか? まとめ 2/2 ・クラスメソッドは、Classクラスの特異メソッド! >あるクラスが特異メソッドを持っている場合、 通常のクラスより先に、特異クラスから探索されます。 >DBからの読出しやファイルからの読出しなど、 外部からデータを取得する場合に使われます。
  88. 88. blockって何ですか?
  89. 89. ひとことで言うと。 「block」とは、 処理のこと。
  90. 90. 処理とは do end の中身、{}(波かっこ)の中身を指します。 処理
  91. 91. blockの特徴 ・単体では実行できません。 オブジェクトでもありません。 ・blockの中で定義した変数は、そのblockの中でしか 使えません。 ・引数としてメソッドに渡すことが可能! ⇒ yieldを使って渡した処理が実行できます。
  92. 92. yieldとは 受け取ったblockを実行するためのコードです。 このコードが出てきたら、レシーバ側のblockを見ることで、 何をやっているか確認することができます。
  93. 93. block、yieldを使うと、何がうれしいのか。 ・使用したい側で、好きなように振る舞いを決められます ・blockを実行したいコードに紐づけられた束縛 (ローカル変数、インスタンス変数、selfなど)も 一緒に連れていけます 実際にコードを見てみましょう。
  94. 94. Blockの活用例 1/5 STUDY_BLOCKクラスの@array は、外部から隠蔽されています。 この@arrayの中身を外部から取得 したいとします。 yieldを記述しておく
  95. 95. Blockの活用例 2/5 使いたい人たちは、@arrayに対してやりたい処理をdo_blockメソッドの引数 として伝えます。 中身を小文字にし て表示したい! 中身にインデックスを つけて表示したい!
  96. 96. Blockの活用例 3/5 それぞれの指示は、yieldのタイミングで実行されています。 yieldの引数の「val」は@arrayの中身です。 Input: 中身を小文字で出力したい Output: @arrayの中身を小文字で出力
  97. 97. Blockの活用例 4/5 レシーバ側で定義した変数も連れて行っています。 Input: 中身にindexをつけて表示したい Output: @arrayの中身をindex付きで出力 「i」はレシーバのローカル変数
  98. 98. Blockの活用例 5/5 参考書等では @arrayに対してattr_reader を使って取り出すと書いてあると思います 。 ですが、レシーバ側に@arrayの情報を一度 全て持たせてしまうことになります。 ・単に全部取得するのか、 ・内容を加工したものが欲しいのか 状況に合わせてプログラミングすることが 、品質向上に繋がると思います。 <参考> attr_readerを使う ここで無駄に全部取得 してしまう! やりたいこと(データの 小文字の表示)はできる
  99. 99. blockって何ですか? まとめ 1/2 ・blockは、「処理」です。 > {}(波括弧)、do endの中のコード、および束縛(ローカル変数、 インスタンス変数、selfなど)をまとめたものです。 (block単体では存在できません。) > メソッドに引数として渡すことができます。 ・yieldとは、受け取ったblockを実行するための コードです。
  100. 100. blockって何ですか? まとめ 2/2 ・block、yieldを使うことで、使用者が使いたいものを自 由に加工することができます。 > blockを使いこなすことで、データの隠蔽はそのままに、 内容だけを加工して取得するといった柔軟なプログラミングが 可能になります。
  101. 101. ダックタイピング
  102. 102. ダックタイピングとは 「アヒルのように歩いてアヒルのように鳴けば、それはアヒルに違いない。」 Rubyは動的言語です。 オブジェクトの「型」とクラスは厳密に結びついておらず、「型」はオブジェクト が反応するメソッドの集合です。 つまり、あるオブジェクトがDuckクラスのインスタンスかどうかを気にせず(通 常のメソッドだろうが特異メソッドだろうが)walk(歩く)とquack(鳴く)に反応 するかだけ気にすればよいのです。 次のスライドから、ダックタイピングの例を紹介します。
  103. 103. <やりたいこと> ● 2つのファイルから読み込んだデータ配列をDBに登録 したい。 ● 配列に対応したテーブルが存在している。 ● ファイルは何度も読み込まれるため、 各DBカラムに同名データがない場合のみ登録する。
  104. 104. <やりたいこと イメージ> No, Team, Dir_file_path 1 , team1, aaa/bbb/ccc 2 , team2, ddd/eee/fff 3 , team3, ggg/hhh/iii team_vs_dir_file_path_map Teamテーブル id team_label regist DirFilePathテーブル id dir_file_path_label Modified_Fileテーブル id file_name No, Dir_file_path, file 1 , jjj/kkk/llll, file_1 2 , mmm/nnn/ooo, file_2 3 , ppp/qqq/rrr, file_3 dir_file_path_vs_file_map regist
  105. 105. 何も考えずに実装した場合 1/3 team_vs_dir_file_path_map_controller ファイルから配列 を取得する処理は 割愛 Teamレコードと DirFilePathレコード を取得 Teamレコードと DirFilePathレコード を取得 登録
  106. 106. 何も考えずに実装した場合 2/3 dir_file_path_vs_file_map_controller Arrayのデータと取 得対象のモデル以外 は同じ処理
  107. 107. 何も考えずに実装した場合 3/3 今回のコントローラーは「登録させる」ことが目的ですが、 レコードの所得の部分の処理が無駄に責任を負ってしまっています。 可読性を上げるために、 create_recordsというメソッドを新たに定義し、共通化しようと思います。 問題点 一旦レコードを作成 してから登録して いる
  108. 108. ダックタイピングを活かした実装 1/9 CreateRecordCommonモジュール app/controller/concerns配下に共通処理「create_record」を作成します。 この中でレコードの取得とsaveを一度に行います。 注目!!
  109. 109. ダックタイピングを活かした実装 2/9 CreateRecordCommonモジュール 8行目に注目してください。 メソッドの引数として取得したmodel、Targetを使って、 find_or_initialize_by メソッドを動的に制御しています。 次にレシーバ(Cotroller)側を確認してみます。 可変可変
  110. 110. ダックタイピングを活かした実装 3/9 team_vs_dir_file_path_map2_controller 1/2 必要な データだけ を抽出
  111. 111. ダックタイピングを活かした実装 4/9 team_vs_dir_file_path_map2_controller 2/2 14行目のcreate_recordの引数は以下のようになっています。 引数1 ⇒ teamラベルのみが入った配列 引数2 ⇒ Teamクラス 引数3 ⇒ DBカラム名(team_label) ※ハードコードを避けるために Modelで定数として定義 ➡ 16行目も同様に、DirFilePathモデル向けに引数を与えています。
  112. 112. ダックタイピングを活かした実装 5/9 create_recordの動作確認 1/3 デバッグしてみます。Teamに対するcreate_recordの内容を追います。 上記、14行目からcreate_recordに入ります。
  113. 113. ダックタイピングを活かした実装 6/9 create_recordの動作確認 2/3 8行目でそれぞれの値を見てみます。 引数が渡されて いる!
  114. 114. ダックタイピングを活かした実装 7/9 create_recordの動作確認 3/3 肝心のレコード作成はどうでしょうか? ちゃんと作成できています。
  115. 115. ダックタイピングを活かした実装 8/9 上記のように、レシーバ側で引数を変えることで、find_or_initialize_byが 動的に実行できます。 このように、メソッドが反応するように補完してあげるだけで、 ダックタイピングが実現できます! ダックタイピングのポイント Team team_label Teamレコード DirFilePath dir_file_path_label DirFilePath レコード
  116. 116. ダックタイピングを活かした実装 9/9 参考までにこちらも載せておきます。 dir_file_path_vs_file_map2_controller Tableが増えた場合も create_recordを流用 できるため、 メンテナンスしやすい
  117. 117. ダックタイピング ● ダックタイピングとは、オブジェクトをメソッドに 補完するテクニック ● コードの重複を避けることができ、メンテナンス性が 向上する! ※ただし、むりやり共通化するのは可読性が下がるので やめましょう。 まとめ
  118. 118. まとめ
  119. 119. 今回のテーマは、私自身がRubyを勉強していた時に今一つイメージがつかめず、 ネットで調べても例が乏しくメリットが解らなかったものを集めてみました。 今回挙げた例の多くは、実際の現場で使っているものにアレンジを加えたもの なので、これらの内容を理解する ⇒ 実務を想定したイメージがわく ⇒ Rubyの理解に繋がる! という流れになればよいと思いました。 Rubyはプログラマーの自由度を優先した言語なので、書いていてストレスが 少なく、楽しい言語です。 また、RubyやRuby on Railsを採用した案件は、魅力的な案件が多いです! 勉強は大変だと思いますが頑張ってください! 一人でも多くのRubiest(Rubyプログラマ)が誕生し、 Ruby言語がより一層盛り上がることを祈っております。
  120. 120. ご清聴ありがとうございました。
  121. 121. 参考資料 ■特異メソッド、特異クラスとクラスメソッドの関係について https://qiita.com/fujishin05/items/be60f4f788f2732921a4 ■インスタンスメソッドとクラスメソッドはどのようにして使い分けるべきか?(Rubyの場合) https://blog.mah-lab.com/2014/11/13/instance-method-and-class-method-with-ruby/ ■Rubyの動かないコード (初級編) ブロックとクロージャの性質 http://language-and-engineering.hatenablog.jp/entry/20101118/p1 ■メタプログラミングRuby 第2版 オライリー・ジャパン ■オブジェクト指向設計実践ガイド Rubyでわかる進化しつづける柔軟なアプリケーションの育て方 技術評論社

×