Where is the method for the array
I'm pretty much trying to mimic a class method where
, but instead on an instance, that instance is an array of hashes. For example: this exists as a class method Class.where(:name => "Joe")
, so I want to be able to do this:
@joe = {:name => "Joe", :title => "Mr.", :job => "Accountant"}
@kelly = {:name => "Kelly", :title => "Ms.", :job => "Auditor"}
@people = [@joe, @kelly]
and call this:
@people.where(:name => 'Joe')
which should return an object @joe
.
How should I write this?
source to share
As I understand it, the task you want to define Array#where
. Here you are:
▶ class Array
▷ def where hash
▷ return nil unless hash.is_a? Hash # one might throw ArgumentError here
▷ self.select do |e|
▷ e.is_a?(Hash) && hash.all? { |k, v| e.key?[k] && e[k] == v }
▷ end
▷ end
▷ end
#⇒ :where
▶ @people.where(:name => 'Joe')
#⇒ [
# [0] {
# :job => "Accountant",
# :name => "Joe",
# :title => "Mr."
# }
# ]
▶ @people.where(:name => 'Joe', :job => 'Accountant')
#⇒ [
# [0] {
# :job => "Accountant",
# :name => "Joe",
# :title => "Mr."
# }
# ]
▶ @people.where(:name => 'Joe', :job => 'NotAccountant')
#⇒ []
Hope it helps.
UPD Slightly updated function to distinguish between values nil
and missing keys. Credits to @CarySwoveland.
source to share
You can use Enumerable # find to get the first element that matches:
@people.find { |p| p[:name] == 'Joe' }
or List # find_all to retrieve all elements that match:
@people.find_all { |p| p[:name] == 'Joe' }
source to share
This is slightly different from Rails' where
, more like find_by
: where
returns a relation, a collection of instances. In fact, the implementations of both are about the same and use different methods Enumerable
:
@people.select { |h| h[:name] == 'Joe' } # where-like
@people.find { |h| h[:name] == 'Joe' } # find_by-like
You can generalize it at any time by fulfilling Enumerable#all?
the hash condition.
source to share