2017-08-15 1 views
0

J'ai une colonne JSON dans mon modèle qui est un hachage vide par défaut.Utiliser la fusion! ou deep_merge! mettre à jour le hachage dans le modèle activerecord

Je veux vérifier si des clés spécifiques sont présentes et sinon pour fusionner le hachage vide avec un hachage par défaut avec les clés.

Dans mon modèle je vérifie si un utilitaire (eau, gaz ou électrique est présent) et si pas alors insérer ce hachage par défaut:

def default_config 
    {:config => {"features" => {"utilities" => {"water" => true, "gas" => true, "electric" => true}}}} 
end 

c'est ainsi que je vérifie pour savoir si un utilitaire clé est présente:

def water 
    has_water? || parent.has_water? 
    end 

qui à son tour appelle ces méthodes (tous dans mon modèle):

def utility(util) 
    self[:config].try(:fetch, "features", nil).try(:fetch, "utilities", nil).try(:fetch, "#{util}", nil) 
    end 

    def has_water? 
    utility("water") == true 
    end 

Ceci afin de pouvoir configurer la colonne JSON si les clés déjà présentes, que je tente ici:

def set_water(boolean) 
    new_val = cleaned_boolean(boolean) 
    water ? nil : self[:config].deep_merge!(default_config) 
    self[:config]["features"]["utilities"]["water"] = new_val 
    end 

Quand je teste ce que je reçois

undefined method `[]=' for nil:NilClass 

Erreur lors de la tentative de définition d'une valeur d'utilitaire indiquant que mon default_config n'est pas fusionné dans le hachage vide existant.

+0

Vous pouvez essayer d'utiliser 'force d'arrachage byebug' et de mettre un point d'arrêt avec 'binding.pry' pour voir ce qui est réellement assigné à chaque var. – Kris

Répondre

2

reverse_merge! est la manière habituelle de définir des valeurs par défaut pour un Hash dans rails.

self[:config].reverse_merge!(default_config) 

c'est sensiblement égale à:

default_config.merge!(self[:config]) 

Laissant tout self[:config] intact et la fusion juste dans les paires de valeurs clés manquantes de default_config.

également cette expression ternaire:

water ? nil : self[:config].deep_merge!(default_config) 

est plus idiomatiques écrit en (utilisant Hash#reverse_merge!)

self[:config].reverse_merge!(default_config) unless water 

et depuis water retourne une valeur boolean il est généralement écrit comme une question par exemple water? (comme dans has_water?) Je ne sais pas si la méthode water est utilisé fréquemment, mais je factoriser comme

def has_water?(include_parent=false) 
    utility("water") == true || (include_parent && parent.has_water?) 
end 

appellent Puis, comme:

self[:config].reverse_merge!(default_config) unless has_water?(true)