Ruby Gemsはどう動くのか?CanCanを例に仕組みを徹底解説
Railsでの開発が快適な理由のひとつは、認可(authorization)、サイト管理、EC機能など、よくあるプログラミングのニーズに対して、あなたより賢い誰かがすでに解決策をコード化し、gemとしてパッケージ化してくれている点にあります。
もちろん、Gemfileにgemを追加すれば、内部の仕組みを深く理解しなくてもその恩恵を受けられます。しかし、「一体どうやって組み込まれているのだろう?」と疑問に思ったことはありませんか?
ここでは、Ryan Bates氏作の認可用gem「CanCan」を例に、以下の3つの質問に答えていきます。これらは視点を広げれば、あらゆるgemに共通して当てはまる問いです。
CanCanのコードはどこに保存されているのか?
can?メソッドはどこで定義されているのか?Railsはいつ・どこで・どのようにgemのコードを読み込むのか?
1. gemのコードはどこにある?
まず、GemfileにCanCanを記述し、bundle installを実行します。
# Gemfile
gem "cancan", "~> 1.6.10"
$ bundle install
Bundlerを使えば、特定のgemがどこにインストールされているかを簡単に確認できます。bundle showコマンドを使うだけです。
$ bundle show cancan
/Users/jasonswett/.rvm/gems/ruby-2.0.0-p0/gems/cancan-1.6.10
これで質問1は解決です。続いて、can?メソッドがどこで定義されているのかを見ていきましょう。
2. can?メソッドはどこで定義されている?
$ cd /Users/jasonswett/.rvm/gems/ruby-2.0.0-p0/gems/cancan-1.6.10
$ grep -r 'def can?' *
lib/cancan/ability.rb: def can?(action, subject, *extra_args)
lib/cancan/controller_additions.rb: def can?(*args)
実はcan?という名前のメソッドは2つ存在します。今回注目したいのは、lib/cancan/ability.rbに定義されている方です。
# lib/cancan/ability.rb
def can?(action, subject, *extra_args)
match = relevant_rules_for_match(action, subject).detect do |rule|
rule.matches_conditions?(action, subject, extra_args)
end
match ? match.base_behavior : false
end
このコードの細かい動作については深入りしませんが、重要なポイントはそこではありません。大切なのは、gemで何か問題にぶつかったとき、今やあなたはgemのソースコードを直接掘り下げて、何が起きているのかを調査できるようになった、という点です。
3. Railsはいつ・どのようにgemを読み込むのか?
gemのコードの保存場所と調べ方がわかったところで、次は「Railsはどうやってgemの存在を認識し、いつコードを読み込むのか」という疑問です。
これについては、Railsの初期化プロセスに関する公式ドキュメントの該当セクションに説明があります。関連する部分を抜粋しましょう。
標準的なRailsアプリケーションには、アプリケーションの依存関係をすべて宣言するGemfileが存在します。config/boot.rbはENV['BUNDLE_GEMFILE']にこのファイルの場所を設定します。Gemfileが存在する場合、bundler/setupがrequireされます。
この処理は、初期化プロセスのごく早い段階——正確には2番目のステップ——で行われます。これは理にかなっています。プロジェクトが特定のgemに依存している場合、そのコードがどこから参照されるか事前にはわかりません。だからこそ、できるだけ早い段階で読み込んでおけば、アプリケーションのどこからでもgemのコードを利用できるようになるのです。
-
AASM Gemで学ぶRubyステートマシン入門|Stateデザインパターンから実践的な使い方まで
今回は、ステートマシン(状態遷移マシン)の仕組みと、RubyプロジェクトでAASM gemを使ってステートマシンを活用する方法を解説します。 まずは身近な例から考えてみましょう。 信号機を想像してください。信号機は「赤」「黄」「青」のいずれかの状態を取ります。 そして、色が変わるとき、次に何色になるかは現在の色によって決まっています。 ここでは、視覚障害のある方が渡れるタイミングを音で知らせるタイプの信号機だとしましょう。 さて、ここからが本題です。 あなたがこの信号機のソフトウェアを開発することになったとします。 毎回どの音を鳴らすべきか、次はどの色に変わるべきか——それをどう判断すればよ
-
Ruby 2.6のMJITとは?仕組みとパフォーマンスを徹底解説
Rubyのパフォーマンスは、バージョンが上がるごとに大きく向上してきました。そしてRuby開発チームは、さらに速いRubyを実現するために全力を尽くしています。 その取り組みのひとつが「3×3プロジェクト」です。 その目標とは? Ruby 3.0を、Ruby 2.0の3倍速くすることです。 このプロジェクトの一環として誕生したのが、新しいMJITコンパイラです。これが本記事のテーマとなります。 MJITとは何か MJITは「Method Based Just-in-Time Compiler(メソッドベースのジャストインタイムコンパイラ)」の略称です。 これは具体的にどういう意味でしょうか?