{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## 10-4 イベントをフックする\n", "### 10-4-1 モジュールがincludeやextendされたときのフック" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "3\n" ] }, { "data": { "text/plain": [ "[IncludeClass1, IncludeClass2, IncludeClass3]" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "module IncludedCount\n", " class << self\n", " def included(klass)\n", " @included ||= []\n", " @included << klass\n", " end\n", " \n", " def included_module_and_class\n", " @included\n", " end\n", " \n", " def included_count\n", " @included&.count || 0\n", " end\n", " end\n", "end\n", "\n", "p IncludedCount.included_count\n", "\n", "class IncludeClass1\n", " include IncludedCount\n", "end\n", "\n", "class IncludeClass2\n", " include IncludedCount\n", "end\n", "\n", "class IncludeClass3\n", " include IncludedCount\n", "end\n", "\n", "p IncludedCount.included_count\n", "\n", "IncludedCount.included_module_and_class" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 10-4-2 継承されたときのフック" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "クラス定義式の前\n", "[InheritedTimingSubClass, InheritedTiming, Object, JSON::Ext::Generator::GeneratorMethods::Object, Kernel, BasicObject]\n", "true\n", "false\n", "クラス定義式の後\n", "true\n" ] }, { "data": { "text/plain": [ "true" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "class InheritedTiming\n", " class << self\n", " private\n", " \n", " def inherited(subclass)\n", " p subclass.ancestors\n", " p subclass.instance_methods.include? :super_method\n", " p subclass.instance_methods.include? :subclass_method\n", " end\n", " end\n", " \n", " def super_method\n", " end\n", "end\n", "\n", "puts \"クラス定義式の前\"\n", "\n", "class InheritedTimingSubClass < InheritedTiming\n", " puts \"クラス定義式の後\"\n", " \n", " def subclass_method\n", " end\n", "end\n", "\n", "p InheritedTimingSubClass.instance_methods.include? :super_method\n", "InheritedTimingSubClass.instance_methods.include? :subclass_method" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 10-4-3 メソッドに対して操作が行われたときのフック\n", "■メソッドが追加されたら処理をしたい" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "method added: after_added_method\n", "method added: add_from_define_method\n", "method added: add_from_class_eval\n" ] }, { "data": { "text/plain": [ ":add_from_class_eval" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "class AddedMethodClass\n", " def before_added_method; end\n", " \n", " class << self\n", " private\n", " def method_added(method_name)\n", " puts \"method added: #{method_name}\"\n", " end\n", " end\n", " \n", " def after_added_method; end\n", " define_method :add_from_define_method, ->(){}\n", "end\n", "\n", "AddedMethodClass.class_eval do\n", " def add_from_class_eval; end\n", "end" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "rescued\n", "succeeded\n" ] } ], "source": [ "class BrokenMethodClass\n", " class << self\n", " private\n", " def method_added(method_name)\n", " raise \"Wow!\"\n", " end\n", " end\n", " \n", " def after_added_method\n", " puts \"succeeded\"\n", " end\n", "rescue\n", " puts \"rescued\"\n", "end\n", "\n", "BrokenMethodClass.new.after_added_method" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`method_added` はメソッド定義の後に実行される" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "第一部完!\n", "次回以降は Part4 から読みたい節をピックアップして読む" ] } ], "metadata": { "kernelspec": { "display_name": "Ruby 2.7.1", "language": "ruby", "name": "ruby" }, "language_info": { "file_extension": ".rb", "mimetype": "application/x-ruby", "name": "ruby", "version": "2.7.1" } }, "nbformat": 4, "nbformat_minor": 4 }