在Ruby中初始化实例时使用哈希作为参数时发生了什么?

时间:2014-03-15 11:29:14

标签: ruby-on-rails ruby hash

我为User定义了一个类,它将哈希作为参数,     类用户       attr_accessor:name,:email

  def initialize(attributes = {})
    @name  = attributes[:name]
    @email = attributes[:email]
  end

  def formatted_email
    "#{@name} <#{@email}>"
  end
end

在使用括号和参数的空格语法在控制台中初始化时,行为是不同的,第二个没有接收属性,但如果我先定义一个哈希然后用哈希作为参数初始化,它现在运作良好,为什么会发生这种情况?

2.0.0-p451 :013 > example = User.new(name:'John', email:'john@example.com')
 => #<User:0x007fbcdb57e140 @name="John", @email="john@example.com"> 
2.0.0-p451 :014 > example = User.new {name:'John', email:'john@example.com'}
 => #<User:0x007fbcdb599080 @name=nil, @email=nil> 
2.0.0-p451 :021 > hash = {name: 'John', email: 'john@example.com'}
 => {:name=>"John", :email=>"john@example.com"} 
2.0.0-p451 :022 > User.new hash
 => #<User:0x007fbcdc4af8a8 @name="John", @email="john@example.com"> 

2 个答案:

答案 0 :(得分:3)

查看代码:

class User 
  def initialize(attributes = {})
    p attributes # I put it to debug the hash **attributes** after each *new* call.
    @name  = attributes[:name]
    @email = attributes[:email]
  end

  def formatted_email
    "#{@name} <#{@email}>"
  end
end

# here you did pass the method argument as a Hash.
User.new(name:'John', email:'john@example.com') 
# >> {:name=>"John", :email=>"john@example.com"} # output of attributes hash
# you got #<User:0x007fbcdb57e140 @name="John", @email="john@example.com">, as the
# hash **attributes** is, {:name=>"John", :email=>"john@example.com"}. So inside the 
# initialize method
#  @name  = "John" as , attributes[:name] is "John"
#  @email = "john@example.com" as, attributes[:email] is "john@example.com"

# here you didn't pass the method argument as a Hash, rather a block.
User.new {name:'John', email:'john@example.com'}
# >> {} # output of attributes hash is empty hash.
# you got #<User:0x007fbcdb599080 @name=nil, @email=nil>, as *attributes* is empty.
# so inside the initialize method @name  = nil happened, as attributes[:name] is nil.
# @email = nil, as attributes[:email] is nil.

# here you did pass the method argument as a Hash.
hash = {name: 'John', email: 'john@example.com'}
User.new hash # output of attributes hash
# >> {:name=>"John", :email=>"john@example.com"}

在Ruby中,调用语法的方法是

  • meth_name(argument_list_of_object/objects) { #block }
  • meth_name(argument_list_of_object/objects)
  • meth_name argument_list_of_object/objects。当你没有传递阻止时这是有效的,否则错误将被删除

这意味着在Ruby中,{ .. }在方法调用之后,解析为好像,您正在向方法发送一个块,而不是像将 hash 作为参数传递一样。

说明这一理论的另一个简单例子:

def foo(arg = 10)
  p arg
end

foo 12 # => 12
foo(12) # => 12
foo { 12 } # => 10 default value
foo "arg" { 12 }
# ~> -:8: syntax error, unexpected '{', expecting end-of-input
# ~> foo "arg" { 12 }
# ~>  

总结:

# you are passing a 2 key/value argument, which in runtime will create a hash
# {name:'John', email:'john@example.com'}, then will be assigned to
# local variable attributes of the method initialize.
User.new name:'John', email:'john@example.com'
# => #<User:0x90f5a24 @email="john@example.com", @name="John">

# same as above
User.new(name:'John', email:'john@example.com')
# => #<User:0x90f4a5c @email="john@example.com", @name="John">

# simply passing a block to the method.
User.new {name:'John', email:'john@example.com'}
# => #<User:0x90f7450 @email=nil, @name=nil>

希望这有帮助。

答案 1 :(得分:0)

这是由于空白空间,以下应打印正确,我已删除空格并添加括号

example = User.new({name: 'John', email: 'john@example.com'})