Hello-- There must be a better way to do this. I have a class method in my model that finds averages and does a few calculations using find_by_sql. The problem I¹m encountering is that all computed columns from MySQL come back as type string. E.g., def self.find_averages(domain_id) if @@domain_average return @@domain_average else @@domain_average = MyDomain.find_by_sql(["select avg(latency) as latency, avg(datediff(session_end, session_start)) as session_duration from live_logs where domain_id=?"], domain_id])[0] end end The problem is that I¹m using a lot of to_f conversions because type coercions are not happening as I would have expected. Again, for example: foo = MyDomain.find_averages(1) bar = foo[:latency] / 3.0 # fails because foo[:latency] is a string and Ruby won¹t do the coercion zoo = foo[:latency].to_f / 3.0 # succeeds because I did the coercion explicitly, but code is more brittle Does anyone have a thought has to how this might better be achieved? Thanks _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
You need to provide manual casting of these types. The preferred mechanism is to override the default accessors: Class MyDomain < ActiveRecord::Base def latency Float(read_attribute("latency")) end end Then you can write your code: bar = foo.latency / 3.0 I just re-read this section of the Ruby on Rails book.. _____ From: Steve Ross [mailto:sross-ju+vs0qJmycyYsO2DCxJlVaTQe2KTcn/@public.gmane.org] Sent: Friday, October 28, 2005 2:30 PM To: rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org Subject: [Rails] find_by_sql column types Hello-- There must be a better way to do this. I have a class method in my model that finds averages and does a few calculations using find_by_sql. The problem I''m encountering is that all computed columns from MySQL come back as type string. E.g., def self.find_averages(domain_id) if @@domain_average return @@domain_average else @@domain_average = MyDomain.find_by_sql(["select avg(latency) as latency, avg(datediff(session_end, session_start)) as session_duration from live_logs where domain_id=?"], domain_id])[0] end end The problem is that I''m using a lot of to_f conversions because type coercions are not happening as I would have expected. Again, for example: foo = MyDomain.find_averages(1) bar = foo[:latency] / 3.0 # fails because foo[:latency] is a string and Ruby won''t do the coercion zoo = foo[:latency].to_f / 3.0 # succeeds because I did the coercion explicitly, but code is more brittle Does anyone have a thought has to how this might better be achieved? Thanks _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
This should work: @@domain_average = MyDomain.find_by_sql(["select avg(latency) as latency from live_logs where domain_id=?", domain_id])[0][''latency''].to_f -lv Steve Ross wrote:> Hello-- > > There must be a better way to do this. I have a class method in my model > that finds averages and does a few calculations using find_by_sql. The > problem I’m encountering is that all computed columns from MySQL come > back as type string. E.g., > > def self.find_averages(domain_id) > if @@domain_average > return @@domain_average > else > @@domain_average = MyDomain.find_by_sql(["select avg(latency) as > latency, avg(datediff(session_end, session_start)) as session_duration > from live_logs where domain_id=?"], domain_id])[0] > end > end...
Except that this only works where find_by_sql is returning one column. My find is returning about seven. I''ve settled on: @@domain_average.foo = @@domain_average.foo.to_f @@domain_average.bar = @@domain_average.bar.to_f at the end of my get_averages() function. Somehow, it seems like a hack. Comments? On 10/28/05 3:06 PM, "Lou Vanek" <vanek-9H8CmIPm+GA@public.gmane.org> wrote:> This should work: > > @@domain_average = MyDomain.find_by_sql(["select avg(latency) as > latency from live_logs where domain_id=?", domain_id])[0][''latency''].to_f > > -lv > > Steve Ross wrote: > >> Hello-- >> >> There must be a better way to do this. I have a class method in my model >> that finds averages and does a few calculations using find_by_sql. The >> problem I¹m encountering is that all computed columns from MySQL come >> back as type string. E.g., >> >> def self.find_averages(domain_id) >> if @@domain_average >> return @@domain_average >> else >> @@domain_average = MyDomain.find_by_sql(["select avg(latency) as >> latency, avg(datediff(session_end, session_start)) as session_duration >> from live_logs where domain_id=?"], domain_id])[0] >> end >> end > ... > >
any number of fields can be returned at one time because find_by_sql returns an array of hashes. An example with two fields returned: record = MyDomain.find_by_sql(["select avg(latency) as latency, avg(field2) as avgfld2 from live_logs where domain_id=?", domain_id])[0] @@domain_average = record[''latency''].to_f @@avgfld2 = record[''avgfld2''].to_f Steve Ross wrote:> Except that this only works where find_by_sql is returning one column. My > find is returning about seven. I''ve settled on: > > @@domain_average.foo = @@domain_average.foo.to_f > @@domain_average.bar = @@domain_average.bar.to_f > > at the end of my get_averages() function. > > Somehow, it seems like a hack. > > Comments? > > > On 10/28/05 3:06 PM, "Lou Vanek" <vanek-9H8CmIPm+GA@public.gmane.org> wrote: > > >>This should work: >> >>@@domain_average = MyDomain.find_by_sql(["select avg(latency) as >> latency from live_logs where domain_id=?", domain_id])[0][''latency''].to_f >> >>-lv >> >>Steve Ross wrote: >> >> >>>Hello-- >>> >>>There must be a better way to do this. I have a class method in my model >>>that finds averages and does a few calculations using find_by_sql. The >>>problem I¹m encountering is that all computed columns from MySQL come >>>back as type string. E.g., >>> >>>def self.find_averages(domain_id) >>> if @@domain_average >>> return @@domain_average >>> else >>> @@domain_average = MyDomain.find_by_sql(["select avg(latency) as >>>latency, avg(datediff(session_end, session_start)) as session_duration >>>from live_logs where domain_id=?"], domain_id])[0] >>> end >>>end >> >>... >> > >