Hashing object arrays with Rails (inject, index_by, etc.)

For example, suppose you have a User model and each object has a name, email, age, and so on.

Suppose you have a group of arrays that you want to do only for certain email people, and which emails are targeted. (It was a bit bad, but it was like that) ** * Email is guaranteed to be unique **

At first, I wrote the following process.

sample.rb



#The group of email addresses you want to target.
targets = ["[email protected]","[email protected]"..."[email protected]"]

targets.each do |target|
  User.all.each do |user|
    #If there is a match, proceed to the next process
    next if target != user.email
    user.nextaction
  end
end

If this is the case, it will be double-turned in each, so when I think that it can be done more easily, why not make a hash with email as the key? ?? It became.

And here is the first hash generated by inject.

sample.rb



#The email group you want to target.
targets = ["[email protected]","[email protected]"..."[email protected]"]
#User with email as key.Hash all
users_sort_email = User.all.inject({}) {|hash,user| hash[user.email] = user; hash }
targets.each do |target|
  #If target is used as a key (= email with the same value as target exists), skip to the next process
  next if users_sort_email[target].blank?
  user.nextaction
end

You can do this, but using index_by makes it easier to see.

sample.rb



#The email group you want to target.
targets = ["[email protected]","[email protected]"..."[email protected]"]
#User with email as key.This alone represents hashing of all.
users_sort_email = User.all.index_by(&:email)
targets.each do |target|
  next if users_sort_email[target].blank?
  user.nextaction
end

It became very easy to see. However, index_by is supported by ActiveRecord, so let's use injection in the default Ruby.

Postscript

Initially, the above article described age as the key instead of email, but in the ** comment, "If you specify data whose uniqueness is not guaranteed as the key, the hash key will be duplicated, and eventually You pointed out that you can only call nextaction **.

This is exactly what you said, and when you actually used it in practice, it was processed with a key that guarantees uniqueness, but please fully understand the recognition that "that is why the above sort can be used". It was a mistake that occurred because I wrote the article.

Based on this, we have revised the article by clearly stating that email is the key and that emal is unique. Thank you!

Also, I was able to receive a polite comment when I wanted to perform the same processing with a key whose uniqueness is not guaranteed, such as age. For details, please refer to the comment section, but ** if you have ActiveRecord **, it can be realized by the following processing.

sample.rb


targets = [1,4,5,6,10,23]
User.where(age: targets).each do |u| 
  u.nextaction
end

The SQL issued in this case is as follows.

SQL.rb


-- User.where(age: targets)Is issuing such SQL
SELECT * FROM users WHERE (users.age IN (1,4,5,6,10,23));

** Get all users with target age (all user data extracted at this point is the target of nextaction) → By turning each, "only the target user will perform nextaction to all people" * It is realized in the form of *.

I learned a lot about this as well, and thank you for taking the time to comment ... I learned!

Recommended Posts

Hashing object arrays with Rails (inject, index_by, etc.)
Eliminate Rails FatModel with value object
[Rails] Manage secret keys etc. with credentials.yml
How to delete a new_record object built with Rails