32 votes

Imbriquée à la création d'objet JSON dans les Rails

Comment puis-je passer JSON à une application RAILS, de sorte qu'il sera créé imbriquée à l'enfant des objets dans un has_many relation?

Voici ce que j'ai à ce jour:

Deux objets de modèle.

class Commute < ActiveRecord::Base
  has_many :locations
  accepts_nested_attributes_for :locations, :allow_destroy => true
end

class Location < ActiveRecord::Base
  belongs_to :commute
end

Avec la navette, j'ai un contrôleur standard mis en place. Je voudrais être en mesure de créer un Commute objet ainsi que plusieurs enfants de l'Emplacement des objets dans une seule RESTE l'appel à l'aide de JSON. J'ai essayé des choses comme ceci:

curl -H "Content-Type:application/json" -H "Accept:application/json" 
-d "{\"commute\":{\"minutes\":0, 
\"startTime\":\"Wed May 06 22:14:12 EDT 2009\", 
\"locations\":[{\"latitude\":\"40.4220061\",
\"longitude\":\"40.4220061\"}]}}"  http://localhost:3000/commutes

Ou des plus lisible, le JSON est:

{
    "commute": {
        "minutes": 0,
        "startTime": "Wed May 06 22:14:12 EDT 2009",
        "locations": [
            {
                "latitude": "40.4220061",
                "longitude": "40.4220061"
            }
        ]
    }
}

Quand je l'exécuter, j'obtiens ce résultat:

Processing CommutesController#create (for 127.0.0.1 at 2009-05-10 09:48:04) [POST]
  Parameters: {"commute"=>{"minutes"=>0, "locations"=>[{"latitude"=>"40.4220061", "longitude"=>"40.4220061"}], "startTime"=>"Wed May 06 22:14:12 EDT 2009"}}

ActiveRecord::AssociationTypeMismatch (Location(#19300550) expected, got HashWithIndifferentAccess(#2654720)):
  app/controllers/commutes_controller.rb:46:in `new'
  app/controllers/commutes_controller.rb:46:in `create'

Il ressemble à l'emplacement tableau JSON est de le lire, mais pas interprétée comme un objet d'Emplacement.

Je peux facilement changer soit le client ou le serveur, de sorte que la solution pourrait venir de chaque côté.

Donc, ne RAILS de rendre cela facile à faire pour moi? Ou dois-je besoin d'ajouter dans certains de support pour cette pour mon trajet de l'objet? Peut-être ajouter un from_json méthode?

Merci pour toute aide.


Comme je l'ai déjà travaillé dans ce, une solution qui fonctionne est de modifier mon contrôleur. Mais cela ne semble pas les "rails" manière de faire, alors vous pouvez toujours vous laissez-moi savoir si il ya une meilleure façon.

def create
    locations = params[:commute].delete("locations");
    @commute = Commute.new(params[:commute])

    result = @commute.save

    if locations 
      locations.each do |location|
        @commute.locations.create(location)
      end
    end


    respond_to do |format|
      if result
        flash[:notice] = 'Commute was successfully created.'
        format.html { redirect_to(@commute) }
        format.xml  { render :xml => @commute, :status => :created, :location => @commute }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @commute.errors, :status => :unprocessable_entity }
      end
    end
  end

38voto

Marc Hughes Points 3794

Compris, l'emplacement de l'objet doit avoir été appelée locations_attributes à correspondre avec les Rails de l'objet imbriqué de création de schéma de nommage. Après avoir fait cela, il fonctionne parfaitement avec un Rails par défaut du contrôleur.

{
    "commute": {
        "minutes": 0,
        "startTime": "Wed May 06 22:14:12 EDT 2009",
        "locations_attributes": [
            {
                "latitude": "40.4220061",
                "longitude": "40.4220061"
            }
        ]
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X