@user.update_languages(params[:language][:language1], 
                       params[:language][:language2], 
                       params[:language][:language3])
lang_errors = @user.errors
logger.debug "--------------------LANG_ERRORS----------101-------------" 
                + lang_errors.full_messages.inspect

if params[:user]
  @user.state = params[:user][:state]
  success = success & @user.save
end
logger.debug "--------------------LANG_ERRORS-------------102----------" 
                + lang_errors.full_messages.inspect

if lang_errors.full_messages.empty?

@user对象将错误添加到update_languages方法中的lang_errors变量中。 当我在@user对象上执行保存时,我丢失了最初存储在lang_errors变量中的错误。

虽然我正在尝试做的更多的是一个黑客(似乎没有工作)。我想知道为什么变量值被洗掉了。我理解通过引用传递,所以我想知道值如何可以保存在那个变量中而不被洗掉。


当前回答

是的,但是....

Ruby将引用传递给一个对象,因为Ruby中的所有东西都是对象,那么你可以说它是通过引用传递的。

我不同意这里的帖子声称它是通过价值,这对我来说似乎是迂腐的赛门铁克游戏。

然而,实际上它“隐藏”了行为,因为ruby提供的大多数操作都是“开箱即用”的——例如字符串操作,会生成对象的副本:

> astringobject = "lowercase"

> bstringobject = astringobject.upcase
> # bstringobject is a new object created by String.upcase

> puts astringobject
lowercase

> puts bstringobject
LOWERCASE

这意味着大多数时候,原始对象保持不变,给人一种ruby是“传递值”的感觉。

当然,在设计自己的类时,理解这种行为的细节对于功能性行为、内存效率和性能都很重要。

其他回答

Ruby是解释性的。变量是对数据的引用,而不是数据本身。这便于对不同类型的数据使用相同的变量。

赋值lhs = rhs然后复制rhs上的引用,而不是数据。这与其他语言不同,比如C语言,赋值是从rhs复制数据到lhs。

对于函数调用,传递的变量,比如x,确实被复制到函数中的局部变量中,但x是一个引用。然后会有两个引用副本,它们都引用相同的数据。一个在调用者中,一个在函数中。

函数中的赋值会将一个新的引用复制到函数的x版本。在此之后,调用者的x版本保持不变。它仍然是对原始数据的引用。

相反,在x上使用.replace方法将导致ruby执行数据复制。如果在任何新赋值之前使用replace,那么调用者确实也会在其版本中看到数据更改。

类似地,只要传入变量的原始引用是恰当的,则调用者看到的实例变量将是相同的。在对象的框架内,实例变量总是具有最新的引用值,无论这些引用值是由调用者提供的,还是在类传入的函数中设置的。

“按值调用”或“按引用调用”在这里被混淆了,因为在编译语言中“=”是一个数据副本。在这种解释语言中,'='是一个参考副本。在这个例子中,你有一个传入的引用,后面跟着一个引用副本,尽管'='破坏了传入的原始引用,然后人们谈论它就好像'='是一个数据副本。

为了与定义保持一致,我们必须与'保持一致。替换',因为它是一个数据副本。从的角度来看。替换'我们看到这确实是通过引用传递的。此外,如果我们在调试器中遍历,我们会看到传入的引用,因为变量是引用。

However if we must keep '=' as a frame of reference, then indeed we do get to see the passed in data up until an assignment, and then we don't get to see it anymore after assignment while the caller's data remains unchanged. At a behavioral level this is pass by value as long as we don't consider the passed in value to be composite - as we won't be able to keep part of it while changing the other part in a single assignment (as that assignment changes the reference and the original goes out of scope). There will also be a wart, in that instance variables in objects will be references, as are all variables. Hence we will be forced to talk about passing 'references by value' and have to use related locutions.

Ruby是通过引用传递还是通过值传递?

Ruby是引用传递。总是这样。没有例外。没有如果。少啰嗦

下面是一个简单的程序,说明了这一事实:

def foo(bar)
  bar.object_id
end

baz = 'value'

puts "#{baz.object_id} Ruby is pass-by-reference #{foo(baz)} because object_id's (memory addresses) are always the same ;)"

=> 2279146940 Ruby是引用传递的2279146940,因为object_id(内存地址)总是相同的;)

def bar(babar)
  babar.replace("reference")
end

bar(baz)

puts "some people don't realize it's reference because local assignment can take precedence, but it's clearly pass-by-#{baz}"

=>有些人没有意识到它是引用,因为局部赋值可以优先,但它显然是引用传递

Two references refer to same object as long as there is no reassignment. 

同一对象中的任何更新都不会引用到新的内存,因为它仍然在相同的内存中。 以下是一些例子:

    a = "first string"
    b = a



    b.upcase! 
    => FIRST STRING
    a
    => FIRST STRING

    b = "second string"


a
    => FIRST STRING
    hash = {first_sub_hash: {first_key: "first_value"}}
first_sub_hash = hash[:first_sub_hash]
first_sub_hash[:second_key] = "second_value"

    hash
    => {first_sub_hash: {first_key: "first_value", second_key: "second_value"}}

    def change(first_sub_hash)
    first_sub_hash[:third_key] = "third_value"
    end

    change(first_sub_hash)

    hash
    =>  {first_sub_hash: {first_key: "first_value", second_key: "second_value", third_key: "third_value"}}

是的,但是....

Ruby将引用传递给一个对象,因为Ruby中的所有东西都是对象,那么你可以说它是通过引用传递的。

我不同意这里的帖子声称它是通过价值,这对我来说似乎是迂腐的赛门铁克游戏。

然而,实际上它“隐藏”了行为,因为ruby提供的大多数操作都是“开箱即用”的——例如字符串操作,会生成对象的副本:

> astringobject = "lowercase"

> bstringobject = astringobject.upcase
> # bstringobject is a new object created by String.upcase

> puts astringobject
lowercase

> puts bstringobject
LOWERCASE

这意味着大多数时候,原始对象保持不变,给人一种ruby是“传递值”的感觉。

当然,在设计自己的类时,理解这种行为的细节对于功能性行为、内存效率和性能都很重要。

Ruby是严格意义上的值传递,但是值是引用。

这可以称为“pass-reference-by-value”。这篇文章有我读过的最好的解释:http://robertheaton.com/2014/07/22/is-ruby-pass-by-reference-or-pass-by-value/

按值传递引用可以简单地解释如下:

函数接收(并将访问)调用者在内存中使用的同一对象的引用。但是,它不接收调用方存储该对象的盒子;与pass-value-by-value一样,函数提供自己的方框,并为自己创建一个新变量。

结果行为实际上是引用传递和值传递的经典定义的组合。