以下是代码:
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
这就是我得到的东西:
[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>'
我原本希望能够访问people.second
和people.second.id
。怎么了?
答案 0 :(得分:7)
普通红宝石中不存在此方法。它来自铁轨。要使用它,您必须包括Active Support。
require 'active_support/core_ext'
a = [4, 5, 10]
a.first # => 4
a.second # => 5
a.third # => 10
但你真的不应该习惯以这种方式访问数组元素。出现first
/ last
个助手是有原因的:通常只需要第一个或最后一个元素。
user = User.where(name: 'Sergio').first # user might not exist
last_transaction = user.transactions.last
如果您打算访问第二,第三,第四(和更多)元素,那么有更好的选择。例如,使用.each
进行迭代。
user.transactions.each do |tran|
# ...
end
我个人更喜欢索引器而不是这些帮助器*(即使它们可用)。
users[1]
与users.second
)他们更容易。考虑改变
users[1] to users[2]
VS。
users.second to users.third
*我的意思是Active Support带来的帮助。我更喜欢first
而不是users[0]
。
答案 1 :(得分:1)
只需使用people[1]
,这是访问数组中元素的标准方法。
要求“active_support / core_ext”添加了许多你可能不需要的东西,而这些东西相当于非常少量的语法糖。
答案 2 :(得分:0)
正如其他答案所述,此方法来自Active Support。但是如果你不想仅针对一种方法引入Active Support ......好吧,这是Ruby,不是吗?
class Array
def second
self[1]
end
end
或者,更一般地说:
module Enumerable
def second
first = true
each { |x| first ? (first = false) : return x }
end
end
您实际上可以包含这两个定义,对于Arrays,将使用更具体(也可能更快)的方法。对于其他类型的Enumerables,将使用更通用的方法。