2015-01-23 6 views
10

Ho un modello Rails che ha una colonna del database di tipo "JSON":Come utilizzare il JSON tipo di campo ActiveRecord

create_table "games", force: true do |t| 
    t.json  "game_board" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
end 

Grande! Ora come lo uso? È davvero semplice come treating the field like a Hash?

self.game_board[:player1] = 1 
self.game_board[:cards] = cards.to_hash 

Se dovessi scrivere che, sarebbe tutto solo funziona come previsto, quindi in un futuro chiamata API da un client ho potuto fare questo ?:

self.game_board[:player] # And get back the 1 that I put here before 

Che dire di prestazioni pure? L'intero game_board verrà de-serializzato ogni volta anche se quel campo non viene mai letto? Il campo verrà riscritto (IOW una scrittura del database) ogni volta che cambio una parte di "Hash?"

risposta

20

Sì, ActiveRecord consente di utilizzare i campi json di Postgres semplicemente come Hash nei loro modelli. Tuttavia, ci sono un paio di cose da considerare:

  1. Hash può essere NULL su inizializzazione
    Nella tua create_table di migrazione si consente il campo per essere :game_boardNULL. Pertanto, al primo utilizzo il campo :game_board dell'istanza modello sarà NULL e sarà necessario inizializzare l'hash prima di utilizzarlo. (Vedi esempio qui sotto)

  2. in JSON tutti i tasti sono stringhe
    Così, da salvare (e ricarica) tutti i tasti saranno trasformati in stringhe se avete usato simboli o numeri prima. Pertanto, per evitare comportamenti indesiderati si consiglia di utilizzare chiavi stringa a meno che l'ORM non sia configurato per simbolizzare tutte le chiavi.


I suoi esempi:

self.game_board   ||= {} 
self.game_board[:player1] = 1 
self.game_board[:cards] = cards.to_hash 

# after reload from database (access via String-key): 
self.game_board['player1'] # And retrieve value 1 (that we put here before) 


@ Prestazioni:

  1. Sì, ogni volta che ActiveRecord legge una voce dal database e crea un modello di istanza, JSON i campi non vengono serializzati in Hash. Ma se pensate che sia un colpo di prestazioni per la vostra applicazione di quanto dovreste usare un campo di testo e serializzare/deserializzare JSON/Hash quando è necessario o, ancora meglio, non usare affatto ActiveRecord. Creando un mucchio di classi e utilizzando metodi magici, ActiveRecord crea un sovraccarico tale da non doversi preoccupare della deserializzazione di JSON. La convenienza ha i suoi costi.

  2. Sì, ogni volta che si modifica un valore nell'Hash, il campo (intero) JSON viene sostituito e aggiornato con la nuova versione serializzata.
    Due note su questo:

    • Anche in Postgres per sé (non solo in ActiveRecord) la possibilità di effettuare aggiornamenti su alcuni JSON-elementi manca fino ad ora. Compare this Stackoverflow-question
    • In generale, i campi JSON devono essere utilizzati con una struttura fissa o, almeno, in dimensioni gestibili e il tipo di campo non deve essere un archivio di documenti come ad es. in MongoDB.Compare the Postgres documentation