ruby 代码调试_用撬调试Ruby代码

ruby 代码调试

Your comprehensive guide to Pry and how to use it .

有关Pry及其使用方法的综合指南。

Every programmer has faced a situation where they go to execute their code and get an error message they’re confused by, or even worse, the code runs successfully but nothing is output. This was me, and before I learned about Pry I would do things like combing through my code, line by line, trying to guess where the error could be. I even had a phase of inserting puts statements (puts “The error is here!”) hoping to figure out where the error was originating from. Once I learned about Pry, I never looked back. I truly believe it is one of the most important tools for beginning Ruby programmers.

每个程序员都面临着这样一种情况,他们去执行代码并收到错误消息,令他们感到困惑,甚至更糟的是,代码成功运行,但没有任何输出。 这就是我,在我了解Pry之前,我会做一些事情,例如逐行梳理我的代码,试图猜测错误可能在哪里。 我什至有一个插入puts语句的阶段(puts“错误在这里!”),希望弄清楚错误的起源。 一旦了解了Pry,我就再也没有回头。 我真的相信它是初学者Ruby程序员最重要的工具之一。

什么是撬? (What is Pry?)

Pry is a REPL (Read, Evaluate, Print, Loop) that pauses your code wherever inserted and allows you to test/debug. When your code gets to the ‘pry’ it will freeze and your terminal will turn into a REPL right in the middle of your program.

Pry是一种REPL(读取,评估,打印,循环),可在插入位置处暂停代码,并允许您进行测试/调试。 当您的代码进入“撬”状态时,它将冻结,并且您的终端将在程序中间变成REPL。

如何使用Pry? (How do I use Pry?)

The first step is to make sure you have the pry gem installed by typing the following into your terminal:

第一步是通过在终端中键入以下内容来确保您已安装了pry gem:

gem install pry

Once it’s installed, you will have to require it at the top of any file you plan on using it in like so:

安装之后,您将需要在计划使用它的任何文件的顶部都需要它,如下所示:

# test.rb
require 'pry'

Now it's time to actually install a pry break into your code using the following snippet: binding.pry

现在是时候使用以下代码片段在代码中实际安装撬破了: binding. pry binding. pry

Let’s create a file called ‘practice.rb’ and insert the following code into it:

让我们创建一个名为“ practice.rb”的文件,并将以下代码插入其中:

require 'pry'def my_fancy_method
inside_method = "We are now inside the method."
puts inside_method
pry_coming = "We are about to see how pry works!" binding.pry frozen = "Pry froze the program before it got to this point!"
puts frozenend
my_fancy_method

Now, when you call “my_fancy_method” before the code finishes fully executing, it will run into the “binding.pry” and kick out into the REPL before it gets to the end. Inside the REPL, you will have everything that was defined before binding.pry, but not anything afterwards. Your terminal should look something like this:

现在,当您在代码完成完全执行之前调用“ my_fancy_method”时,它将遇到“绑定”。 ”并在REPL结束之前踢入REPL。 在REPL内部,您将拥有在binding.pry之前定义的所有内容,但之后没有任何内容。 您的终端应如下所示:

3: def my_fancy_method4:     inside_method = "We are now inside the method."
5
: puts inside_method6: pry_coming = "We are about to see how pry works!"=> 7: binding.pry8: frozen = "Pry froze the program before it got to this point!"
9
: puts frozen10: end[1] pry(main)>

At the bottoms you will see the pry(main)> prompt indicating you are currently inside the pry REPL. Let’s test it out. Since the variable inside_method was defined before binding.pry, it should be known to Pry.

在底部,您会看到pry(main)>提示,表明您当前在pry REPL内部。 让我们测试一下。 由于变量inner_method是在binding.pry之前定义的,因此Pry应该知道它。

[1] pry(main)> inside_method=> "We are now inside the method."[2] pry(main)>

It worked!! Now, lets try calling the variable frozen which isn’t defined until after the binding.pry on line 8:

有效!! 现在,让我们尝试调用直到绑定之后才定义的冻结变量。 撬起第8行:

[[1] pry(main)> inside_method=> "We are now inside the method."[2] pry(main)> frozenNameError: undefined local variable or method `frozen' for main:Object

It doesn’t know what frozen is, because as far as its concerned it hasn’t gotten to that definition yet so it does not exist. Make sense?

它不知道冻结是什么,因为就其相关而言,它尚未达到该定义,因此它不存在。 合理?

[3] pry(main)> exitPry froze the program before it got to this point!

When you type ‘exit’ to leave Pry, it will continue executing the rest of the code, as seen here.

当您键入“ exit”离开Pry时,它将继续执行其余代码,如此处所示。

使用撬来调试 (Using Pry to Debug)

Ok. Now that we understand how to install, and use pry, we’ll see how it helps us debug code. Here are the most common uses of Pry for me so far in my early journey through the coding world.

好。 现在我们了解了如何安装和使用pry,我们将看到它如何帮助我们调试代码。 到目前为止,这是我在编码世界的早期旅程中最常用的Pry用法。

用例#1:检查变量 (Use Case #1: Checking Variables)

One common mistake for early coders is improperly assigning values to variables. For example, let's say you had the following code:

早期编码人员的一个常见错误是不正确地将值分配给变量。 例如,假设您有以下代码:

require 'pry'def simple_cubing_tool(number)
number * number * number
puts "The answer is #{number}!"end
simple_cubing_tool(4)

It takes in an integer as an argument and multiplies it times itself 3 times. Then it returns a statement giving you your number cubed. Now in a simple case like this you may see the problem already, but let’s take a look at when we run our method with the input of 4.

它接受一个整数作为参数,并将其自身乘以3倍。 然后,它返回一条语句,为您提供您的数字立方。 现在,在这样的简单情况下,您可能已经看到问题了,但是让我们看一下在输入4的情况下运行方法的情况。

// ♥ > ruby practice.rb
The answer is 4!

4?? But 4 cubed is 64 not 4. Lets see what happened by using Pry:

4 ?? 但是4的立方是64而不是4。让我们看看使用Pry发生了什么:

require 'pry'def simple_cubing_tool(number)
number * number * number
binding.pry puts "The answer is #{number}!"end
simple_cubing_tool(4)3: def simple_cubing_tool(number)4: number * number * number
=> 5: binding.pry6: puts "The answer is #{number}!"
7
: end[1] pry(main)> number
=> 4

If we type number into pry, even after line four: (number * number * number) has been executed, we see the value of number is still 4. Oops! we forgot to assign number*number*number value to a variable. How do we fix this?

如果我们将数字键入pry,即使执行了第四行:(数字*数字*数字),我们也会看到number的值仍然是4。糟糕! 我们忘记为变量分配数字*数字*数字值。 我们该如何解决?

require 'pry'def simple_cubing_tool(number)
num_cubed = number * number * number
puts "The answer is #{num_cubed}!"end

Ok now lets run it again.

现在,让我们再次运行它。

// ♥ > ruby practice.rb
The answer is 64!

Perfect! Now you see how to use Pry to check the value of variables at different stages of your program.

完善! 现在,您将了解如何使用Pry在程序的不同阶段检查变量的值。

用例2:查看您在嵌套哈希/数组中的位置 (Use Case #2: Seeing where you are in a nested Hash/Array)

Let’s say we have an array of hashes (AOH) defined as follows:

假设我们有一个散列(AOH)数组,定义如下:

nested = [
{:fruit => {
:apple => 1,
:banana => 2,
:grape => 6
},
:pets => {
:fido => "dog",
:whiskers => "cat",
:charles => "mouse",
:bitey => "snake"
},
:teams => {
:new_york => {
:baseball => ["mets", "yankees"],
:basketball =>["knicks", "nets"],
:football => ["giants", "jets"],
:hockey => ["rangers", "islanders"]
},
:los_angeles => {
:baseball => ["dodgers", "angels"],
:basketball =>["lakers", "clippers"],
:football => ["rams", "chargers"],
:hockey => ["kings"]
},
:chicago => {
:baseball => ["cubs"],
:basketball => ["bulls"],
:football => ["bears"],
:hockey => ["blackhawks"]
}
}
}
]

Our goal here is to iterate through this hash and return all of the basketball teams for each city in the form of:

我们的目标是遍历该哈希值,并以以下形式返回每个城市的所有篮球队:

“The basketball teams for (city name) are (basketball team names).”

“(城市名称)的篮球队是(篮球队名称)。”

Now, this may seem complicated, but using our friend Pry, we should be able to take this step by step.

现在,这似乎很复杂,但是使用我们的朋友Pry,我们应该能够逐步进行此操作。

def list_basketball_teams_by_city
nested.each do |element|
element.each do |outer_key, outer_value|
binding.pryendendend
list_basketball_teams_by_city// ♥ > ruby practice.rbTraceback (most recent call last):
5: from practice.rb:45:in `<main>'
4: from practice.rb:37:in `list_basketball_teams_by_city'
3: from practice.rb:37:in `each'
2: from practice.rb:38:in `block in list_basketball_teams_by_city'
1: from practice.rb:38:in `each'practice.rb:39:in `block (2 levels) in list_basketball_teams_by_city': undefined method `pry' for #<Binding:0x00007faadd86ecc0> (NoMethodError)

When we run this code we get a NoMethodError — undefined method ‘pry’… hmm..

当我们运行这段代码时,我们得到一个NoMethodError —未定义的方法“撬”……嗯。

Oops! we forgot to require ‘pry’ at the top of our code!!!! (I actually made this mistake while writing this so figured I would keep it in)

糟糕! 我们忘记在代码顶部要求“撬” !!!! (我在写这篇文章时实际上犯了这个错误,以至于我会坚持下去)

require 'pry'def list_basketball_teams_by_city
nested.each do |element|
element.each do |outer_key, outer_value|
binding.pryendendend
list_basketball_teams_by_city// ♥ > ruby practice.rbFrom: /Users/sean.laflam/Development/code/mod1/practice.rb:41 Object#list_basketball_teams_by_city:38: def list_basketball_teams_by_city(array)39: array.each do |element|40: element.each do |outer_key, outer_value|
=> 41: binding.pry42: end43: end44: end[1] pry(main)>

Much better!! Now based on our code, we can see we are two levels into our nested hash array, and on the first loop of each. We can confirm this by plugging outer_key and outer_value into our pry terminal:

好多了!! 现在基于我们的代码,我们可以看到我们处于嵌套哈希数组的两个级别中,并且每个级别都位于第一个循环中。 我们可以通过将outer_key和outer_value插入我们的撬终端来确认这一点:

[1] pry(main)> outer_key=> :fruit[2] pry(main)> outer_value=> {:apple=>1, :banana=>2, :grape=>6}

Good, but we still need some work. We won’t get to the :teams hash until the 3rd loop of our inner each loop and then we still need to dive in 2 levels deeper to return the array of baseball team names. Let’s keep going and add some logic. (Remember: use “exit!” to back all the way out of PRY)

很好,但是我们仍然需要一些工作。 在内部每个循环的第3个循环之前,我们不会进入:teams哈希,然后我们仍然需要更深入2个级别来返回棒球队的名称数组。 让我们继续并添加一些逻辑。 ( 请记住 :使用“退出!”一路退回PRY)

def list_basketball_teams_by_city(array)
array.each do |element|
element.each do |outer_key, outer_value|
if outer_key == :teams
outer_value.each do |city, sports_hash|
binding.pryendendendendend38: def list_basketball_teams_by_city(array)39: array.each do |element|40: element.each do |outer_key, outer_value|41: if outer_key == :teams42: outer_value.each do |city, sports_hash|
=> 43: binding.pry44: end45: end46: end47: end48: end

We should now be inside of the :teams hash and on the first iteration of our cities hash within :teams which would be :new_york.

现在,我们应该在:teams哈希值内,并且在我们的城市哈希的第一次迭代中:teams内将是:new_york。

We can check this again with pry by entering “city” and “sports_hash” into PRY.

我们可以通过在PRY中输入“ city”和“ sports_hash”再次使用pry进行检查。

[1] pry(main)> sports_hash=> {:baseball=>["mets", "yankees"],:basketball=>["knicks", "nets"],:football=>["giants", "jets"],:hockey=>["rangers", "islanders"]}[2] pry(main)> city=> :new_york

Looks good! We’re getting close to the desired output! Lets bring it home.

看起来挺好的! 我们正在接近所需的输出! 让它带回家。

require 'pry'def list_basketball_teams_by_city(array)
array.each do |element|
element.each do |outer_key, outer_value|
if outer_key == :teams
outer_value.each do |city, sports_hash|
sports_hash.each do |sport, team_name_array|
if sport == :baseball
puts "The basketball teams for #{city} are #{sport}."
end
end
end
end
end
end
endlist_basketball_teams_by_city(nested)// ♥ > ruby practice.rbThe basketball teams for New York are baseball.The basketball teams for Los Angeles are baseball.The basketball teams for Chicago are baseball.

Oh no!! So close but something is wrong. Lets use pry to figure out what happened.

不好了!! 如此接近,但出了点问题。 让我们用撬动找出发生了什么。

if sport == :baseball
binding.pry
puts "The basketball teams for #{city} are #{sport}."
end38: def list_basketball_teams_by_city(array)39: array.each do |element|40: element.each do |outer_key, outer_value|41: if outer_key == :teams42: outer_value.each do |city, sports_hash|43: sports_hash.each do |sport, team_name_array|44: if sport == :baseball
=> 45: binding.pry46: puts "The basketball teams for #{city} are #{sport
47
: end48: end49: end50: end51: end52: end53: end[1] pry(main)> sport=> :baseball[2] pry(main)> team_name_array=> ["mets", "yankees"][3] pry(main)>

There are a couple of errors here. If we check the sport it returns :baseball, but we’re looking for basketball teams for each city. The error is on line 44 in our if statement, where we say if sport ==:baseball instead of :basketball.

这里有几个错误。 如果我们检查这项运动,它将返回:baseball,但我们正在寻找每个城市的篮球队。 错误出现在if语句的第44行,我们在其中说if sport ==:baseball而不是:basketball。

Then, we returned the wrong variable in our puts statement. We want to return the array of basketball team names for that city, which is defined as “team_name_array” yet we entered puts The basketball teams for #{city} are #{sport}.

然后,我们在puts语句中返回了错误的变量。 我们要返回该城市的篮球队名称数组,定义为“ team_name_array”,但我们输入了 #{city}的篮球队是#{sport}。

Here is the final debugged code with these corrections added:

这是添加了这些更正的最终调试代码:

require 'pry'def list_basketball_teams_by_city(array)
array.each do |element|
element.each do |outer_key, outer_value|
if outer_key == :teams
outer_value.each do |city, sports_hash|
sports_hash.each do |sport, team_name_array|
if sport == :basketball
puts "The basketball teams for #{city} are #{team_name_array}."
end
end
end
end
end
end
endlist_basketball_teams_by_city(nested)
// ♥ > ruby practice.rbThe basketball teams for New York are ["knicks", "nets"].The basketball teams for Los Angeles are ["lakers", "clippers"].The basketball teams for Chicago are ["bulls"].~/.../code/mod1 // ♥ >

You can work on this code even further to make the output “prettier” but as you can see, Pry was extremely helpful in helping us get to the correct output.

您可以进一步处理此代码,以使输出“更漂亮”,但是如您所见,Pry在帮助我们获得正确的输出方面非常有帮助。

用例#3:您需要调试代码的其他地方!!! (Use Case #3: Anywhere else you need to debug your Code!!!)

You can use Pry in any application that you seem fit where you need to debug errors in your code. Now that you’re a Pry wizard get out there and test it on your own!

您可以在需要调试代码错误的任何似乎合适的应用程序中使用Pry。 既然您是Pry向导,请出去亲自进行测试!

翻译自: https://medium.com/@laflamablanc/debugging-ruby-code-with-pry-a0bf1f5e97ca

ruby 代码调试

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值