web-dev-qa-db-fra.com

Obtention des types d'attributs dans un objet ActiveRecord

Je voudrais savoir s'il est possible d'obtenir les types (tels que connus par AR - par exemple dans le script de migration et la base de données) par programme (je sais que les données existent quelque part).

Par exemple, je peux gérer tous les noms d'attributs:

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

.attributes renvoie simplement un mappage des noms à leurs valeurs actuelles (par exemple, aucune information de type si le champ n'est pas défini).

Certains endroits, je l'ai vu avec les informations de type:

dans script/console, tapez le nom d'une entité AR:

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

Il connaît donc clairement les types. En outre, il existe .column_for_attribute, qui prend un nom attr et renvoie un objet colonne - dont le type est enfoui dans l'objet colonne de la base de données sous-jacente, mais il ne semble pas être un moyen propre de l'obtenir.

Je serais également intéressé s'il existe un moyen convivial pour le nouveau "ActiveModel" qui arrive (Rails3) et est découplé des spécificités de la base de données (mais peut-être que les informations de type ne feront pas partie de celui-ci, je ne peux pas sembler savoir si c'est le cas).

Merci.

61
Michael Neale

Dans Rails 3, pour votre modèle "Driver", vous voulez Driver.columns_hash.

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

Si vous voulez les parcourir, vous feriez quelque chose comme ceci:

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

qui affichera les éléments suivants:

id => integer
name => string
created_at => datetime
updated_at => datetime
95
Grant Birchmeier

Vous pouvez accéder aux types de colonnes en procédant comme suit:

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

Si vous souhaitez obtenir une liste de tous les types de colonnes dans un modèle particulier, vous pouvez:

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

Dans Rails 5, vous pouvez le faire indépendamment de la base de données. C'est important si vous utilisez la nouvelle API Attributes pour définir des attributs (supplémentaires).

Obtenir tous les attributs d'une classe de modèle:

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

Obtenir le type:

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

C'est parfois plus d'informations que nécessaire. Il existe une fonction pratique qui mappe tous ces types vers un ensemble de base (: entier,: chaîne, etc.)

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

Vous pouvez également obtenir toutes ces données en un seul appel avec attribute_types qui renvoie un 'name': type hachage.

16
MattW.

Dans Rails 5, cela vous donnera une liste de tous les noms de champs avec leur type de données:

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

Cet extrait vous donnera tous les attributs d'un modèle avec les types de données de base de données associés dans un hachage. Remplacez simplement Post par votre modèle d'enregistrement actif.

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

Renvoie un hachage comme celui-ci.

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