@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变量中的错误。

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


当前回答

试试这个:——

1.object_id
#=> 3

2.object_id
#=> 5

a = 1
#=> 1
a.object_id
#=> 3

b = 2
#=> 2
b.object_id
#=> 5

标识符a包含值对象1的object_id 3,标识符b包含值对象2的object_id 5。

现在这样做:——

a.object_id = 5
#=> error

a = b
#value(object_id) at b copies itself as value(object_id) at a. value object 2 has object_id 5
#=> 2

a.object_id 
#=> 5

现在,a和b都包含相同的object_id 5,它指向值对象2。 因此,Ruby变量包含object_ids来引用值对象。

执行以下操作也会给出错误:——

c
#=> error

但是这样做不会产生错误:——

5.object_id
#=> 11

c = 5
#=> value object 5 provides return type for variable c and saves 5.object_id i.e. 11 at c
#=> 5
c.object_id
#=> 11 

a = c.object_id
#=> object_id of c as a value object changes value at a
#=> 11
11.object_id
#=> 23
a.object_id == 11.object_id
#=> true

a
#=> Value at a
#=> 11

这里标识符a返回值对象11,其对象id为23,即object_id 23位于标识符a,现在我们看到一个使用method的例子。

def foo(arg)
  p arg
  p arg.object_id
end
#=> nil
11.object_id
#=> 23
x = 11
#=> 11
x.object_id
#=> 23
foo(x)
#=> 11
#=> 23

foo中的Arg被赋值为x。 它清楚地表明参数是由值11传递的,值11本身是一个对象,对象id为23。

现在再看这个:——

def foo(arg)
  p arg
  p arg.object_id
  arg = 12
  p arg
  p arg.object_id
end

#=> nil
11.object_id
#=> 23
x = 11
#=> 11
x.object_id
#=> 23
foo(x)
#=> 11
#=> 23
#=> 12
#=> 25
x
#=> 11
x.object_id
#=> 23

在这里,标识符arg首先包含object_id 23来引用11,在对值对象12进行内部赋值后,它包含object_id 25。但它不会改变在调用方法中使用的标识符x引用的值。

因此,Ruby是按值传递的,Ruby变量不包含值,但包含对值对象的引用。

其他回答

其他的答案都是正确的,但是一个朋友让我向他解释这一点,归根结底就是Ruby是如何处理变量的,所以我想分享一些我为他写的简单的图片/解释(很抱歉篇幅太长,可能有些过于简化了):


Q1:当你将一个新变量str赋值为'foo'时会发生什么?

str = 'foo'
str.object_id # => 2000

答:一个名为str的标签被创建,指向对象'foo',对于这个Ruby解释器的状态来说,它恰好位于内存位置2000。


Q2:当你使用=将现有变量str赋值给一个新对象时会发生什么?

str = 'bar'.tap{|b| puts "bar: #{b.object_id}"} # bar: 2002
str.object_id # => 2002

A:标签str现在指向一个不同的对象。


Q3:当你分配一个新的变量= str会发生什么?

str2 = str
str2.object_id # => 2002

答:创建一个名为str2的新标签,指向与str相同的对象。


Q4:如果被str和str2引用的对象被改变了会发生什么?

str2.replace 'baz'
str2 # => 'baz'
str  # => 'baz'
str.object_id # => 2002
str2.object_id # => 2002

答:两个标签仍然指向同一个对象,但是对象本身已经发生了变化(它的内容已经改变为其他东西)。


这和最初的问题有什么关系?

这与第三季度和第四季度的情况基本相同;该方法获得传入给它的变量/ label (str2)的私有副本(str)。它不能改变标签str指向的对象,但它可以改变它们都引用的对象的内容,以包含else:

str = 'foo'

def mutate(str2)
  puts "str2: #{str2.object_id}"
  str2.replace 'bar'
  str2 = 'baz'
  puts "str2: #{str2.object_id}"
end

str.object_id # => 2004
mutate(str) # str2: 2004, str2: 2006
str # => "bar"
str.object_id # => 2004

需要注意的是,您甚至不需要使用“replace”方法来更改原始值。如果你为一个哈希值分配了其中一个哈希值,你就是在改变原始值。

def my_foo(a_hash)
  a_hash["test"]="reference"
end;

hash = {"test"=>"value"}
my_foo(hash)
puts "Ruby is pass-by-#{hash["test"]}"

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

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

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

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

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

试试这个:——

1.object_id
#=> 3

2.object_id
#=> 5

a = 1
#=> 1
a.object_id
#=> 3

b = 2
#=> 2
b.object_id
#=> 5

标识符a包含值对象1的object_id 3,标识符b包含值对象2的object_id 5。

现在这样做:——

a.object_id = 5
#=> error

a = b
#value(object_id) at b copies itself as value(object_id) at a. value object 2 has object_id 5
#=> 2

a.object_id 
#=> 5

现在,a和b都包含相同的object_id 5,它指向值对象2。 因此,Ruby变量包含object_ids来引用值对象。

执行以下操作也会给出错误:——

c
#=> error

但是这样做不会产生错误:——

5.object_id
#=> 11

c = 5
#=> value object 5 provides return type for variable c and saves 5.object_id i.e. 11 at c
#=> 5
c.object_id
#=> 11 

a = c.object_id
#=> object_id of c as a value object changes value at a
#=> 11
11.object_id
#=> 23
a.object_id == 11.object_id
#=> true

a
#=> Value at a
#=> 11

这里标识符a返回值对象11,其对象id为23,即object_id 23位于标识符a,现在我们看到一个使用method的例子。

def foo(arg)
  p arg
  p arg.object_id
end
#=> nil
11.object_id
#=> 23
x = 11
#=> 11
x.object_id
#=> 23
foo(x)
#=> 11
#=> 23

foo中的Arg被赋值为x。 它清楚地表明参数是由值11传递的,值11本身是一个对象,对象id为23。

现在再看这个:——

def foo(arg)
  p arg
  p arg.object_id
  arg = 12
  p arg
  p arg.object_id
end

#=> nil
11.object_id
#=> 23
x = 11
#=> 11
x.object_id
#=> 23
foo(x)
#=> 11
#=> 23
#=> 12
#=> 25
x
#=> 11
x.object_id
#=> 23

在这里,标识符arg首先包含object_id 23来引用11,在对值对象12进行内部赋值后,它包含object_id 25。但它不会改变在调用方法中使用的标识符x引用的值。

因此,Ruby是按值传递的,Ruby变量不包含值,但包含对值对象的引用。

参数是原始引用的副本。因此,您可以更改值,但不能更改原始引用。