2015-10-04 16 views
6

Come posso creare una migrazione in ruby ​​dove il valore predefinito è una stringa piuttosto che un numero intero, voglio memorizzare enum nel database, ma non voglio memorizzarlo come Integer, perché non ha senso per un'altra applicazione che vuole utilizzare la stessa tabella. Come posso fare default: "female" invece di default:0Come memorizzare enum come stringa nel database nelle guide

class AddSexToUsers < ActiveRecord::Migration 
    def change 
    add_column :users, :sex, :integer, default: 0 
    end 
end 
class User < ActiveRecord::Base 
    enum sex: [:female, :male] 
    has_secure_password 
end 

ho

+0

cosa del database stai usando? –

+0

Sto usando sqlite per lo sviluppo e mysql per la produzione –

risposta

0

A mia conoscenza non è possibile con lo standard Rails enum. Guardare https://github.com/lwe/simple_enum, è più ricco di funzioni e consente anche di memorizzare i valori enum come stringhe su DB (tipo di colonna stringa, cioè varchar in termini di DB).

9

enum in Rails e ENUM type in MySQL sono 2 cose diverse.

  1. enum in Rails è solo un wrapper per la vostra colonna integer così è più facile per voi da usare le stringhe nelle query, piuttosto che interi. Ma a livello di database è tutto convertito in numeri interi (automaticamente da Rails), poiché questo è il tipo di colonna.

  2. ENUM tipo in MySQL è specifico del fornitore tipo di colonna (ad esempio, SQLite doesn't support it, ma PostgreSQL does). In MySQL:

un enum è un oggetto stringa con un valore scelto da un elenco di valori consentiti che sono enumerate in modo esplicito nella specifica colonna al momento della creazione della tabella.

CREATE TABLE shirts (
    name VARCHAR(40), 
    size ENUM('x-small', 'small', 'medium', 'large', 'x-large') 
); 
INSERT INTO shirts (name, size) VALUES ('dress shirt','large'), ('t-shirt','medium'), 
    ('polo shirt','small'); 
SELECT name, size FROM shirts WHERE size = 'medium'; 
+---------+--------+ 
| name | size | 
+---------+--------+ 
| t-shirt | medium | 
+---------+--------+ 

per la migrazione, è necessario fare questo:

class AddSexToUsers < ActiveRecord::Migration 
    def change 
    add_column :users, :sex, "ENUM('female', 'male') DEFAULT 'female'" 
    end 
end 
+1

Se si segue questo percorso, è necessario passare ai dump dello schema SQL, altrimenti Rails inserirà un tipo di colonna di stringa nel file schema.rb. Passare con quanto segue in config/application.rb: 'config.active_record.schema_format =: sql' –

11

Leggendo la documentazione enum, è possibile vedere Rails utilizzano l'indice valore del Array spiegato come:

Si noti che quando viene utilizzata una matrice, il mapping implicito dai valori agli interi del database è derivato dall'ordine in cui i valori appaiono nell'array.

Ma è anche affermato che è possibile utilizzare una Hash:

è anche possibile mappare in modo esplicito il rapporto tra attributi e interi database con un hash.

Con l'esempio:

class Conversation < ActiveRecord::Base 
    enum status: { active: 0, archived: 1 } 
end 

Così ho testato utilizzando Rails 4.2.4 e sqlite3 e ha creato una classe User con un tipo string per sesso tipo e un Hash nelle enum con string valori (sto usando fem e mal valori differiscano da femminile e maschio):

migrazione:

class CreateUsers < ActiveRecord::Migration 
    def change 
    create_table :users do |t| 
     t.string :sex, default: 'fem' 
    end 
    end 
end 

Modello:

class User < ActiveRecord::Base 
    enum sex: { female: 'fem', male: 'mal' } 
end 

E in console:

u = User.new 
#=> #<User id: nil, sex: "fem"> 
u.male? 
#=> false 
u.female? 
#=> true 
u.sex 
#=> "female" 
u[:sex] 
#=> "fem" 
u.male! 
# INSERT transaction... 
u.sex 
#=> "male" 
u[:sex] 
#=> "mal" 
+2

quindi nel db è memorizzato' fem'? –

0

faccio le seguenti per memorizzare gli stati di stringa e utilizzare i vantaggiosi Rails metodi di supporto:

def self.up 
    add_column :works, :status, :string, null: false, default: 'offering' 
end 

class Work < ApplicationRecord 
    ALL_STATES = %w[canceled offering running payment rating done].freeze 
    enum status: ALL_STATES.zip(ALL_STATES).to_h 
end 
Problemi correlati