{ "cells": [ { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# 7-3 method_missing" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "ename": "NoMethodError", "evalue": "undefined method `no_method' for main:Object", "output_type": "error", "traceback": [ "\u001b[31mNoMethodError\u001b[0m: undefined method `no_method' for main:Object", "\u001b[37m(pry):1:in `
'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:387:in `eval'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:387:in `evaluate_ruby'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:355:in `handle_line'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:274:in `block (2 levels) in eval'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:273:in `catch'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:273:in `block in eval'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:272:in `catch'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:272:in `eval'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/lib/iruby/backend.rb:66:in `eval'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/lib/iruby/backend.rb:12:in `eval'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/lib/iruby/kernel.rb:87:in `execute_request'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/lib/iruby/kernel.rb:47:in `dispatch'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/lib/iruby/kernel.rb:37:in `run'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/lib/iruby/command.rb:70:in `run_kernel'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/lib/iruby/command.rb:34:in `run'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/bin/iruby:5:in `'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/bin/iruby:23:in `load'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/bin/iruby:23:in `
'\u001b[0m" ] } ], "source": [ "no_method()" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "# BasicObject#method_missingのコードはうまく動かなかったのでスキップ" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "# Kernel.#caller の `.#` はモジュール関数?" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ " # 7-3-2 method_missingの使い方" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ ":initialize" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "class DelegateArray\n", " def initialize\n", " @array = []\n", " end\n", "end" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "ename": "NoMethodError", "evalue": "undefined method `<<' for #", "output_type": "error", "traceback": [ "\u001b[31mNoMethodError\u001b[0m: undefined method `<<' for #", "\u001b[37m(pry):14:in `
'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:387:in `eval'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:387:in `evaluate_ruby'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:355:in `handle_line'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:274:in `block (2 levels) in eval'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:273:in `catch'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:273:in `block in eval'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:272:in `catch'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:272:in `eval'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/lib/iruby/backend.rb:66:in `eval'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/lib/iruby/backend.rb:12:in `eval'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/lib/iruby/kernel.rb:87:in `execute_request'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/lib/iruby/kernel.rb:47:in `dispatch'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/lib/iruby/kernel.rb:37:in `run'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/lib/iruby/command.rb:70:in `run_kernel'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/lib/iruby/command.rb:34:in `run'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/bin/iruby:5:in `'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/bin/iruby:23:in `load'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/bin/iruby:23:in `
'\u001b[0m" ] } ], "source": [ "delegate_array = DelegateArray.new\n", "delegate_array << 1" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ ":method_missing" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "class DelegateArray\n", " def method_missing(name, *args)\n", " @array.__send__ name, *args\n", " end\n", "end" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1]" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "delegate_array << 1" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2]" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "delegate_array << 2" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "# 7-3-3 注意点" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ ":method_missing" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "class LoopMethodMissingClass\n", " def method_missing(name, *args)\n", " __send__(name)\n", " end\n", "end\n", "\n", "# LoopMethodMissingClass.new.no_method # 無限ループ!" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ ":method_missing" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "class OverrideMethodMissing\n", " def method_missing(method_name, *args)\n", " if method_name == :target_method\n", " return 'target_method is called'\n", " end\n", " \n", " super\n", " end\n", "end" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "ename": "NoMethodError", "evalue": "undefined method `no_method' for #", "output_type": "error", "traceback": [ "\u001b[31mNoMethodError\u001b[0m: undefined method `no_method' for #", "\u001b[37m(pry):36:in `method_missing'\u001b[0m", "\u001b[37m(pry):39:in `
'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:387:in `eval'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:387:in `evaluate_ruby'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:355:in `handle_line'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:274:in `block (2 levels) in eval'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:273:in `catch'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:273:in `block in eval'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:272:in `catch'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/pry-0.12.2/lib/pry/pry_instance.rb:272:in `eval'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/lib/iruby/backend.rb:66:in `eval'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/lib/iruby/backend.rb:12:in `eval'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/lib/iruby/kernel.rb:87:in `execute_request'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/lib/iruby/kernel.rb:47:in `dispatch'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/lib/iruby/kernel.rb:37:in `run'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/lib/iruby/command.rb:70:in `run_kernel'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/lib/iruby/command.rb:34:in `run'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/gems/iruby-0.3/bin/iruby:5:in `'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/bin/iruby:23:in `load'\u001b[0m", "\u001b[37m/home/jovyan/.gem/ruby/2.6.0/bin/iruby:23:in `
'\u001b[0m" ] } ], "source": [ "OverrideMethodMissing.new.no_method" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "\"target_method is called\"" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "OverrideMethodMissing.new.target_method" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# railsでmethod_missingが使われているところ\n", "# https://github.com/rails/rails/blob/607d77ab073581172a66b26e2807790cd723719e/activerecord/lib/active_record/relation/delegation.rb#L103-L110" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/plain": [ ":method_missing" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# ActiveSupport#StringInquirer の method_missing\n", "class StringInquirer < String\n", " def method_missing(method_name, *arguments)\n", " if method_name[-1] == \"?\"\n", " self == method_name[0..-2]\n", " else\n", " super\n", " end\n", " end\n", "end" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "true\n", "false\n" ] } ], "source": [ "string = StringInquirer.new(\"foo\")\n", "puts string.foo?\n", "puts string.bar?" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [], "source": [ "# 次回は7-4 evalから" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Ruby 2.6.2", "language": "ruby", "name": "ruby" }, "language_info": { "file_extension": ".rb", "mimetype": "application/x-ruby", "name": "ruby", "version": "2.6.2" } }, "nbformat": 4, "nbformat_minor": 2 }