Hernan Acosta
Hernan Acosta

Reputation: 397

Query in Active record with an array of hash

I have the following model in Ruby

class Entity < ActiveRecord::Base
  validates :account_type, presence: true
  validates :account_id, presence: true
end

and I have an array of hashes called accounts something like:

[{'account_id':44, 'account_type':'user'},..,{'account_id':44, 'account_type':'other'}, {'account_id':88,
'account_type':'another'}]

So I want a way to obtain all the entities that match with the elements of the accounts array (account_id and account_type both at same time).

I tried using this code:

entities = []
accounts.each do |account|
    entities << Entity.where(account_id: ActiveSupport::HashWithIndifferentAccess.new(account)['account_id'])
    .where(account_type: ActiveSupport::HashWithIndifferentAccess.new(account)['account_type'])
end

But there is a way to do it more efficient ??

Upvotes: 0

Views: 2697

Answers (3)

ogabriel
ogabriel

Reputation: 301

If i got your problem, this should solve it:

entities = accounts.map { |acc| Entity.where(account_id: acc['account_id'], account_type: acc['account_type']) }

Let me explain what is happening:

  • first, the method map returns an array will all the entries that dit match with anything at the database
  • the map is interating through the accounts array, just like the each, which means it will bring the data at accounts to the where query
  • a comma between where conditions also works for comparisons, unless you are doing an or, in the case i suppose you can use this syntax: where('account_id = :id or account_type = :type', id: acc['account_id'], type: acc['account_type'])

Upvotes: 0

Ursus
Ursus

Reputation: 30056

If you're using rails 5 you could try or. Something like this

entities = Entity.none
items.each do |item|
  entities = entities.or(Entity.where(item))
end

This is just one SQL query but if the array is big I don't know how this works.

Upvotes: 1

mu is too short
mu is too short

Reputation: 434665

Given this:

[{'account_id':44, 'account_type':'user'}, {'account_id':44, 'account_type':'other'}, ... ]

the SQL you want is:

select ...
where account_id = 44 and account_type = 'user'
   or account_id = 44 and account_type = 'other'
   or ...

Note that SQL's operator precedence makes that the same as:

select ...
where (account_id = 44 and account_type = 'user')
   or (account_id = 44 and account_type = 'other')
   or ...

You can build a query like that using ActiveRecord but it is a little cumbersome due to the way #or works:

accounts = your_array_of_hashes
entities = accounts.inject(Entity.none) { |memo, h| memo.or(Entity.where(h)) }

Upvotes: 3

Related Questions