6

I have an array of hashes - @profiles which has data as:

[{:user_id=>5, :full_name=>"Emily Spot"},{:user_id=>7, :full_name=>"Kevin Walls"}] 

I want to get full_name of say user_id = 7? I'm doing the following: but it's throwing an error that expression @profiles.find{|h| h[':user_id'] == current_user.id} is nil.

name = @profiles.find{ |h| h[':user_id'] == current_user.id }[':full_name'] 

if I use select instead of find then error is - no implicit conversion of String into Integer.

How do I search through the array of hashes?

UPDATE:

After @Eric's answer, I restructured my job model & view actions:

 def full_names profile_arr||= [] profile_arr = self.applications.pluck(:user_id) @profiles = Profile.where(:user_id => profile_arr).select([:user_id, :first_name, :last_name]).map {|e| {user_id: e.user_id, full_name: e.full_name} } @full_names = @profiles.each_with_object({}) do |profile, names| names[profile[:user_id]] = profile[:full_name] end end 

In the view....,

p @current_job.full_names[current_user.id] 

3 Answers 3

7

@profiles is an array of hashes, with symbols as keys, whereas what you use is String objects.

So ':user_id' is a string, and you want symbol: :user_id:

@profiles.find{ |h| h[:user_id] == current_user.id } 

I want to get full_name of say user_id == 7

@profiles.find { |hash| hash[:user_id] == 7 }.fetch(:full_name, nil) 

Note, I used Hash#fetch for case, when there is no hash with value 7 at key :user_id.

Sign up to request clarification or add additional context in comments.

5 Comments

Oh yes, silly me....that quote was a mistake. Thx. OK so you mean the safe operator will bypass if value of expression is nil ?
@Means yea, so if @profiles.find { |hash| hash[:user_id] == 7 } returns nil, without safe navigation calling name on it will raise an exception,whereas with safe navigation it will just return nil
@Means nil&.non_existing_method => nil
Sorry, Andrey, but the '&.full_name' threw an error : undefined method `full_name' for {:user_id=>5, :full_name=>"Emily Spot"}:Hash. Only when I append [:full_name] to that @profile.find expression, it works. Any idea?
@Means my bad, I edited the answer, you are 100% correct, you can't run full_name on a hash, because it does not implement that method.
4

As you've noticed, it's not very convenient to extract the name of user_id 7. You could modify your data structure a bit :

@profiles = [{:user_id=>5, :full_name=>"Emily Spot"}, {:user_id=>7, :full_name=>"Kevin Walls"}] @full_names = @profiles.each_with_object({}) do |profile, names| names[profile[:user_id]] = profile[:full_name] end p @full_names # {5=>"Emily Spot", 7=>"Kevin Walls"} p @full_names[7] # "Kevin Walls" p @full_names[6] # nil 

You didn't lose any information but name look-up is now much faster, easier and more robust.

4 Comments

Eric, this is an out-of-the-box answer....and actually perfectly worked for me as I have moved the full_names now to controller. I've edited into my original question to show how I structured it before and now applied your inputs.
@Means: Good to know. You probably should put this logic in the model though.
Can you suggest if @profiles SQL query in my original question -UPDATE part, can be improved/optimized without that long 'select...map' combination?
@Means after your edit it is obvious, that this logic should go to the model. You should think about setting up proper associations.
1

Suggesting, to create a new hash that can make things simpler

Eg:

results = {} profiles = [ {user_id: 5, full_name: "Emily Spot"}, {user_id: 7, full_name: "Kevin Walls"} ] profiles.each do |details| results[details[:user_id]] = details[:full_name] end 

Now, results will have:

{5: "Emily Spot", 7: "Kevin Walls"} 

So, if you need to get full_name of say user_id = 7, simply do:

results[7] # will give "Kevin Walls" 

1 Comment

Michael, you didn't really answer the question. You need to give a solution that returns a specific user's full name. Your answer is close, but I'm going to downvote it until you get a chance to edit or delete your answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.