为什么我在数组中得到第二个,第三个对象的奇怪行为?

Sno*_*ash -1 ruby

这是代码:

class Person
  attr_accessor :id, :name

  def initialize(init = {})
    init.each do |k, v|
      send("#{k}=", v)
    end
  end
end

people = [ 
  Person.new(:id => 1, :name => "Adam"), 
  Person.new(:id => 2), 
  nil,
]

people.map! do |person|
  person ||= Person.new(:id => 3, :name => "Some default")
  person.name ||= 'Eve'
  person
end

binding.pry
Run Code Online (Sandbox Code Playgroud)

这就是我得到的东西:

[1] pry(main)> people
=> [#<Person:0x007fc2b0afba98 @id=1, @name="Adam">,
 #<Person:0x007fc2b0afb930 @id=2, @name="Eve">,
 #<Person:0x007fc2b0afb7f0 @id=3, @name="Some default">]
[2] pry(main)> people.first
=> #<Person:0x007fc2b0afba98 @id=1, @name="Adam">
[3] pry(main)> people.second
NoMethodError: undefined method `second' for #<Array:0x007fc2b0afb890>
from (pry):3:in `<main>'
Run Code Online (Sandbox Code Playgroud)

我原以为能够访问people.secondpeople.second.id.这是怎么回事?

Ser*_*sev 7

普通红宝石中不存在此方法.它来自铁轨.要使用它,您必须包括Active Support.

require 'active_support/core_ext'

a = [4, 5, 10]

a.first # => 4
a.second # => 5
a.third # => 10
Run Code Online (Sandbox Code Playgroud)

但是你真的不应该习惯以这种方式访问​​数组元素.first/ lasthelper存在的原因是:通常只需要第一个或最后一个元素.

user = User.where(name: 'Sergio').first # user might not exist
last_transaction = user.transactions.last
Run Code Online (Sandbox Code Playgroud)

如果您计划访问第二,第三,第四(和更多)元素,则有更好的选择..each例如,迭代.

user.transactions.each do |tran|
  # ...
end
Run Code Online (Sandbox Code Playgroud)

我个人更喜欢索引器而不是这些帮助器*(即使它们可用).

  1. 索引器形式较短(users[1]对比users.second)
  2. 他们更容易.考虑改变

    users[1] to users[2]
    
    Run Code Online (Sandbox Code Playgroud)

    users.second to users.third
    
    Run Code Online (Sandbox Code Playgroud)

*我的意思是积极支持带来的助手.我也喜欢firstusers[0].