ruby中的方法不要改变变量

时间:2013-07-15 17:26:56

标签: ruby-on-rails ruby

我是ruby的新手,也是编程的新手。我在一个独立的ruby脚本中有一段代码,它从yaml文件中读取数据并将该数据分配给方法中的变量。这都是在一种方法中完成的。 在方法定义之外,我调用该方法并打印分配的变量的值。但是,呃哦,方法中赋值的变量的值是零...为什么?这与我假设的面向对象编程有关。有人可以详细说明吗?

以下是代码。提前谢谢。

#!/usr/bin/env ruby

require 'pg'
require 'yaml'

source_connection=nil

def load_configurations
    file_name = nil

    ARGV.each do|a|
      file_name = "#{a}"
    end
    dest_options = YAML.load_file(file_name)
    source_connection = dest_options['dest_name']
end

load_configurations()

puts source_connection

#####  returns nothing. why? #####

2 个答案:

答案 0 :(得分:5)

在Ruby中,就像在大多数语言中一样(至少我知道,Javascript可能是一个例外),有一个名为可见范围的概念。

Ruby中有四个范围:

  • 全球范围
  • 班级范围
  • 方法范围
  • 阻止范围

在实践中,它意味着为ex定义的局部变量。 in方法仅在此方法中可见,除非您显式向上传入(使用方法/块调用参数)或向下传入(使用返回)调用堆栈。

在你的情况下,在你将source_connection分配给nil的方法之外会发生什么,但是你在不同的范围内引用相同的var名称,因此只在那里分配。解决这个问题的Ruby方法是定义实例变量@source_connection)或将此变量显式传递到方法中然后返回它。

专业提示:在Ruby中,默认情况下会返回最后一次评估,因此您无需显式写入return source_connection

编辑:
对于类实例和实例变量,事情变得有点复杂,所以如果我只是指向Metaprogramming Ruby书的方向,那么最好的就是完美地列出这些主题。

EDIT2:
我的重写建议(有一点风格改变 - 对于方法定义,无论有没有params,总是添加parentheres是好的。另一方面,如果没有或只有一个参数,你可以省略,但这取决于个人味道 ;) 我还将缩进改为2个空格 - 我认为它是最常用的。

#!/usr/bin/env ruby

require 'pg'
require 'yaml'

def load_configurations()
  file_name = nil

  ARGV.each do|a|
    file_name = "#{a}"
  end
  dest_options = YAML.load_file(file_name)
  dest_options['dest_name'] # Ruby will return last evaluation
end

source_connection = load_configurations

puts source_connection # now it will print what you expect

答案 1 :(得分:3)

变量在方法范围内创建,不会设置为全局范围中定义的变量。有关更多信息,这可能是一个很好的阅读:http://www.techotopia.com/index.php/Ruby_Variable_Scope

你应该可以这样做:

def load_configurations
  file_name = nil

  ARGV.each do |a| 
    file_name = "#{a}"
  end

  dest_options = YAML.load_file(file_name)
  dest_options['dest_name']
end

source_connection = load_configurations
puts source_connection