2017-01-21 3 views
3

Je développe actuellement une petite application Rails 5 dans laquelle je dois transmettre un objet ActiveRecord à un service externe en fonction de certains événements. Dans mon modèle, je l'ai défini comme suit:Inclure dynamiquement des associations d'objets dans Rails

# /models/user.rb 
after_create :notify_external_service_of_user_creation 

def notify_external_service_of_user_creation 
    EventHandler.new(
    event_kind: :create_user, 
    content: self 
) 
end 

Le EventHandler est ensuite cet objet à convertissent JSON et est l'envoyer par une requête HTTP au service externe. En appelant .to_json sur l'objet ce qui rend une sortie JSON qui ressemblerait à quelque chose comme ceci:

{ 
    "id":1234, 
    "email":"[email protected]", 
    "first_name":"Thomas", 
    "last_name":"Anderson", 
    "association_id":12, 
    "another_association_id":356 
} 

Maintenant, je besoin d'un moyen d'inclure toutes les associations de premier niveau directement dans ce, au lieu de simplement montrer l'foreign_key. Ainsi, la construction Je cherche serait quelque chose comme ceci:

{ 
    "id":1234, 
    "email":"[email protected]", 
    "first_name":"Thomas", 
    "last_name":"Anderson", 
    "association_id":{ 
    "attr1":"some_data", 
    "attr2":"another_value" 
    }, 
    "another_association_id":{ 
    "attr1":"some_data", 
    "attr2":"another_value" 
    }, 
} 

Ma première idée était de réfléchir sur le modèle comme ceci: object.class.name.constantize.reflect_on_all_associations.map(&:name), où object est une instance d'un utilisateur dans ce cas, et utiliser cette liste faire une boucle sur les associations et les inclure dans la sortie. Cela semble plutôt fastidieux, donc je me demandais s'il y aurait une meilleure façon d'y parvenir en utilisant Ruby 2.4 et Rails 5.

+0

Qu'est-ce que vous utilisez pour la sérialisation JSON? https://github.com/rails-api/active_model_serializers prend en charge les associations. – MikDiet

+0

@MikDiet J'appelle '.to_json' sur l'obejct, c'est tout. – Severin

Répondre

0

Si vous ne voulez pas utiliser un sérialiseur externe, vous pouvez remplacer as_json pour chaque modèle . as_json est appelé par to_json.

module JsonWithAssociations 
    def as_json 
    json_hash = super 

    self.class.reflect_on_all_associations.map(&:name).each do |assoc_name| 
     assoc_hash = if send(assoc_name).respond_to?(:first) 
        send(assoc_name).try(:map, &:as_json) || [] 
        else 
        send(assoc_name).as_json 
        end 

     json_hash.merge!(assoc_name.to_s => assoc_hash) 
    end 

    json_hash 
    end 
end 

Vous devez prepend ce module particulier afin qu'il remplace la méthode par défaut as_json.

User.prepend(JsonWithAssociations) 

ou

class User 
    prepend JsonWithAssociations 
end