Reputation: 51
I am currently struggling with something which should be pretty straightforward in Rails.
I would like to issue one ActiveRecord query and fetch model objects from the database and subsequently store those in a hash for later lookup.
I have done some research but haven't found the optimal way to accomplish this, so would appreciate some help. My intention is to reduce the number of sql queries using lookup hashes in loop structures.
In the pseudo code below, I am fetching status codes from an sms gateway and compare those with an ActiveRecord table will all status-code descriptions.
#Status_codes in array format
status_codes = StatusCode.all
status_codes_hash = status_codes.to_array????
#Fetch delivery-status from sms gateway
response = HTTParty.get(myUrl)
response.each do |status|
if status_codes_hash[status.code]
#Do stuff
end
end
Upvotes: 4
Views: 9822
Reputation: 17949
The shortest version for ActiveRecord:
Currency.all.map { [_1.iso_code, _1] }.to_h
returns:
=> { 'USD' => #<Currency id: 1, territory: "United States", name: "United States dollar", symbol: "$", iso_code: "USD", ...
Upvotes: 0
Reputation: 707
You can construct a Hash with an array of key value pairs like this:
Hash[/an array of key values goes here/]
So all you have to do is convert your StatusCodes to key value pairs and use it as input for Hash[]
like this
Hash[status_codes.map{|sc|[sc.code, sc]}]
Should do the trick
http://www.ruby-doc.org/core-1.9.3/Hash.html#method-c-5B-5D
Upvotes: 2
Reputation: 8517
You convert a model instance to hash via the attributes method:
StatusCode.all.map(&:attributes)
#=> [{ id: 1, code: 404, ...}, { id: 2, code: 405, ...}, ...]
Upvotes: 6
Reputation: 3789
The inject
method is a convenient way to do what you're looking for, I think.
status_codes_hash = status_codes.inject({}) do |hash, obj|
hash[obj.code] = obj
end
Upvotes: 0
Reputation: 2716
Use this snippet to get your hash of statuses with their codes as keys:
status_codes.group_by(&:code)
The snippet is a shortcut for status_codes.group_by{|status| status.code}
It would also be better and more universal to check the key like this:
if status_codes_hash.has_key?(status.code)
# do stuff
end
Upvotes: 4