Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails select - unwanted automatic typecast

DBMS is PostgreSQL.

In controller:

@data = current_user.myitems.all(:select => 'record_date, count(record_date) as value', :group => 'record_date')

In a view:

<% @data.each do |item| -%>
   <%= item.record_date.utc.strftime('%Y%m%d') %>
<% end -%>

Everything is working fine.

But if I change date field name:

@data = current_user.myitems.all(:select => 'record_date as recdate, count(record_date) as value', :group => 'record_date')

<% @data.each do |item| -%>
   <%= item.recdate.utc.strftime('%Y%m%d') %>
<% end -%>

I get the error message:

undefined method `utc' for "2012-02-09 17:03:47":String

WTF??!! I did not order to cast the type to string!!!

You may suggest not to make an alias in SQL string or to define aliases in model, but I do not want to change models to make aliases for columns, as I need aliases only once and for display purposes only. Controller's method has "case" statement where multiple select statements are present, each with its own column names. I need to make aliases to have solid view, without "if" statements.

like image 512
Paul Avatar asked Jun 05 '26 10:06

Paul


1 Answers

You get the types of a postgres query via ftype. ActiveRecord uses this information in the postgres adapter (method #result_as_array) to check wherever columns need escaping then throws away this information.

My guess on the further data flow would be that it takes the column name and uses the data gained via reflection from the database to determine the type. Since the basic type is String, you get that. So, use the column types rails expects or hack the postgres adapter and ActiveRecord to ask the column types via ftype.

tl;dr: Alias the stuff on the Ruby side (in the model somewhere) AR doesn't like what you're doing.

like image 176
Reactormonk Avatar answered Jun 07 '26 01:06

Reactormonk



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!