FactoryBotが「Failure/Error: config.include FactoryBot::Syntax::Methods」で読み込めなかった話
Rails4からRails5にアップデートをする際、重要ロジックのテストを書いていないことに気づいた。
そこで、改めてRSpecを使おうと思いいろいろ調べている中で、テストデータ作成ツールに FactoryBot
を利用することに。
しかし、いくら試せど下記のようなエラーが・・・。
Failure/Error: config.include FactoryBot::Syntax::Methods NameError: uninitialized constant FactoryBot # ./spec/rails_helper.rb:63:in `block in <top (required)>' # ./spec/rails_helper.rb:33:in `<top (required)>' # ./spec/services/xxxxxxs/xxxxxx_service_spec.rb:1:in `require' # ./spec/services/xxxxxxs/xxxxxx_service_spec.rb:1:in `<top (required)>' No examples found. Finished in 0.00052 seconds (files took 12.32 seconds to load) 0 examples, 0 failures, 1 error occurred outside of examples
原因は、Gemfileの定義で下記に様にしていたから笑
group :development do # テスト関連 gem "rspec-rails" # rspec本体 gem "factory_bot_rails" # テストデータ作成 end
rails_helper.rbでは
ENV['RAILS_ENV'] ||= 'test'
としているため
group :test do # テスト関連 gem "rspec-rails" # rspec本体 gem "factory_bot_rails" # テストデータ作成 end
が正解。
しょぼいことでハマって疲れた笑
ScalaとRubyのコレクションで使える.mapについてちょっと調べてみた
突然ですが
先日、後輩くんがこんな実装をしました。
_nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] _divisible = _nums.select{ |n| n % 2 == 0 } p _divisible # [2, 4, 6, 8, 10] _multiplied = _divisible.map {|n| n * 100 } p _multiplied # [200, 400, 600, 800, 1000]
実際はプロダクト上に実装したコードと少し違いますが、要件としては「コレクションの中から該当するものだけにしぼり、処理を施して新しいコレクションにする」という感じです。
さらにこれを「select」と「map」をつなげ、最終的には下記のような形となりました。
_nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] _multiplied = _nums.select{ |n| n % 2 == 0 }.map {|n| n * 100 } p _multiplied # [200, 400, 600, 800, 1000]
実は私、2年ほど前までScalaを書いていたのですが、上記のような書き方で結構実装した覚えがあります。
Scalaについて
Scala(スカラ(SKAH-lah[1])はオブジェクト指向言語と関数型言語の特徴を統合したマルチパラダイムのプログラミング言語である。 引用:Wikipedia - Scala
独学で2年、業務で2年ほどScalaを書いていた私ですが、詳しいScalaについてのお話はなるべく避けていきます・・・笑
ですが、例えば上記のコードをScalaで実装すると、こんな感じになるかと思います。
val nums = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) val multiplied = nums.filter { n => n % 2 == 0 }.map { n => n * 100 } multiplied.map(println)
どうでしょう?
ほぼ同じ様に書けるんですよね。
Scalaの場合はパターンマッチというのがmapの関数内部に適用出来ますので、例えばこんな感じに書けます。
val nums = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) val multiplied = nums.map { case n if n % 2 == 0 => Some(n * 100) case _ => None }.flatten multiplied.map(println)
SomeとNoneはOption型というものでして、値がある場合Some、ない場合はNoneという子のオブジェクトで表現することにより、nullを徹底的に排除したプログラミングが出来るといったものです。※表現間違っていたらスミマセン
最後にOption型のコレクションに対して.flattenすると、Noneの要素が排除され、Someの要素が残り期待する結果が取得できます。
まあ、実際このような書き方をするのであれば、最後に書いたcollectメソッドを使います。
まとめ
Rubyを書きはじめた当初はあまり興味のなかった私ですが、こういった様にScalaと同じ様にプログラミング出来るのが意外でして、最近ではRubyも楽しいと感じるようになりました。
RubyのArray.mapの実装
さて、ここからは完全に余談です。
気になったのでRubyのArray.mapの実装を見てみました。
多分下記だと思っているのですが・・・スミマセン、github上でざっと見た感じですので憶測も含んでます!
https://github.com/ruby/ruby/blob/trunk/array.c#L2730-L2763
簡単に説明させていただくと、対象のArray内要素の件数分forでループし、同じく指定したブロック処理(rb_yield_force_blockargで、.map{ |n| ここの箇所 })を実行して新しいArray(コレクション)に詰めて返却するというもののようです。
一報、Scalaの.mapは、例えばcollection/immutable/List.scalaで見ることが出来ます。
簡単に解説すると、要素の先頭から順に受け取った関数(.map(A => B))に渡して処理を実行する感じですかね。
ちょっと詳しく説明しだすと終わらない気がするのでこの辺で・・・笑
collectと言えば・・・
さらに余談ですが、RubyのArray.mapはcollectの別名なんですね。
https://github.com/ruby/ruby/blob/trunk/array.c#L6449
実はScalaにもcollectというメソッドがありまして、先述の例題を実装しなおすと
val nums = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) val multiplied = nums.collect { case n if n % 2 == 0 => n * 100 } multiplied.map(println)
と書くことが出来ます。
どうでしょう?記述量がぐっと減ったように感じませんか?
家で作業スペースを作った話
最近奥さんと相談しまして、家でも作業できるように「ぼくがかんがえたさいきょうの家作業スペース」を作りました!
デスクは奥さんが好きなメープル色の、120cm☓70cmの幅があるローデスクです。
ディスプレイはLGの27UK850で、付属のTYPE-CポートをMBPにつなげるだけで、MBPに電源を供給できるというスグレモノです。こちらはなんといただきもの。ありがとうございます。
つなげるとこんな感じですね。
作業をしてみましたが、これだけでもなかなかの空間です。
ですが、やはり物足りないものがあります。
そう、それはキーボード。
板前さんが使う包丁の用に、エンジニアである僕にも大好きなキーボードがあります。
それがコレ。Happy Hacking Keyboard(HHKB)です。
会社で使っているものですが、ちょっと厚みがあるので都度家に持って変えるのは大変なのです。
はい、家用に買ってしまいました笑
家用のHHKBは黒色です。クールですね。
もちろん無刻印(英文字)です。
とても気に入っております。
さらに、家の作業スペースがある場所はWi-Fiが届きにくいため、中継機というものを購入。電波はバリ3に(し語)
iPadも脇において、なんか出来る人風に見えます。(見えるだけ)
少し殺風景なので、昔どこかの雑貨屋さんで購入した猫の置物をおいてみます。
名前はまだありません。
ちなみに中身はろうそく。
火はつけたことありませんが、どうやら口から火を吹く作りですね(違)
そんなわけで、やっと家でも会社の環境と遜色のない作業スペースを作ることが出来ました!
会社の僕のデスクと見比べても、ほとんど同じような環境になりました。
家で作業していても、結構はかどります。
そして、PS4も配置し、ディスプレイにガッチャンコワールド笑
結構仕事頑張っていて、なかなかドラクエ11がクリア出来ませんが、自分だけのスペースというのは良いものですね。
Slimで動的にスタイルを変更するメモ
.row style=(@this.id == @that.id ? "background-color: #ff9800" : "")
いっつも忘れるのでメモ。
classでも良い的な。