1

tl;dr给定一个Arel::Attributes::Attribue对象,说Model.arel_table[:created_at]如何获得它的 SQL 类型?

背景:我正在绕过 ActiveRecord 基础设施,支持 Arel 编写一些需要真正有效生成的 SQL 报告。使用 Arel 的to_sql方法,我正在生成最终的 SQL 并直接通过ActiveRecord::Base.connection.execute. 但是,我需要将 SQL 转换应用于某些列(例如,更改存储在 GMT 中的时间戳的时区)。由于列数很大(并且根据用户输入而变化),我不想对这些转换进行硬编码。我想查看所选列的 SQL 类型并相应地应用转换。

4

2 回答 2

2

如果您设置了 ActiveRecord 类,那么您可以访问它的columnscolumns_hash方法。这些将为您提供列对象(的实例) ,ActiveRecord::ConnectionAdapters::Column您应该在那里找到方法。例如:typesql_type

> Model.columns_hash['created_at'].type
 => :datetime 
> Model.columns_hash['created_at'].sql_type
 => "timestamp without time zone"

sql_type是特定于数据库的(即上面的 PostgreSQL),type将与迁移中的类型匹配,因此您可能希望使用它而不是sql_type.

也就是说,您可能会使用通常的 ActiveRecord 关系方法(它应该为您处理转换和时区)然后to_sql在最后调用:

sql = Model.where('created_at > ?', some_time).select('pancakes').to_sql

然后将该 SQL 输入executeor select_rows。这将使您可以使用大多数常用的 ActiveRecord 东西,同时避免创建一堆您不关心的 ActiveRecord 包装器的开销。

于 2013-02-03T06:00:04.380 回答
1

在 arel 中可能特别有用的东西是type_cast_for_database。这可以在 arel 表上使用:

Model.arel_table.type_cast_for_database(:id, 'test')
=> 0
Model.arel_table.type_cast_for_database(:id, '47test')
=> 47

虽然您没有具体了解类型,但您可以查看字符串之类的值是否将转换为数字或其他内容。

编辑

需要注意的是,这仅在 arel 表具有 type_casterable_to_type_cast时才有效?. 如果你从上面的模型中得到它,它应该有一个类型脚轮。

于 2018-08-21T20:48:43.827 回答