Reputation: 86097
Here's the code:
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
and here's what I get in 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>'
I was expecting to be able to access people.second
and people.second.id
. What's up?
Upvotes: 0
Views: 1423
Reputation: 4202
Just use people[1]
, which is the standard way to access elements in an array.
Requiring "active_support/core_ext" adds a lot of stuff you probably don't need for what amounts to a very small amount of syntactic sugar.
Upvotes: 1
Reputation: 230336
This method does not exist in plain ruby. It's from rails. To use it, you have to include Active Support.
require 'active_support/core_ext'
a = [4, 5, 10]
a.first # => 4
a.second # => 5
a.third # => 10
But you really shouldn't accustom yourself with accessing array elements in this way. first
/last
helpers exist for a reason: very often you need just the first or last element.
user = User.where(name: 'Sergio').first # user might not exist
last_transaction = user.transactions.last
If you plan on accessing second, third, fourth (and further) elements, there are better options. Iterating with .each
, for example.
user.transactions.each do |tran|
# ...
end
I personally prefer indexer over such helpers* at all times (even when they are available).
users[1]
vs. users.second
)They are easier. Consider changing
users[1] to users[2]
vs.
users.second to users.third
* I mean the helpers that Active Support brings in. I do prefer first
over users[0]
.
Upvotes: 8
Reputation: 30445
As the other answer states, this method is from Active Support. But if you don't want to pull in Active Support just for a single method... well, this is Ruby, isn't it?
class Array
def second
self[1]
end
end
Or, more generally:
module Enumerable
def second
first = true
each { |x| first ? (first = false) : return x }
end
end
You could actually include both of those definitions, and for Arrays, the more specific (and probably faster) method will be used. For other types of Enumerables, the more general method will be used.
Upvotes: 0