2010-03-08 98 views
55

我想知道是否有可能以编程方式获取类型(如AR所知 - 例如在迁移脚本和数据库中)(我知道数据存在于某处) 。在ActiveRecord对象中获取属性的类型

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

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

.attributes仅返回名称与其当前值的映射(例如,如果现场没有设置任何类型的信息)。

我与类型信息看到了一些地方:

在脚本/控制台,输入AR实体的名称:

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

所以很明显它知道的类型。另外,还有.column_for_attribute,它接受一个attr名称并返回一个列对象 - 它具有隐藏在底层数据库列对象中的类型,但它似乎不是一种干净的方式来获取它。

我也会感兴趣的是,如果有一种方法对即将到来的新的“ActiveModel”(rails3)是友好的,并且与数据库细节分离(但也许类型信息不会成为它的一部分,我可以似乎没有发现它是否是)。

谢谢。

回答

84

在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 
+0

你知道我该如何测试一个值是否与列匹配,像这样的 '2.is_a? Driver.columns_hash [“name”] .type' – mariowise 2014-07-31 19:03:04

+0

不,不知道。 – 2014-07-31 21:06:01

+0

我可以确认这仍然在Rails 4.2中工作 – Phil 2017-09-22 11:58:52

19

您可以通过执行此访问类型列:

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

如果你想在某一特定型号的所有列类型的列表,你可以这样做:

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

谢谢。我猜这不会是ActiveModel的一部分,虽然它是绑定到列(这可能不会使它到AM)。但是这对于AR来说非常棒。你知道我真的知道,在我的脑海中,但由于某种原因阻止了它。 – 2010-03-08 06:53:59

7

在Rails 5,你可以做这独立于数据库。如果使用新的Attributes API来定义(附加)属性,这一点很重要。

获得从模型类的所有属性:

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 

您也可以与attribute_types一个调用,它返回一个'name': type哈希所有的数据。

+3

这也适用于Rails 4.2。注意'type_for_attribute('id')'只接受一个字符串是很重要的。这有点令人困惑,因为'type_for_attribute('id')。type'返回一个符号。 – 2016-02-25 18:11:00

+0

如果通过数据库独立,你的意思是ORM,那么Mongoid还没有实现这个'type_for_attribute'。也许在Rails 5正式发布之后。 – 2016-03-16 15:31:23

1

该片段将为您提供模型的所有属性以及散列中的关联数据库数据类型。只需将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} 
3

在导轨5这会给你所有的字段名的列表以及它们的数据类型一起:

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

注意'type_for_attribute'需要字符串。它很高兴地使用符号或不存在的名字,返回一个不会投射的ActiveModel :: Type :: Value!海事组织的一个错误,我会尝试报告/修复。 – 2018-01-01 12:30:16