Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 循环,输出正在重复_Ruby - Fatal编程技术网

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操作系统上所做的。看,尤其是第二个答案和