获取 ActiveRecord 对象中的属性类型

我想知道是否有可能以编程的方式获得类型(如在迁移脚本和数据库中的 AR-eg 所知)(我知道数据存在于其中的某个地方)。

例如,我可以处理所有属性名称:

ar.attribute_names.each { |name| puts name }

.属性只返回名称到它们当前值的映射(例如,如果没有设置字段,则不返回类型信息)。

我在一些地方看到过类型信息:

在 script/sole 中,键入 AR 实体的名称:

>> Driver
=> Driver(id: integer, name: string, created_at: datetime, updated_at: datetime)

所以很明显它知道类型。还有。Column _ for _ tribute,它接受 attr 名称并返回一个列对象——其类型隐藏在底层数据库列对象中,但似乎不是获取该类型的简单方法。

我还想知道是否有一种方法可以友好地应用即将推出的新的“ ActiveModel”(Rails3) ,并且与数据库细节分离(但是类型信息可能不是其中的一部分,我似乎无法找到它是否是)。

谢谢。

53380 次浏览

您可以通过以下方法访问列的类型:

#script/console
Driver.columns.each {|c| puts c.type}

如果希望获得特定 Model 中所有列类型的列表,可以这样做:

Driver.columns.map(&:type) #gets them all
Driver.columns.map(&:type).uniq #gets the unique ones

在 Rails 3中,对于您的模型“ Driver”,您需要 Driver.columns_hash

Driver.columns_hash["name"].type  #returns :string

如果你想遍历它们,你可以这样做:

Driver.columns_hash.each {|k,v| puts "#{k} => #{v.type}"}

它将产生以下结果:

id => integer
name => string
created_at => datetime
updated_at => datetime

在 Rails 5中,您可以独立于数据库执行此操作。如果您使用新的 AttributesAPI 来定义(其他)属性,那么这一点非常重要。

从模型类获取所有属性:

pry> User.attribute_names
=> ["id",
"firstname",
"lastname",
"created_at",
"updated_at",
"email",...

类型:

pry> User.type_for_attribute('email')
=> #<ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::MysqlString:0x007ffbab107698
@limit=255,
@precision=nil,
@scale=nil>

有时候信息量太大了。有一个方便的函数可以将所有这些类型映射到一个核心集(整数、字符串等)

> User.type_for_attribute('email').type
=> :string

您还可以使用属性 _ type 在一次调用中获取所有数据,该属性返回一个 'name': type散列。

此代码片段将为您提供一个模型的所有属性,其中包含哈希中的相关数据库数据类型。只需用活动记录模型替换 Post 即可。

Post.attribute_names.map {|n| [n.to_sym,Post.type_for_attribute(n).type]}.to_h

将返回这样的散列。

=> {:id=>:integer, :title=>:string, :body=>:text, :created_at=>:datetime, :updated_at=>:datetime, :topic_id=>:integer, :user_id=>:integer}

在 Rails 5中,这将为您提供所有字段名及其数据类型的列表:

Model_Name.attribute_names.each do |k| puts "#{k} = #{Model_Name.type_for_attribute(k).type}" end

Rails 5 + (也可以使用虚拟属性) :

Model.attribute_types['some_attribute'].type

在 Rails 4中,您将使用 Column _ type

假设 Foobar是你的活动记录模型,你也可以这样做:

attributes = Foobar.attribute_names.each_with_object({}) do |attribute_name, hash|
hash[attribute_name.to_sym] = Foobar.type_for_attribute(attribute_name).type
end

也可以在 Rails 4上工作