Ruby 循环,输出正在重复
我是编程新手,实际上知道我的代码有什么问题,但我不知道如何解决它!我编写了一个演示代码:Ruby 循环,输出正在重复,ruby,Ruby,我是编程新手,实际上知道我的代码有什么问题,但我不知道如何解决它!我编写了一个演示代码: def pass1 @user = 'Kras' @pass = 'zim' @country = 'DE' end def pass2 @user = 'Hanna' @pass = 'Ooma' end def print puts @user end [pass1,pass2].each do print end 输出: Hanna Hanna 我的输出
def pass1
@user = 'Kras'
@pass = 'zim'
@country = 'DE'
end
def pass2
@user = 'Hanna'
@pass = 'Ooma'
end
def print
puts @user
end
[pass1,pass2].each do
print
end
输出:
Hanna
Hanna
我的输出应该是:
Kras
Hanna
我知道问题是@user被分配了两次。我的问题是如何避免这种情况?谢谢,请不要投反对票!每个人都会犯错误
在我的实际代码中,我尝试在两个用户的循环中运行这两种方法:
def private_key
IO.popen('cmd', 'r+') do |pipe|
# inside of irb, changing to a different directory
pipe.puts('cd C:/OpenSSL/bin')
pipe.puts('openssl.exe')
pipe.puts("genrsa -out C:/Sites/keys/#{@user}private.pem 2048")
pipe.close_write
end
end
def create_csr
IO.popen('cmd', 'r+') do |pipe|
# inside of irb, changing to a different directory
pipe.puts('cd C:/OpenSSL/bin')
pipe.puts('openssl.exe')
pipe.puts("req -config c:/OpenSSL/openssl.cnf -new -batch -sha256 -key C:/Sites/keys/#{@username}private.pem -subj 'hal#{@user}' -out C:/Sites/keys/#{@username}csr.pem")
pipe.close_write
end
end
这里发生了一个非常奇怪的情况。所发生的是对
[pass1,pass2]
进行求值,结果是填充数组的内容,而不是实际的方法
然后根据结果调用您的。每个。由于pass2
设置@user='Hanna'
,因此您将获得双输出
您可以使用以下代码看到:
puts "#{[pass1, pass2]}" # => ["DE", "Ooma"]
之所以这样做是因为Ruby总是返回方法中最后一条语句的结果
编写此代码的正确方法是从数组中删除方法调用。那是糟糕的形式。但我不确定你想要实现什么,所以你可以这样实现你的结果:
def pass1
@pass = 'zim'
@country = 'DE'
@user = 'Kras'
end
def pass2
@pass = 'Ooma'
@user = 'Hanna'
end
[pass1, pass2].each do |user|
puts user
end
是的,可能
def pass1
@user = 'Kras'
@pass = 'zim'
@country = 'DE'
end
def pass2
@user = 'Hanna'
@pass = 'Ooma'
end
def foo
puts @user
end
[:pass1,:pass2].each do |sym|
send(sym)
foo
end
输出
Kras
Hanna
你的问题
基本问题是数组中没有用户名,而是方法的返回值,因此#print只对@user变量中当前存储的内容进行操作
具有结构的解决方案
重构整个混乱局面,并使用a获取成员变量。例如:
class Pass < Struct.new(:user, :pass, :country)
end
pass1 = Pass.new 'Kras', 'zim', 'DE'
pass2 = Pass.new 'Hanna', 'Ooma'
[pass1, pass2].map { |pass| p pass.user }
#=> ["Kras", "Hanna"]
class Pass[“克拉斯”,“汉娜”]
这将打印:
“Kras”
“汉娜”
并返回一个数组,您可以根据需要使用或丢弃该数组。看起来您正在尝试编写类似于此的内容,即惯用Ruby,以及我们如何循环对象实例,调用该对象中的特定方法:
class User
def initialize(user, pass, country=nil)
@user = user
@pass = pass
@country = country
end
def user
@user
end
end
pass1 = User.new( 'Kras', 'zim', 'DE' )
pass2 = User.new( 'Hanna', 'Ooma' )
[pass1, pass2].each do |o|
puts o.user
end
运行时,输出:
Kras
Hanna
请注意,我不是在方法内部打印值,而是检索它的值,然后打印它。这让我可以在层中构建功能。我可以有一个print\u user
方法,但我会被它能做什么所困扰:
def print_user
puts @user
end
它只输出到控制台或STDOUT指向的任何地方。如果我需要将其写入文件,我必须编写另一个采用文件名的方法。如果我想将值发送到数据库,我必须编写另一个方法,该方法接受数据库DSN。这很愚蠢,相反,我的对象处理并返回关于它自己的东西,然后我会有一些外部方法来处理我得到的值的I/O
回到您的代码:看起来您正在尝试使用方法来创建变量的状态,这是可行的,但实际上不是您应该这样做的方式。有时,我们希望整体切换对象的设置,但通常我们会将其作为类中的方法进行切换,可能类似于这样:
class User
attr_reader :favorite_color, :favorite_food
def initialize(user, pass, country=nil)
@user = user
@pass = pass
@country = country
@favorite_color = 'orange'
@favorite_food = 'pumpkins'
end
def change_color_and_food(c, f)
@favorite_color = c
@favorite_food = f
end
end
pass1 = User.new( 'Kras', 'zim', 'DE' )
pass1.change_color_and_food('red', 'beets')
class User
attr_accessor :user, :username, :pass, :country
def initialize(user, username, pass, country=nil)
@user = user
@username = username
@pass = pass
@country = country
end
# ...more methods specific to users...
end
跑步让我们将食物和颜色偏好改为“甜菜”和“红色”:
看看您的附加代码,它看起来可以简化(又名DRY'd又名“不要重复自己”)。我不使用Windows,因此无法对此进行测试,但以下代码似乎正确:
def private_key
Dir.chdir('C:/OpenSSL/bin') do
system('openssl.exe')
system("genrsa -out C:/Sites/keys/#{@user}private.pem 2048")
end
end
def create_csr
Dir.chdir('C:/OpenSSL/bin') do
system('openssl.exe')
system("req -config c:/OpenSSL/openssl.cnf -new -batch -sha256 -key C:/Sites/keys/#{@username}private.pem -subj 'hal#{@user}' -out C:/Sites/keys/#{@username}csr.pem")
end
end
Ruby接受一个块,因此它会将目录更改为给定的参数,执行块中的命令,然后在退出时弹出目录
而且,你不需要打开一个管道,你应该能够用它来完成你想要做的事情
但是等等!还有更多
还有多余的工作要做,所以我要多干一点:
def create(cmd)
Dir.chdir('C:/OpenSSL/bin') do
system('openssl.exe')
system(cmd)
end
end
def private_key(u)
create("genrsa -out C:/Sites/keys/#{ u.user }private.pem 2048")
end
def create_csr(u)
create("req -config c:/OpenSSL/openssl.cnf -new -batch -sha256 -key C:/Sites/keys/#{ u.username }private.pem -subj 'hal#{ u.user }' -out C:/Sites/keys/#{@username}csr.pem")
end
这些方法不需要是用户类的一部分,它们只知道如何访问用于从该类实例检索属性的方法
将用户的一个实例作为参数传递给任何一个方法,如果用户看起来像这样,那么这些方法将做正确的事情:
class User
attr_reader :favorite_color, :favorite_food
def initialize(user, pass, country=nil)
@user = user
@pass = pass
@country = country
@favorite_color = 'orange'
@favorite_food = 'pumpkins'
end
def change_color_and_food(c, f)
@favorite_color = c
@favorite_food = f
end
end
pass1 = User.new( 'Kras', 'zim', 'DE' )
pass1.change_color_and_food('red', 'beets')
class User
attr_accessor :user, :username, :pass, :country
def initialize(user, username, pass, country=nil)
@user = user
@username = username
@pass = pass
@country = country
end
# ...more methods specific to users...
end
正如我所说,我没有Windows,所以这是未经测试的,但它离Ruby代码应该是什么更近了。谢谢,那么我应该如何编写循环?我用我原来的方法更新了我的问题,你会发现它们都太长了,无法像你建议的那样编写!我用我原来的方法更新了我的问题,你会发现它们都太长了,不能像你支持我的那样写出来!但总的来说,我觉得你的解决方案很有趣!如果下面的答案不清楚,@user
被设置为'Kris',然后在Ruby解析代码时改为'Hanna'<代码>[pass1,pass2]。每个do
只执行打印
两次;如果将其替换为print,则会得到相同的结果;打印
。就像我说的,我没有Windows,所以无法测试。不需要使用IO.popen
,而且system
应该可以工作。您的“不工作”没有告诉我任何有用的信息,因此,作为一个粗略的猜测,我认为您需要使用您想要使用的命令的整个路径。子进程通常具有非常有限的环境,因此无法使用可搜索的可执行路径,这意味着必须指定命令的整个路径。这就是我们在Linux或Mac操作系统上所做的。看,尤其是第二个答案和