Upgrade to Pro — share decks privately, control downloads, hide ads and more …

如何使用 byebug 來除錯 Ruby 程式

Avatar for Johnlin Johnlin
August 02, 2020

如何使用 byebug 來除錯 Ruby 程式

Avatar for Johnlin

Johnlin

August 02, 2020
Tweet

More Decks by Johnlin

Other Decks in Programming

Transcript

  1. ᮫ԙզ • John Lin • Twitter: @johnlinvc • Senior Solution

    Architect, DevOps 
 @ West Pharmaceutical Service (୆ᖯҖ๏෰຿)
  2. ྖંၢ݊ coupon.rb def get_coupon(user_id, history) if history[user_id] = true return

    0 end history[user_id] = true 3000 end puts get_coupon(1, {}) Ṝछศᑍࢴཫ౎ੋఔࣜᛰ
  3. ྖંၢ݊ coupon.rb $ ruby coupon.rb 0 def get_coupon(user_id, history) if

    history[user_id] = true return 0 end history[user_id] = true 3000 end puts get_coupon(1, {}) Ṝछศᑍࢴཫ౎ੋఔࣜᛰ →৭ᐽཫੋbash/byebug ࿨༬ظෆಉɼጯ֘ཁ༌ग़ 3000
  4. ༻ puts ֬ೝఔࣜ။ෆ။ඃࣥߦ౸ def get_coupon(user_id, history) if history[user_id] = true

    return 0 end puts "here" history[user_id] = true 3000 end puts get_coupon(1, {}) ೗Ռ༗ࣥߦ౸Ṝཫब။༌ग़ here
  5. ༻ puts ֬ೝఔࣜ။ෆ။ඃࣥߦ౸ $ ruby coupon_here.rb 0 def get_coupon(user_id, history)

    if history[user_id] = true return 0 end puts "here" history[user_id] = true 3000 end puts get_coupon(1, {}) ೗Ռ༗ࣥߦ౸Ṝཫब။༌ग़ here ᔒ༗ hereɼ
 ॴҎᔒ༗ࣥߦ౸ਖ਼֬తҐஔ
  6. byebug • ໋ྩྻత Ruby আࡨثɻ • ࢖༻ TracePoint API ိሣ

    Ruby ఔࣜআࡨɻ • ࢧԉ MRI Ruby 2.4.0 Ҏ্ɻ ෆࢧԉ jruby, rubinius ౳ଖଞ Ruby ௚ᩄثɻ
  7. ࢖༻ byebug root@coscup:/app# byebug coupon.rb [1, 9] in /app/coupon.rb =>

    1: def get_coupon(user_id, history) 2: if history[user_id] = true 3: return 0 4: end 5: history[user_id] = true 6: 3000 7: end 8: 9: puts get_coupon(1, {}) (byebug)
  8. ᙘ໘ղ㘸 root@coscup:/app# byebug coupon.rb [1, 9] in /app/coupon.rb => 1:

    def get_coupon(user_id, history) 2: if history[user_id] = true 3: return 0 4: end 5: history[user_id] = true 6: 3000 7: end 8: 9: puts get_coupon(1, {}) (byebug) 䈕໊᪑ߦᏐൣᅴ
  9. ᙘ໘ղ㘸 root@coscup:/app# byebug coupon.rb [1, 9] in /app/coupon.rb => 1:

    def get_coupon(user_id, history) 2: if history[user_id] = true 3: return 0 4: end 5: history[user_id] = true 6: 3000 7: end 8: 9: puts get_coupon(1, {}) (byebug) ఔࣜᛰ࿨ߦᥒ
  10. ᙘ໘ղ㘸 root@coscup:/app# byebug coupon.rb [1, 9] in /app/coupon.rb => 1:

    def get_coupon(user_id, history) 2: if history[user_id] = true 3: return 0 4: end 5: history[user_id] = true 6: 3000 7: end 8: 9: puts get_coupon(1, {}) (byebug) ඪࣔ໨લ
 ఀࢭҐஔ
  11. ᙘ໘ղ㘸 root@coscup:/app# byebug coupon.rb [1, 9] in /app/coupon.rb => 1:

    def get_coupon(user_id, history) 2: if history[user_id] = true 3: return 0 4: end 5: history[user_id] = true 6: 3000 7: end 8: 9: puts get_coupon(1, {}) (byebug) prompt ɼඪࣔ䬟زߦੋզ၇༌ೖతࢦྩ
  12. ཭։ byebug [1, 9] in /app/coupon.rb => 1: def get_coupon(user_id,

    history) 2: if history[user_id] = true 3: return 0 4: end 5: history[user_id] = true 6: 3000 7: end 8: 9: puts get_coupon(1, {}) (byebug) quit Really quit? (y/n) y root@coscup:/app#
  13. help (byebug) help break -- Sets breakpoints in the source

    code catch -- Handles exception catchpoints condition -- Sets conditions on breakpoints continue -- Runs until program ends, hits a breakpoint or reaches a line debug -- Spawns a subdebugger delete -- Deletes breakpoints disable -- Disables breakpoints or displays display -- Evaluates expressions every time the debugger stops down -- Moves to a lower frame in the stack trace edit -- Edits source files enable -- Enables breakpoints or displays finish -- Runs the program until frame returns frame -- Moves to a frame in the call stack help -- Helps you using byebug history -- Shows byebug's history of commands info -- Shows several informations about the program being debugged interrupt -- Interrupts the program irb -- Starts an IRB session kill -- Sends a signal to the current process list -- Lists lines of source code method -- Shows methods of an object, class or module next -- Runs one or more lines of code pry -- Starts a Pry session quit -- Exits byebug restart -- Restarts the debugged program save -- Saves current byebug session to a file set -- Modifies byebug settings show -- Shows byebug settings skip -- Runs until the next breakpoint as long as it is different from the current one source -- Restores a previously saved byebug session step -- Steps into blocks or methods one or more times thread -- Commands to manipulate threads
  14. help • byebug ༗㚎ݐ㘸໌ࢦྩɻ • ࡏ prompt ༌ೖ help बՄҎ؃౸ࢦྩྻදɻ

    • ࡏ prompt ༌ೖ help <ࢦྩ> बՄҎ؃౸ࢦྩత㘸໌ɻ (byebug) help (byebug) help help
  15. h[elp] (byebug) help help h[elp][ <cmd>[ <subcmd>]] Helps you using

    byebug help -- prints a summary of all commands help <cmd> -- prints help on command <cmd> help <cmd> <subcmd> -- prints help on <cmd>'s subcommand <subcmd> [ ] 㚎త෦෼ੋબᎩੑతɼॴҎ໵ՄҎ୞ଧ h
  16. l[ist] • ؃ݱࡏࣥߦ౸䬟Ұߦࢦྩɻ။༌ग़ෟۙతزߦɻ (byebug) list [1, 9] in /app/coupon.rb =>

    1: def get_coupon(user_id, history) 2: if history[user_id] = true 3: return 0 4: end 5: history[user_id] = true 6: 3000 7: end 8: 9: puts get_coupon(1, {})
  17. b[reak] • ཁٻ byebug ࡏࣥߦ౸ࢦఆߦᏐલఀԼိɻఀԼိతҐஔɼ ላ໊ڣ၏ ”தᏗᴍ“
 • ໵ՄҎ༻؆ሜ b


    (byebug) break 2 Created breakpoint 1 at /app/coupon.rb:2 (byebug) b 3 Created breakpoint 3 at /app/coupon.rb:3
  18. ༻ byebug ֬ೝఔࣜ။ෆ။ඃࣥߦ౸ [1, 9] in /app/coupon.rb => 1: def

    get_coupon(user_id, history) 2: if history[user_id] = true 3: return 0 4: end 5: history[user_id] = true 6: 3000 7: end 8: 9: puts get_coupon(1, {}) (byebug) break 5 Created breakpoint 1 at /app/coupon.rb:5 (byebug) ૝֬ఆ။ࣥߦୈ 5 ߦ
  19. ༻ byebug ֬ೝఔࣜ။ෆ။ඃࣥߦ౸ [1, 9] in /app/coupon.rb => 1: def

    get_coupon(user_id, history) 2: if history[user_id] = true 3: return 0 4: end 5: history[user_id] = true 6: 3000 7: end 8: 9: puts get_coupon(1, {}) (byebug) break 5 Created breakpoint 1 at /app/coupon.rb:5 (byebug) ཁٻࡏࣥߦୈ 5 ߦ࣌ఀԼိ
  20. ༻ byebug ֬ೝఔࣜ။ෆ။ඃࣥߦ౸ [1, 9] in /app/coupon.rb => 1: def

    get_coupon(user_id, history) 2: if history[user_id] = true 3: return 0 4: end 5: history[user_id] = true 6: 3000 7: end 8: 9: puts get_coupon(1, {}) (byebug) break 5 Created breakpoint 1 at /app/coupon.rb:5 (byebug) continue ཁٻ៺᠃ࣥߦ
  21. ༻ byebug ֬ೝఔࣜ။ෆ။ඃࣥߦ౸ [1, 9] in /app/coupon.rb => 1: def

    get_coupon(user_id, history) 2: if history[user_id] = true 3: return 0 4: end 5: history[user_id] = true 6: 3000 7: end 8: 9: puts get_coupon(1, {}) (byebug) break 5 Created breakpoint 1 at /app/coupon.rb:5 (byebug) continue 0 root@coscup:/app# ᔒ༗ఀԼိब݁ଋྃɼॴҎୈ 5 ߦੋᔒ༗ࣥߦ౸తɻ
  22. [1, 9] in /app/coupon.rb 1: def get_coupon(user_id, history) => 2:

    if history[user_id] = true 3: return 0 4: end 5: history[user_id] = true 6: 3000 7: end 8: 9: puts get_coupon(1, {}) (byebug) next [1, 9] in /app/coupon.rb 1: def get_coupon(user_id, history) 2: if history[user_id] = true => 3: return 0 4: end ݱࡏࣥߦ౸ୈ 2 ߦ
  23. [1, 9] in /app/coupon.rb 1: def get_coupon(user_id, history) => 2:

    if history[user_id] = true 3: return 0 4: end 5: history[user_id] = true 6: 3000 7: end 8: 9: puts get_coupon(1, {}) (byebug) next [1, 9] in /app/coupon.rb 1: def get_coupon(user_id, history) 2: if history[user_id] = true => 3: return 0 4: end ࣥߦԼҰߦ
  24. [1, 9] in /app/coupon.rb 1: def get_coupon(user_id, history) => 2:

    if history[user_id] = true 3: return 0 4: end 5: history[user_id] = true 6: 3000 7: end 8: 9: puts get_coupon(1, {}) (byebug) next [1, 9] in /app/coupon.rb 1: def get_coupon(user_id, history) 2: if history[user_id] = true => 3: return 0 4: end ݱࡏࣥߦ౸ྃୈࡾߦ
  25. ෆੋ㑌ݸ஍ํ౎ೳதᏗ • ༗Ұࠣᔒ༗ࣥߦҙٛత஍ํੋෆೳதᏗతɻ૾ੋۭߦɼ end, {, }ɻ (byebug) break /app/coupon.rb:4 ***

    Line 4 is not a valid breakpoint in file /app/coupon.rb. Valid break points are: [B] 1: def get_coupon(user_id, history) [B] 2: if history[user_id] = true [B] 3: return 0 4: end ᔒ༗ඪ [B] తߦᏐແ๏தᏗ
  26. ࡏಛఆ৘گԼ break • ՄҎ୞༗ࡏಛఆత৘گԼ break • break [file:]line [if <expr>]


    (byebug) break 3 if history[user_id] Created breakpoint 5 at /app/coupon.rb:3
  27. ࡏ rails server ༻ byebug • rails 4.2 ೭ޙब༬ઃࡏ։ᚙ໛ࣜ҆᧋ byebug

    • ࡏ code ཫ࢖༻ byebug method ိࡏࣥߦఔࣜత࣌ީఀࡏ byebug ႔ɻ • ඇ rails తఔࣜ require 'byebug' ޙ໵Մ༻ byebug methodɻ • ෆա byebug method ෆࢉੋதᏗᴍɻ
  28. ࡏ rails ཫ࢖༻ byebug Started GET "/posts" for 127.0.0.1 at

    2020-08-01 12:18:37 +0000 Processing by PostsController#index as */* [3, 12] in /app/rails_example/app/controllers/ posts_controller.rb 3: 4: # GET /posts 5: # GET /posts.json 6: def index 7: byebug => 8: @posts = Post.all 9: end 10: 11: # GET /posts/1 12: # GET /posts/1.json (byebug) ။ఀࡏ byebug తԼҰߦ
  29. ࡏඇ rails ཫ࢖༻ byebug $ ruby coupon_byebug.rb [1, 10] in

    /app/coupon_byebug.rb 1: require 'byebug' 2: def get_coupon(user_id, history) 3: byebug => 4: if history[user_id] = true 5: return 0 6: end 7: history[user_id] = true 8: 3000 9: end 10: (byebug) ઌ require ࠽ೳ࢖༻ byebug
  30. ᑍ݅ࣜ byebug • code ཫత byebug बੋҰൠత ruby methodɻՄҎ์ࡏ೚ Կ஍ํɼ໵ՄҎ༻

    if ိઃఆᑍ݅ ɻ
 $ ruby coupon_byebug_cond.rb [1, 10] in /app/coupon_byebug_cond.rb 1: require 'byebug' 2: def get_coupon(user_id, history) 3: byebug if user_id == 1 => 4: if history[user_id] = true 5: return 0 ୞༗ᑍ݅ූ߹࣌࠽தᏗ
  31. ༻ puts ֬ೝᏓᏐతᆴ def get_coupon(user_id, history) if history[user_id] = true

    puts user_id puts history return 0 end history[user_id] = true 3000 end puts get_coupon(1, {}) $ ruby coupon_puts_val.rb 1 {1=>true} 0
  32. ༻ byebug ֬ೝᏓᏐతᆴ [1, 9] in /app/coupon.rb 1: def get_coupon(user_id,

    history) 2: if history[user_id] = true => 3: return 0 4: end 5: history[user_id] = true 6: 3000 7: end 8: 9: puts get_coupon(1, {}) (byebug) user_id 1
  33. [1, 9] in /app/coupon.rb 1: def get_coupon(user_id, history) 2: if

    history[user_id] = true => 3: return 0 4: end 5: history[user_id] = true 6: 3000 7: end 8: 9: puts get_coupon(1, {}) (byebug) history 1 help 2 help help 3 list
  34. [1, 9] in /app/coupon.rb 1: def get_coupon(user_id, history) 2: if

    history[user_id] = true => 3: return 0 4: end 5: history[user_id] = true 6: 3000 7: end 8: 9: puts get_coupon(1, {}) (byebug) history 1 help 2 help help 3 list
  35. ᙛ࿨㚎ݐࢦྩিಥ࣌ɼ ࢖༻ eval [1, 9] in /app/coupon.rb 1: def get_coupon(user_id,

    history) 2: if history[user_id] = true => 3: return 0 4: end 5: history[user_id] = true 6: 3000 7: end 8: 9: puts get_coupon(1, {}) (byebug) eval('history') {1=>true}
  36. v[ar] • v[ar] args ɿྻग़ method తჩᏐɻ • v[ar] c[onst]

    ɿྻग़ݱࡏ scope 㚎త constantɻ • v[ar] i[nstance] [object] ɿྻग़ object ҃ੋ self త ivarɻ • v[ar] l[ocal]ɿྻग़ॴ༗ local ᏓᏐɻ • v[ar] a[ll]ɿྻग़ local, global, instance ᏓᏐɻ
  37. [1, 9] in /app/coupon.rb 1: def get_coupon(user_id, history) 2: if

    history[user_id] = true => 3: return 0 4: end 5: history[user_id] = true 6: 3000 7: end 8: 9: puts get_coupon(1, {}) (byebug) var local history = {1=>true} user_id = 1
  38. ෆ୞᧺࡯ɼؐՄҎհೖ [1, 2] in /app/modify_var.rb => 1: a = 1

    2: puts "a is: #{a}" (byebug) n [1, 2] in /app/modify_var.rb 1: a = 1 => 2: puts "a is: #{a}" (byebug) a = 56 56 (byebug) c a is: 56 a = 1 puts "a is: #{a}"
  39. ༻ puts ፙᏓᏐඃमվతҐஔ def get_coupon(user_id, history) puts history if history[user_id]

    = true puts history return 0 end history[user_id] = true 3000 end puts get_coupon(1, {}) $ ruby coupon_puts_find.rb {} {1=>true} 0
  40. ༻ byebug ፙᏓᏐඃमվతҐஔ (byebug) display history 1: history = (undefined)

    (byebug) set linetrace linetrace is on (byebug) continue Tracing: /app/coupon.rb:9 puts get_coupon(1, {}) 1: history = (undefined) Tracing: /app/coupon.rb:2 if history[user_id] = true 1: history = {} Tracing: /app/coupon.rb:3 return 0 1: history = {1=>true}
  41. ༻ byebug ፙᏓᏐඃमվతҐஔ (byebug) display history 1: history = (undefined)

    (byebug) set linetrace linetrace is on (byebug) continue Tracing: /app/coupon.rb:9 puts get_coupon(1, {}) 1: history = (undefined) Tracing: /app/coupon.rb:2 if history[user_id] = true 1: history = {} Tracing: /app/coupon.rb:3 return 0 1: history = {1=>true}
  42. ༻ byebug ፙᏓᏐඃमվతҐஔ (byebug) display history 1: history = (undefined)

    (byebug) set linetrace linetrace is on (byebug) continue Tracing: /app/coupon.rb:9 puts get_coupon(1, {}) 1: history = (undefined) Tracing: /app/coupon.rb:2 if history[user_id] = true 1: history = {} Tracing: /app/coupon.rb:3 return 0 1: history = {1=>true}
  43. ༻ byebug ፙᏓᏐඃमվతҐஔ (byebug) display history 1: history = (undefined)

    (byebug) set linetrace linetrace is on (byebug) continue Tracing: /app/coupon.rb:9 puts get_coupon(1, {}) 1: history = (undefined) Tracing: /app/coupon.rb:2 if history[user_id] = true 1: history = {} Tracing: /app/coupon.rb:3 return 0 1: history = {1=>true}
  44. ༻ byebug ፙᏓᏐඃमվతҐஔ (byebug) display history 1: history = (undefined)

    (byebug) set linetrace linetrace is on (byebug) continue Tracing: /app/coupon.rb:9 puts get_coupon(1, {}) 1: history = (undefined) Tracing: /app/coupon.rb:2 if history[user_id] = true 1: history = {} Tracing: /app/coupon.rb:3 return 0 1: history = {1=>true}
  45. ౸ఈݺڣྃ䬟Ұஈఔࣜ? require_relative 'hidden_lib.rb' puts HiddenLib.new.hello("world") $ grep 'hello' hidden_lib.rb $

    ፙෆ౸ hello Ṝݸࣈ۲ʁʁ $ ruby method_caller.rb called hello with args: ["world"]
  46. ౸ఈݺڣྃ䬟Ұஈఔࣜ? # method_caller.rb require_relative 'hidden_lib.rb' puts HiddenLib.new.hello("world") $ grep 'hello'

    hidden_lib.rb $ ፙෆ౸ hello Ṝݸࣈ۲ʁʁ $ ruby method_caller.rb called hello with args: ["world"]
  47. class HiddenLib # hidden_lib.rb def method_missing(name, *args) "called #{name} with

    args: #{args.map(&:to_s)}" end end ౸ఈݺڣྃ䬟Ұஈఔࣜ? # method_caller.rb require_relative 'hidden_lib.rb' puts HiddenLib.new.hello("world") ׬શᔒ༗ hello Ṝݸࣈ۲ʂʂ $ ruby method_caller.rb called hello with args: ["world"]
  48. "ஶ໊"త method_missing • method_missing ੋᙛ object ඃݺڣෆଘࡏత method ɼब ။վҝݺڣṜݸ

    methodɻඃݺڣత method ໊᜝࿨ሏతჩ Ꮠ౎။ੋ method_missing తჩᏐɻ Ruby on Rails ࢖༻ྃ ෆগత method_missingɻ • obj.foo(a,b) => obj.method_missing(:foo, [a,b])
  49. class HiddenLib # hidden_lib.rb def method_missing(name, *args) "called #{name} with

    args: #{args.map(&:to_s)}" end end ༻ puts ፙඃݺڣతఔࣜ # method_caller.rb require_relative 'hidden_lib.rb' puts HiddenLib.new.hello("world")
  50. ༻ byebug ፙඃݺڣతఔࣜ [1, 3] in /app/method_caller.rb 1: require_relative 'hidden_lib.rb'

    2: => 3: puts HiddenLib.new.hello("world") (byebug) step [1, 5] in /app/hidden_lib.rb 1: class HiddenLib 2: def method_missing(name, *args) => 3: "called #{name} with args: #{args.map(&:to_s)}" 4: end 5: end (byebug)
  51. s[tep] [1, 3] in /app/method_caller.rb 1: require_relative 'hidden_lib.rb' 2: =>

    3: puts HiddenLib.new.hello("world") (byebug) step [1, 5] in /app/hidden_lib.rb 1: class HiddenLib 2: def method_missing(name, *args) => 3: "called #{name} with args: #{args.map(&:to_s)}" 4: end 5: end (byebug) • ᄸ㑊ࣥߦਐೖඃݺڣత methodɻ
  52. ༻ puts ፙݺڣ႔ $ ./framework (eval):1:in `<main>' ./framework:4:in `eval' ./framework:4:in

    `<main>' hello # my_code.rb def my_method puts caller_locations "hello" end
  53. ༻ byebug ፙݺڣ႔ ./framework [1, 5] in /app/my_code.rb 1: require

    'byebug' 2: def my_method 3: byebug => 4: "hello" 5: end (byebug) where
  54. ༻ byebug ፙݺڣ႔ ./framework [1, 5] in /app/my_code.rb 1: require

    'byebug' 2: def my_method 3: byebug => 4: "hello" 5: end (byebug) where
  55. ༻ byebug ፙݺڣ႔ ./framework [1, 5] in /app/my_code.rb 1: require

    'byebug' 2: def my_method 3: byebug => 4: "hello" 5: end (byebug) where
  56. w[here] • ᰖࣔ໨લత call stack ɼ0 ੋ໨લඃݺڣత methodɻᏐࣈ େతݺڣᏐࣈখతɻ ex:

    1 ݺڣ 0ɻ (byebug) where --> #0 Object.my_method at /app/my_code.rb:4 #1 <main> at /app/(eval):1 ͱ-- #2 Kernel.eval at /app/framework:4 #3 <main> at /app/framework:4
  57. bye ࢦྩখঞ • h[elp] [cmd] • q[uit] • l[ist] •

    b[reak] [file:]line [if expr] • c[ontinue] • n[ext] • v[ar] l[ocal] • s[tep] • disp[lay] expr • set linetrace • w[here]