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类型并相应地应用转换。
答案 0 :(得分:1)
如果您设置了ActiveRecord类,则可以访问其columns
和columns_hash
方法。这些将为您提供列对象(ActiveRecord::ConnectionAdapters::Column
的实例),您应该找到type
和sql_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提供给execute
或select_rows
。这将允许您使用大多数通常的ActiveRecord内容,同时避免创建一堆您不关心的ActiveRecord包装器的开销。
答案 1 :(得分:1)
type_cast_for_database是专门在竞技场中有用的东西。可以在arel表上使用:
int a(Payment payment){
payment.setValue(payment.getValue() - 1);
return payment.getValue() * 10;
}
虽然您没有明确获得类型,但是您可以看到诸如字符串之类的值是否将转换为数字或其他内容。
编辑
重要的是要注意,这仅在arel表具有type_caster able_to_type_cast?的情况下有效。如果从上述模型中获得它,则它应该具有类型转换程序。