やわらかテック

興味のあること。業務を通して得られた発見。個人的に試してみたことをアウトプットしています🍵

Ruby

Rails Discussionに投稿したら返信が来てgithubにIssueを作成した

早いもので一年も折り返し...。東海地方もいよいよ梅雨入りしてジメジメした季節になりました。 先日、cache_storeの設定に環境変数を指定してInterger型に変換しないと、キャッシュの書き込み時にエラーが出るという現象を確認しました。この振る舞いに疑問…

Rails Discussionに投稿をしてみた

「今年こそは...今年こそは...OSSに貢献するぞ...!」と思い気づけはや3年。 気持ちだけが先行して何をしたら良いのか分からず。結局、それらしいことは何もしていませんでした。 ですが、先日開催されたRubykaigi2023(コロナになって行けなかったけど)へ参…

PostgreSQLでboolean型のカラムを持つレコードを取得するとt, fとなる

Rubyでpg gemを使って、postgresqlに接続してクエリの実行結果を見ていたところ、boolean型のカラムの戻り値がTRUEの場合にt、FALSEの場合にfとなる現象を確認しました。 CREATE TABLE test1 (a boolean, b text); INSERT INTO test1 VALUES (TRUE, 'sic est…

binding.irbでdebugコマンドが使えないのはirbのバージョンが古いため

僕はRubyで何かしら開発をする時にbinding.pryというデバッグツールを愛用してきました。 Rubyを書き始めたのが確か、2.3系の頃で当時からbinding.pryは非常に人気のデバッグツールでした。 しかし、Rubyのバージョンアップにつれてbinding.irbが標準gemとな…

ファイルをオープン(open)したらクローズ(close)しないといけない理由について

僕がプログラミングを始めたばかりの頃、よく「ファイルをクローズし忘れてるよ」と指摘されていました。 当時は「ファイルはオープンしたらクローズするもの...」と反射的にファイルをクローズするようにしていました。しかし、今になって思うと「なぜオー…

【Ruby】なぜeach関数よりもfor inが遅いのか

先日、以下の記事を公開しました。 www.okb-shelf.work Rubyで配列からハッシュを作る際に、どの方法が一番パフォーマンスが良いのかを計測したのですが、過去にJavaScriptで似たような計測をした時はシンプルなfor文が最速だったので、Rubyでも同じような結…

【Ruby】配列からハッシュを生成する4つの方法と速度比較

Rubyで開発をしていると配列からハッシュ(連想配列)を生成するコードを書くことがあります。 個人的にはreduce関数を使ってバシッと書くのが気持ちよくて好きなのですが、最近、人によってこの処理の書き方が違うことに気づきました。 4つの書き方 僕が個人…

Rspec+Railsを使ったconcernの単体テストの書き方

Railsの開発にてmodelやcontrollerの共通処理をconcernとして切り出すことはよくあるパターンです。 modelやcontrollerはクラス(class)として表現するものの、concernはActiveSupport::Concernをextendしたモジュール(module)として定義する必要があります。…

Class.new内部の関数定義へ変数を受け渡す方法について

Rspecでモックを作りたくて動的なクラスをClass.newで生成していた時のことです。 関数で受け取った配列を.mapで処理していたところ、do |student|で定義したブロック変数がClass.new内部に定義した関数のスコープ外になるという現象に遭遇しました。 def cr…

無名ブロック(anonymous block)によってRuboCopがコケるようになった

2023年3月31日をもってRuby2.7がEOL(EndOfLife)となりました。安らかにお眠りください...🪦 Ruby | endoflife.date 業務でRubyを触り始めたのが、ちょうど2.3~2.7系の時だったので感慨深いものがあります。 Ruby2.7のEOLに伴って、プロダクトのレポジトリ内でR…

mastdonからServiceクラスの作り方を学ぶ

みなさんはRailsの開発にて、サービスクラス(ServiceObject)を使っているでしょうか。 モデルやコントローラーがファットになるのを防ぐために導入される設計方法で、ドメイン知識におけるサービス(eg: 商品の購入処理)の一連の処理をまとめたクラスを作成す…

トランザクションがあれば安心ではないのでRailsでもロックをかけたい

Railsでトランザクションを扱いたい時はActiveRecordに実装されたtransactionメソッドを呼び出します。 ActiveRecord::Base::transaction do : end 今までRailsでトランザクションのブロックを宣言した時は、他のトランザクションからデータの取得、更新は出…

Rubyで巨大な配列を扱う時はEnumeratorを使うのが良さそう

先日、Rubyで巨大な配列(Array)を扱うことがありました。 気になるのは巨大な配列を宣言したときのメモリ使用量です。試しに、要素数が10,000個の配列を宣言してみると89,712Byteほどメモリを使用していることが分かります。 require 'objspace' # memsize_o…

オレオレRspecを自作して覚えるRubyのブロック引数について

Rubyのブロック引数についてご存じでしょうか。 非常に便利な機能で皆さんもよく使っている、正確にはブロック引数に対してブロックを渡していますが、ブロック引数を定義する機会がほとんどない方も多いでしょう。 例: eachの場合 # do以降の処理がブロック…

【Ruby】boolean型の値を渡すだけの関数にはキーワード引数を付与してあげよう

ある日のこと。Rubyのコードを読んでいるとboolean型の値が引数となる関数の呼び出し処理を見て「なんじゃこりゃ...」という気持ちになりました。簡単な例を紹介します。 def say_hello(is_morning) if is_morning puts 'おはようございます' else puts 'こ…

「RubyでつくるRuby」を読んだら簡単なRubyインタプリタが作れた

「RubyでつくるRuby ゼロから学ぶなおすプログラミング言語入門」を読了しました。 非常にチャレンジングな本で、なんとRuby初心者の方に向けてRubyを動かすプログラム、つまりRubyインタプリタを作ってみようという本です。「え、そんなのプログラミング初…

【Ruby】配列が特定の要素を含むかを判定するならany?ではなくinclude?を使うべし

ある日のこと。Rubyのコードを読んでいると配列の要素が特定の値を含んでいるかどうかの判定にinclude?を使っている箇所とany?を使っている箇所があることに気づきました。 lst = [1,2,3,4,5] puts lst.any?(1) # true puts lst.include?(1) # true たしかに…

【ええな〜コード】作って学ぶRailsのenumの仕組みについて

Railsを使っていて何かと便利なのが「enum」です。 他の言語では列挙型(Enumerable)と呼ばれることがありますが、実態としてはActiveRecordに定義されたenumという関数です。modelファイルの中でカラム値のバリエーションを指定することが出来るのが非常に便…

【ええな〜コード】OSSのコードから学ぶ設定値(configure)の作り方

こちらは「ええな〜コード」の記念すべき第一本目の記事です。「ええな〜コード」とはOSSのコードから勉強・参考になる箇所を抜粋して、記事として紹介するという趣旨の不定期シリーズです。 今回はよくある設定値(configure)について「ええな〜」と思うコー…

【ActiveRecord】レコード数を取得するにはlengthやcountではなくsizeを使っておけば良さそう

単体テストのコードを見ていて、対象のテーブルに存在するレコード数を取得する際の記述が統一されていないことを発見しました。ある箇所ではUser.all.sizeと記述されており、ある箇所ではUser.countと記述されており、どの方法で取得するのが効率が良いのか…

idの絞り込みにfindを使わずfind_by!を使っていたのはなぜなのか

コードレビューをしていていた日のこと。あるテーブル(users)からidで絞り込んでレコードを1件取得する際に、以下のようなコードが頻出していることに気づきました。 User.find_by!(id: params[:user_id]) 処理の内容としては、idカラムでusersテーブルから…

Rspecのモック(double)はどのように作られているのか

普段の業務でrspecのモック機能には非常にお世話になっています。使い方は非常に簡単で、既存クラスに定義された関数の振る舞いを変更することが出来ます。 (※実際に既存クラスの定義が書き変わるわけではありません) class Hoge def foo 'foo!' end def bar…

ActiveRecordにてSELECT * FROM table_nameを避ける方法について

ActiveRecordって本当に便利ですよね。SQLを隠蔽して、データベースへのCRUD操作をオブジェクトとメソッドで完結させることが出来ます。一例として、usersテーブルから権限(authority)がadminのレコード一覧を取得する操作は以下のようになります。 (※分かり…

ActiveSupportのtravel_toの仕組みについて

ActiveSupportには、時間を固定することが可能な便利なtravel_toという関数があります(よく単体テストでお世話になっています)。travel_toを呼び出した後にTime.nowで現在時刻を取得してみると、何とtravel_toで指定した日時が取得されるではありませんか。 …

Rails外でActiveSupportのtravel_toが使えない時の解決方法

前提条件 Rails外でActiveSupportを使用している テストフレームワークにRspecを使用している エラーについて Railsではなくsinatraを使ったAPIを書いていて、時間停止の便利関数travel_toを呼び出そうと思ったら以下のようなエラーが出てActiveSupportに定…

OSSのコードを読んでたらコードの書き方が変わった

最近はRubyとRubyOnRailsを使って仕事をしています。RubyやRailsは日本語の情報量が特に多く、やりたいことの多くはGoogleで調べると既に誰かがやっていたり、ライブラリがあったりと誰かが作ったありがたい...コードを使わせて頂くことがよくあります。 し…

特に意味のないデフォルト引数が保守性を低下させるので注意

機能追加の依頼がきた いつものように業務をこなしていると、スケジュール管理機能にとある機能追加の依頼が来ました。 内容としては複数のスケジュールを作成する関数で祝日での場合には、祝日に該当する日にはスケジュールを作成しないようにしたいとのこ…

動的型付け言語(Ruby)でも関数の戻り値の型は可能な限り統一した方が良い

出会いは突然に いつものように眠い目を擦りながらコードレビューをしていると以下のようなコードに遭遇しました。 (※部分的に書き換えてあるので、実際には動作していないコードです) def fetch_companies(setting_id) setting = Setting.find_by(id: setti…

Rubyのコードレビューでよく指摘すること

コードレビューはじめました 昨年の10月から勤務先企業で開発チームのリーダーになりました。元々はコードをガリガリ書くような業務をしていたのですが、ポジションが変わったため、業務の内容も変化しました。大きく変化した点としてコードをレビューしても…