@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?
@userobject 将错误添加到方法中的lang_errors变量中update_lanugages。当我对对象执行保存时,@user我丢失了最初存储在lang_errors变量中的错误。
@user
lang_errors
update_lanugages
虽然我试图做的更像是一种黑客攻击(这似乎不起作用)。我想了解为什么变量值会被淘汰。我理解通过引用传递,所以我想知道如何将值保存在该变量中而不会被淘汰。
在传统术语中,Ruby是严格按值传递的。但这并不是您在这里真正要问的。
这个问题让人们感到困惑,因为有一个东西叫做引用类型,还有一个东西叫做 pass-by-reference,但它们实际上并没有太大的关系。
在按引用传递的情况下,函数的参数是对传递给函数的变量的引用,修改参数会修改原始变量。这不是Ruby。例如,让我们看下面的代码:
def inc(val) val += 1 end a = 1 inc a puts a
如果 Ruby 是一种按引用传递的语言,该程序将打印 2,因为val += 1ininc会增加a. 但事实并非如此。变量val不是对变量的引用a——它是一个具有相同值的自变量。
val += 1
inc
a
val
“可是等等!” 你说。“如果我们处理对象怎么办?对象变量肯定是通过引用传递的,对吧?”
def change_string(str) str << " I can insult you all you want" str << " because you'll never see this" str << " because I'm going to replace the whole string!" str << " Haha you smell bad!" str = "What? I didn't say anything." # I'm so sneaky end be_nice_to_me = "hello" change_string(be_nice_to_me) puts be_nice_to_me
如果 Ruby 是通过引用传递的,那么您永远不会看到该方法是多么卑鄙,change_string因为它会完全用字符串str = "What, I didn't say anything."替换值。如果 Ruby 不通过引用传递,这怎么可能?be_nice_to_me``"What? I didn't say anything."``change_string
change_string
str = "What, I didn't say anything."
be_nice_to_me``"What? I didn't say anything."``change_string
好吧,还记得我之前谈到的那些引用类型吗?嗯,这就是 Ruby 中的对象。引用类型是其值是对其他事物的引用的类型。在这种情况下,变量的值是对字符串的引用"hello"。当您传递字符串时,变量的值(即引用)被复制到变量str中。所以现在它们都持有对同一个对象str的引用,但不是对be_nice_to_me. 因此,当您修改对象时,这些更改会显示出来,因为它们都指的是同一个对象。但是当您修改一个变量时,另一个变量看不到它,因为这两个变量都不是对另一个变量的引用。
"hello"
str
be_nice_to_me
Ruby 是按引用传递还是按值传递?它是按值传递,但所有值都是引用。
Ruby 没有任何纯非引用值的概念,因此您当然不能将一个值传递给方法。变量总是对对象的引用。为了得到一个不会从你下面改变的对象,你需要复制或克隆你传递的对象,从而提供一个没有其他人引用的对象。(即使这也不是万无一失的,尽管 - 两种标准克隆方法都进行浅拷贝,所以克隆的实例变量仍然指向与原始对象相同的对象。如果 ivars 引用的对象发生变异,那仍然会出现在副本中,因为它引用了相同的对象。)