Ace McCloud
Ace McCloud

Reputation: 900

Ruby convert array of active records or objects into array of hashes

I have an object Persons which is an ActiveRecord model with some fields like :name, :age .etc.

Person has a 1:1 relationship with something called Account where every person has an account .

I have some code that does :

   Account.create!(person: current_person)

where current_person is a specified existing Person active record object.

Note : The table Account has a field for person_id and both of them have has_one in the model for each other.

Now I believe we could do something like below for bulk creation :

 Account.create!([{person: person3},{person:: person2} ....])

I have an array of persons but am not sure of the best way to convert to an array of hashes all having the same key.

Basically the reverse of Convert array of hashes to array is what I want to do.

Upvotes: 1

Views: 877

Answers (2)

Manoel M. Neto
Manoel M. Neto

Reputation: 666

The create method actually persists each hash individually, as shown in the source code, so probably it's not what you are looking for. Either way the following code would do the job:

  Account.create!(persons.map { |person| Hash[:person_id, person.id] })

If you need to create all records in the same database operation and are using rails 6+ you could use the insert_all method.

  Account.insert_all(persons.map { |person| Hash[:person_id, person.id] })

For previous versions of rails you should consider using activerecord-import gem.

  # Combination(1).to_a converts [1, 2, 3] to [[1], [2], [3]]
  Account.import [:person_id], persons.pluck(:id).combination(1).to_a

Upvotes: 2

lacostenycoder
lacostenycoder

Reputation: 11196

Why not just loop over your array of objects?

[person1, person2].each{|person| Account.create!(person: person)}

But if for any reason any of the items you loop over fail Account.create! you may be left in a bad state, so you may want to wrap this in an Active Record Transaction.

ActiveRecord::Base.transaction do
  [person1, person2].each{|person| Account.create!(person: person)}
end

Upvotes: 3

Related Questions