I'm querying a mysql database and returning an array of objects created by a join. From what I understand, the ActiveRecord select command returns an array of new objects, each with the properties of both tables in the join.
I want to perform some calculations on each of these objects, and associate a few attributes with the object. I understand that if this was my class, I could use the method_missing approach as seen here. However, since this object is created by the select command, I don't have class code where I can define the add_attrs
function. Is this possible? Is using method_missing the correct approach and if so, how do I implement it?
Here is the initial query which returns an array of ActiveRecord objects.
def self.select_with_location
select("advertisements.id, advertisements.weight, locations.latitude, locations.longitude")
end
If I were to go to the ruby console and type the commands
advertisements = Advertisement.joins(:locations).select_with_location
puts advertisements[0].inspect
I should get something like:
{id: 0, weight: 5, locations.latitude: 49.03030, locations.longitude: 50.5050}
Now, what I want is to iterate through the advertisements and perform a calculation on each of the weights. I want to store the results of that calculation into a new attribute of advertisement, which I want to call weight_multiplier
. After this calculation, if I go to the ruby console and type the following command:
puts advertisements[0].inspect
I would want to get the result
{id:0, weight: 5, locations.latitude: 49.03030, locations.longitude: 50.5050, weight_multiplier: 0.446003}
In this example the numbers themselves aren't important, I just want to add the weight_multiplier attribute to each of the advertisements in the array.
I know the following code is incorrect, but this is the gist of what the function will do:
def self.assign_weight_multiplier advertisements
totalWeights = advertisements.inject(0){|sum,advertisement| sum + advertisement.weight }
advertisements.each do |advertisement|
advertisement.weight_multiplier = (Float(advertisement.weight)/Float(totalWeights))
end
advertisements
end
You can add 2 new methods to your Advertisement
class
def total_weight
@total_weight ||= Advertisement.sum(:weight)
end
def weight_multiplier
self.weight.to_f / total_weight
end
then you can call weight_multiplier
as a instance method on Advertisement
instance