2

我是编程新手,实际上知道我的代码的问题是什么,但真的不知道如何解决它!我写了一个演示代码:

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

4 回答 4

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 “Don't Repeat Yourself”)。我不使用 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

RubyDir.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 代码应有的样子。

于 2013-09-26T16:19:10.833 回答
2

你的问题

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

结构解决方案

重构整个混乱并使用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"]

这将打印:

“克拉斯”
“汉娜”

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

于 2013-09-26T16:05:56.773 回答
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
于 2013-09-26T16:05:04.753 回答
0

这里发生了一个非常奇怪的场景。发生的事情是[pass1, pass2]被评估,结果是填充数组的内容,而不是您的实际方法。

然后根据结果.each调用您。由于sets ,您将获得双倍输出。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
于 2013-09-26T15:59:28.980 回答