Jon
Jon

Reputation: 43

where method for Array

I am pretty much trying to mimic the class method of where, but instead on an instance, this instance being 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 the @joe object.

How should I write this?

Upvotes: 3

Views: 437

Answers (5)

chad_
chad_

Reputation: 3819

You can use Enumerable#find to retrieve the first element that matches:

@people.find     { |p| p[:name] == 'Joe' }

or Enumerable#find_all to retrieve all elements that match:

@people.find_all { |p| p[:name] == 'Joe' }

Upvotes: 3

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121000

As I understood the task, you want to have Array#where defined. Here you go:

▶ 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 the function to distinguish nil values and absent keys. Credits to @CarySwoveland.

Upvotes: 5

B Seven
B Seven

Reputation: 45941

@people.find{|p| p[:name] =='Joe'}

or

@people.find(:name => 'Joe').first

or

@people.select{|p| p[:name ]== 'Joe'}.first

With a method:

def find_user params
  @people.find(params).first
end

find_user name:'Joe'
=> {:name=>"Joe", :title=>"Mr.", :job=>"Accountant"}

Upvotes: 0

errata
errata

Reputation: 26912

If you are talking about an actual array of hashes and not active record:

@some_array.select {|item| item["search_key"] = 'search val' }

Upvotes: 0

D-side
D-side

Reputation: 9495

It's a bit different to Rails' where, more like find_by: where returns a relation, a collection of instances. Actually, the implementations of both are about the same and use different methods of 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 running Enumerable#all? on conditions hash.

Upvotes: 0

Related Questions