获取ActiveRecord对象中的属性类型

Mic*_*ale 65 ruby activerecord ruby-on-rails activemodel

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

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

ar.attribute_names.each { |name| puts name }
Run Code Online (Sandbox Code Playgroud)

.attributes只返回名称到其当前值的映射(例如,如果未设置字段,则不返回类型信息).

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

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

>> Driver
=> Driver(id: integer, name: string, created_at: datetime, updated_at: datetime)
Run Code Online (Sandbox Code Playgroud)

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

我也感兴趣的是,如果有一种方式对新的"ActiveModel"来说是友好的(rails3)并且与数据库细节分离(但也许类型信息不会是它的一部分,我似乎无法找出它是否是).

谢谢.

Gra*_*ier 100

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

Driver.columns_hash["name"].type  #returns :string
Run Code Online (Sandbox Code Playgroud)

如果你想迭代它们,你会做这样的事情:

Driver.columns_hash.each {|k,v| puts "#{k} => #{v.type}"}
Run Code Online (Sandbox Code Playgroud)

这将输出以下内容:

id => integer
name => string
created_at => datetime
updated_at => datetime
Run Code Online (Sandbox Code Playgroud)


Mik*_*cic 22

您可以通过执行以下操作来访问列的类型:

#script/console
Driver.columns.each {|c| puts c.type}
Run Code Online (Sandbox Code Playgroud)

如果要获取特定模型中所有列类型的列表,可以执行以下操作:

Driver.columns.map(&:type) #gets them all
Driver.columns.map(&:type).uniq #gets the unique ones
Run Code Online (Sandbox Code Playgroud)


Mat*_*tW. 16

在Rails 5中,您可以独立于数据库执行此操作.如果您使用新的Attributes API来定义(附加)属性,这一点很重要.

从模型类获取所有属性:

pry> User.attribute_names
=> ["id",
 "firstname",
 "lastname",
 "created_at",
 "updated_at",
 "email",...
Run Code Online (Sandbox Code Playgroud)

获得类型:

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

有时候这些信息比需要的更多.有一个便利功能,将所有这些类型映射到核心集(:整数,:字符串等)

> User.type_for_attribute('email').type
=> :string 
Run Code Online (Sandbox Code Playgroud)

您还可以使用返回'name': type哈希值的attribute_types在一次调用中获取所有数据.

  • 这也适用于Rails 4.2.重要的是要注意`type_for_attribute('id')`只接受一个字符串.这有点令人困惑,因为`type_for_attribute('id').type`返回一个符号. (3认同)

Ami*_*min 6

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

Model_Name.attribute_names.each do |k| puts "#{k} = #{Model_Name.type_for_attribute(k).type}" end
Run Code Online (Sandbox Code Playgroud)


xan*_*ler 5

此代码片段将为您提供模型的所有属性以及哈希中关联的数据库数据类型。只需将 Post 替换为您的 Active Record 模型即可。

Post.attribute_names.map {|n| [n.to_sym,Post.type_for_attribute(n).type]}.to_h
Run Code Online (Sandbox Code Playgroud)

将返回这样的哈希值。

=> {:id=>:integer, :title=>:string, :body=>:text, :created_at=>:datetime, :updated_at=>:datetime, :topic_id=>:integer, :user_id=>:integer} 
Run Code Online (Sandbox Code Playgroud)


est*_*ani 5

Rails 5+(也适用于虚拟属性):

Model.attribute_types['some_attribute'].type
Run Code Online (Sandbox Code Playgroud)