循环,输出重复

时间:2013-09-26 15:53:32

标签: 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

我的输出应该是:

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

4 个答案:

答案 0 :(得分:3)

看起来你正在尝试编写类似于此的东西,这是惯用的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_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')

运行时,我们可以将食物和颜色偏好更改为“甜菜”和“红色”:

pass1.favorite_food # => "beets"

查看您的其他代码,看起来它可以简化(AKA DRY'd AKA“不要重复自己”)。我不使用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的Dir.chdir占用一个块,因此它会将目录更改为给定的参数,执行块中的命令,然后在退出时弹出目录。

并且,您应该能够使用system,而不是打开管道,看起来它可以完成您想要做的事情。

但是等等!还有更多!

仍然存在冗余,所以我会更多地干它:

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

这些方法不需要成为User类的一部分,它们只知道如何访问用于从该类实例中检索属性的方法。

将您的用户实例传递给任一方法作为参数,如果您的用户看起来像这样,方法将做正确的事情:

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代码应该是什么。

答案 1 :(得分:2)

您的问题

您的基本问题是您的阵列没有填充用户名,而是填充了方法的返回值,因此#print仅对@user中存储的当前进行操作变量

具有Struct

的解决方案

重构整个混乱并使用Struct来获取成员变量。例如:

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"]

这将打印:

  

“的Kras”
  “汉娜”

并返回一个数组,您可以根据需要使用或丢弃该数组。

答案 2 :(得分:1)

是的可能!

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

答案 3 :(得分:0)

你有一个非常奇怪的场景。会对[pass1, pass2]进行评估,结果是填充数组的结果,而不是实际的方法。

然后针对结果调用.each。由于pass2设置@user = 'Hanna',您将获得双倍输出。

您可以使用以下代码查看:

puts "#{[pass1, pass2]}" # => ["DE", "Ooma"]

它是['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