Rails 5.1 API - how zu ermöglichen, params für verschachtelte JSON-Objekt Attribute

Gibt es mindestens 10 Fragen zu diesem Thema, aber keiner von Ihnen Antwort zu diesem Problem. Viele der Fragen beziehen sich auf Rails Formen wie diese, die ich nicht habe, oder, um json-Strukturen, die mehr kompliziert sind, wie diese oder diese.


BEARBEITEN in Bezug auf die akzeptierte Antwort, und warum ist dies nicht ein exaktes Duplikat

Den verlinkten Frage in der Antwort von @CarlosRoque zunächst aussieht das gleiche problem, aber es löst nur die Schienen Seite von diesem Heft.

Wenn Sie all die Kommentare Lesen, sehen Sie mehrere versuche zur änderung der template_params Methode gemacht wurden, UMBENENNEN oder ERSETZEN der geschachtelten Attribut "template_items" mit "template_items_attributes". Dies ist notwendig, weil Schienen accepts_nested_attributes_for erfordert "_attributes" angehängt, um den Namen, sonst kann er nicht sehen es.

Wenn Sie untersuchen die monkey patch-code in die Antwort zu beheben wrap_parameters, so dass es funktioniert für verschachtelte Attribute, haben Sie immer noch das problem, dass es nicht wirklich finden, "template_items" (das verschachtelte Objekt), da es nicht das suffix "_attributes".

Daher vollständig zu lösen, das der Kunde musste auch geändert werden, senden Sie das verschachtelte Objekt als "template_items_attributes". Für JS-clients diese kann getan werden, durch die Implementierung von toJSON () - Methode auf das Objekt, um es zu ändern, die während der Serialisierung (Beispiel hier). Aber bewusst sein, dass beim Deserialisieren des JSON, müssen Sie manuell erstellen Sie eine Instanz des Objekts, die für die toJSON() zu arbeiten (erklärt, warum hier).


Habe ich eine einfache has_many /belongs_to:

Modelle:

class Template < ApplicationRecord
  belongs_to :account
  has_many :template_items
  accepts_nested_attributes_for :template_items, allow_destroy: true
end


class TemplateItem < ApplicationRecord  
  belongs_to :template
  validates_presence_of :template

  enum item_type: {item: 0, heading: 1} 
end

Json an den client sieht wie folgt aus:

{
  "id": "55e27eb7-1151-439d-87b7-2eba07f3e1f7",
  "account_id": "a61151b8-deed-4efa-8cad-da1b143196c9",
  "name": "Test",
  "info": "INFO1234",
  "title": "TITLE1",
  "template_items": [
    {
      "is_completed": false,
      "item_type": "item"
    },
    {
      "is_completed": false,
      "item_type": "heading"
    }
  ]
}

Manchmal gibt es eine :id und ein :content - Attribut in jedem template_item (zB. nachdem Sie erstellt wurden und der Benutzer beginnt, Sie zu Bearbeiten).

Den template_params Methode der templates_controller sieht wie folgt aus:

   params.require(:template).permit(
      :id, :account_id, :name, :title, :info, 
      template_items: [:id, :is_completed, :content, :item_type]
  )

Wenn dies eine Rails-form dann, die Zeile wäre:

   params.require(:template).permit(
      :id, :account_id, :name, :title, :info, 
      template_items_attributes: [:id, :is_completed, :content, :item_type]
  )

zum speichern des verschachtelten Kinder Objekte als Teil der übergeordneten Vorlage update-Aktion.

Ich versucht, die änderung der verschachtelten param name:

def template_params
  params.require(:template).permit(:id, :account_id, :name, :title, :info, template_items: [:id, :is_completed, :content, :item_type])
  params[:template_items_attributes] = params.delete(:template_items) if params[:template_items]
  Rails.logger.info params
end

und ich kann sehen, Sie sind immer noch nicht erlaubt:

{  
      "template"   =><ActionController::Parameters   {  
      "id"      =>"55e27eb7-1151-439d-87b7-2eba07f3e1f7",
      "account_id"      =>"a61151b8-deed-4efa-8cad-da1b143196c9",
      "name"      =>"Test",
      "info"      =>"INFO1234",
      "title"      =>"TITLE1",
   }   permitted:false   >,
   "template_items_attributes"   =>   [  
      <ActionController::Parameters      {  
         "is_completed"         =>false,
         "item_type"         =>"item"
      }      permitted:false      >,
      <ActionController::Parameters      {  
         "is_completed"         =>false,
         "item_type"         =>"item"
      }      permitted:false      >
   ]
}

Ich habe auch versucht Zusammenführen:

template_params.merge! ({template_items_attributes:
params[:template_items]}) if params[:template_items].present?

Gleiche problem.

Also, wie kann ich sicherstellen, dass Sie zulässig sind und in template_params OHNE nur tun .Genehmigung! (dh. Ich will nicht zulassen, alles blind)?

Den controller update-Methode:

def update
    Rails.logger.info "*******HERE*******"
    Rails.logger.info template_params
    @template.template_items = template_params[:template_items_attributes]

    if @template.update(template_params)
      render json: @template
    else
      render json: ErrorSerializer.serialize(@template.errors), status: :unprocessable_entity
    end
  end

UDPATE

Wenn ich vom client "template_items_attributes" statt "template_items" in den Parametern auf Schienen, und führen Sie dann die empfohlene template_params wie diese:

    def template_params
      params.require(:template).permit(:id, :account_id, :name, :title, :info, template_items_attributes: [:id, :is_completed, :content, :item_type])
    end

es immer noch nicht schaffen, neue Kinder für die Vorlage!

In diesem Ort, habe ich die Ausgabe der Parameter vor und danach, wie diese:

def update
    Rails.logger.info params
    Rails.logger.info "*******HERE*******"    
    Rails.logger.info template_params

    if @template.update(template_params)
      render json: @template
    else
      render json: ErrorSerializer.serialize(@template.errors), status: :unprocessable_entity
    end
  end

Und hier ist der log von diesem Szenario - Schienen ist NOCH völlig ignoriert die embedded-array. Beachten Sie, dass params, kurz bevor HIER, zeigt zulässig: false und danach template_params enthält nicht mehr die Kinder "template_items_attributes" und ist die Bezeichnung zulässig:true.

I, [2017-10-20T21:52:39.886104 #28142]  INFO -- : Processing by Api::TemplatesController#update as JSON
I, [2017-10-20T21:52:39.886254 #28142]  INFO -- :   Parameters: {"id"=>"55e27eb7-1151-439d-87b7-2eba07f3e1f7", "account_id"=>"a61151b8-deed-4efa-8cad-da1b143196c9", "name"=>"Test", "info"=>"INFO12345", "title"=>"TITLE1", "created_at"=>"2017-10-14T19:30:41.450Z", "updated_at"=>"2017-10-20T17:48:24.909Z", "template_items_attributes"=>[{"is_completed"=>false, "item_type"=>"item"}], "template"=>{"id"=>"55e27eb7-1151-439d-87b7-2eba07f3e1f7", "account_id"=>"a61151b8-deed-4efa-8cad-da1b143196c9", "name"=>"Test", "info"=>"INFO12345", "title"=>"TITLE1", "created_at"=>"2017-10-14T19:30:41.450Z", "updated_at"=>"2017-10-20T17:48:24.909Z"}}
D, [2017-10-20T21:52:39.903011 #28142] DEBUG -- :   User Load (7.7ms)  SELECT  "users".* FROM "users" WHERE "users"."uid" = $1 LIMIT $2  [["uid", "[email protected]"], ["LIMIT", 1]]
D, [2017-10-20T21:52:40.072148 #28142] DEBUG -- :   Template Load (1.4ms)  SELECT  "templates".* FROM "templates" WHERE "templates"."id" = $1 ORDER BY name ASC LIMIT $2  [["id", "55e27eb7-1151-439d-87b7-2eba07f3e1f7"], ["LIMIT", 1]]
I, [2017-10-20T21:52:40.083727 #28142]  INFO -- : <ActionController::Parameters {"id"=>"55e27eb7-1151-439d-87b7-2eba07f3e1f7", "account_id"=>"a61151b8-deed-4efa-8cad-da1b143196c9", "name"=>"Test", "info"=>"INFO12345", "title"=>"TITLE1", "created_at"=>"2017-10-14T19:30:41.450Z", "updated_at"=>"2017-10-20T17:48:24.909Z", "template_items_attributes"=>[{"is_completed"=>false, "item_type"=>"item"}], "controller"=>"api/templates", "action"=>"update", "template"=>{"id"=>"55e27eb7-1151-439d-87b7-2eba07f3e1f7", "account_id"=>"a61151b8-deed-4efa-8cad-da1b143196c9", "name"=>"Test", "info"=>"INFO12345", "title"=>"TITLE1", "created_at"=>"2017-10-14T19:30:41.450Z", "updated_at"=>"2017-10-20T17:48:24.909Z"}} permitted: false>
I, [2017-10-20T21:52:40.083870 #28142]  INFO -- : *******HERE*******
D, [2017-10-20T21:52:40.084550 #28142] DEBUG -- : Unpermitted parameters: :created_at, :updated_at
I, [2017-10-20T21:52:40.084607 #28142]  INFO -- : <ActionController::Parameters {"id"=>"55e27eb7-1151-439d-87b7-2eba07f3e1f7", "account_id"=>"a61151b8-deed-4efa-8cad-da1b143196c9", "name"=>"Test", "title"=>"TITLE1", "info"=>"INFO12345"} permitted: true>
D, [2017-10-20T21:52:40.084923 #28142] DEBUG -- : Unpermitted parameters: :created_at, :updated_at
D, [2017-10-20T21:52:40.085375 #28142] DEBUG -- :    (0.2ms)  BEGIN
D, [2017-10-20T21:52:40.114015 #28142] DEBUG -- :   Account Load (1.2ms)  SELECT  "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT $2  [["id", "a61151b8-deed-4efa-8cad-da1b143196c9"], ["LIMIT", 1]]
D, [2017-10-20T21:52:40.131895 #28142] DEBUG -- :   Template Exists (0.8ms)  SELECT  1 AS one FROM "templates" WHERE "templates"."name" = $1 AND ("templates"."id" != $2) AND "templates"."account_id" = 'a61151b8-deed-4efa-8cad-da1b143196c9' LIMIT $3  [["name", "Test"], ["id", "55e27eb7-1151-439d-87b7-2eba07f3e1f7"], ["LIMIT", 1]]
D, [2017-10-20T21:52:40.133754 #28142] DEBUG -- :    (0.3ms)  COMMIT
D, [2017-10-20T21:52:40.137763 #28142] DEBUG -- :   CACHE Account Load (0.0ms)  SELECT  "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT $2  [["id", "a61151b8-deed-4efa-8cad-da1b143196c9"], ["LIMIT", 1]]
D, [2017-10-20T21:52:40.138714 #28142] DEBUG -- :    (0.2ms)  BEGIN
D, [2017-10-20T21:52:40.141293 #28142] DEBUG -- :   User Load (1.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 FOR UPDATE  [["id", "88de3be9-6d18-4687-ab80-d50f78638ca9"], ["LIMIT", 1]]
D, [2017-10-20T21:52:40.235163 #28142] DEBUG -- :   Account Load (0.7ms)  SELECT  "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT $2  [["id", "a61151b8-deed-4efa-8cad-da1b143196c9"], ["LIMIT", 1]]
D, [2017-10-20T21:52:40.240997 #28142] DEBUG -- :   SQL (1.4ms)  UPDATE "users" SET "tokens" = $1, "updated_at" = $2 WHERE "users"."id" = $3  [["tokens", "{\"ryyymFZ7fpH50rMKArjZ2Q\":{\"token\":\"$2a$10$4jkgRe4LBPxJ8fQUOKCSausUi7DbIUD0bE.7ZRoOuTHrRuX6CaWOe\",\"expiry\":1509293414,\"last_token\":\"$2a$10$cpI.mz81JFjQT0J9acCCl.NdrEatI5l17GtrwrAfwyhyN3xRExcaC\",\"updated_at\":\"2017-10-15T17:10:16.996+02:00\"},\"Y2y0maUT5WYSfH6VZeORag\":{\"token\":\"$2a$10$8KERiIwlc3rX.Mdu.CW6wOMLDbVyB2PFCaBIlw7/LUxC3ITpYTISW\",\"expiry\":1509293475,\"last_token\":\"$2a$10$r6Xw6798T1P7UZlTbEaXoeBCl9oK2fMs72ppAtars8Ai/kaE6nE66\",\"updated_at\":\"2017-10-15T17:11:18.066+02:00\"},\"9Cy48CPVj3WhFkEBPUZQ1Q\":{\"token\":\"$2a$10$Qy4JOD8.jIcPhf93MqFCIelnVaA/ssE31w5DlL8MShDuMROsLSNuS\",\"expiry\":1509293942,\"last_token\":\"$2a$10$e6sxklrHRRD1C15Ix/MqQOfACuCMznmzUjF296cpO1ypWVvJ.JFJK\",\"updated_at\":\"2017-10-15T17:19:05.200+02:00\"},\"O5iufW0Gacqs9sIfJ9705w\":{\"token\":\"$2a$10$EkDf7.y3lY9D36lAwNHBGuct97M6/HGDvnrUsD72c8zCsfVd8y9c2\",\"expiry\":1509482450,\"last_token\":\"$2a$10$S0kHEvKxom2Qgdy0r.q0aeTSlSBFkqU4XZeY91n3RkkYkQykmmGVi\",\"updated_at\":\"2017-10-17T21:40:50.300+02:00\"},\"ETOadoEtoxcz6rR6Ced_dA\":{\"token\":\"$2a$10$8t01bWv/PsVojs3cazuSg..FWa9SZwq1/PUDfuN1S4yBxnMFv2zre\",\"expiry\":1509742360,\"last_token\":\"$2a$10$hveuajISXDOjHLm9EkVzvOd3pwKkqE1rQnIFBoojf0vgMLXV2EvVe\",\"updated_at\":\"2017-10-20T21:52:40.233+02:00\"}}"], ["updated_at", "2017-10-20 19:52:40.236607"], ["id", "88de3be9-6d18-4687-ab80-d50f78638ca9"]]
D, [2017-10-20T21:52:40.243960 #28142] DEBUG -- :    (1.3ms)  COMMIT
I, [2017-10-20T21:52:40.244504 #28142]  INFO -- : Completed 200 OK in 358ms (Views: 1.0ms | ActiveRecord: 37.7ms)
  • Können Sie auch die controller-Aktion, die Sie haben?
  • Vielen Dank für das hinzufügen der controller. Ihr scheint das problem könnte die Tatsache sein, dass Sie nicht haben optional:true. Schienen 5 Kräfte der Eltern erforderlich zu sein. belongs_to : template, optional: true . Wenn Sie dies versuchen, würde ich empfehlen, auch die-snippet, das Sie haben unter Wenn dies war eine Rails-form dann, dass die Zeile bei der Definition Stark Params. Wenn diese änderungen lassen Sie das Modell speichern richtig.
  • Den Eltern ist immer vorhanden - das ist nicht die create-Aktion. In der create-Aktion können Sie nur erstellen einer übergeordneten Vorlage, keine Kinder posten. Aber in der update-Aktion, die Sie aktualisieren können, sowohl die Eltern und Ihre Kinder. Ich werde es versuchen, aber ich bin immer ziemlich verrückt, habe versucht, eine million Dinge in den letzten 4 Stunden.
  • Auch, Sie "sollte nicht", müssen Sie die Zeile @template.template_items = template_params[:template_items_attributes] in Ihren Aktionen. Teil von dem, was Schienen hat, wenn Sie definieren, akzeptiert verschachtelten Attribute. @template.update(template_params) sollte auch Lesen Sie die verschachtelten Attribute und entsprechend aktualisieren. Werfen Sie einen Blick auf diesen blog: devopsdiarist.uk/rails-5-verschachtelte Attribute zeigt ein sehr einfaches Beispiel, aber mit Ihrer exakten Szenario.
  • Guter Punkt, ich fügte hinzu, dass, bevor ich Hinzugefügt accepts_nested_attributes, um zu versuchen und sehen, wenn ich könnte erzwingen, erstellen Sie die Elemente manuell.
  • Ok, durch hinzufügen optional: true und mit der forms-code, bekomme ich jetzt diesen Fehler: ArgumentError (Wenn die Zuordnung von Attributen, müssen Sie passieren einen hash als argument.). Auch wenn ich das log der params die gesamte hash ist nun markiert zulässig: false - das erklärt den Fehler!
  • Ok, die update-Aktion jetzt feuert, log sagt Vorlage Vorhanden ist und die verschachtelten params völlig ignoriert. Nur die Eltern ist aktualisiert, keine Kinder erzeugt werden.
  • okay, jetzt sind Sie auf dem richtigen Weg. Dies nun geschieht, weil in Ihnen nie das erstellen von Zuordnungen. Es gibt also nichts zu aktualisieren. update funktioniert nur, wenn es eine ID ist, kommen für den Verein. wenn Sie gehen, um erstellen Sie eine Zuordnung, die aus zu aktualisieren, müssen Sie zunächst erstellen Sie im edit-action. Oder beurteilen Sie Ihre neue Assoziationen in update und bevor Sie das update-Vorlage , in einer each-Schleife verwenden @template.build_template_item(Item)
  • Ich denke, dass ich eine Antwort jetzt. Geben Sie mir ein paar. Ich habe nicht aktiv dev env jetzt, so musste Sie get info aus den Kommentaren 😀
  • Danke, so habe ich eine catch-22, da es keine edit-action. Es ist ein api. Die Vorlage ist bereits vorhanden und in diesem update, die ich brauche, um neue Kinder zu. Also warum gibt es keine ids in der json. Hmmm...also ich denke ich werde bauen müssen die Kinder in die template-update-Aktion (vielleicht durch den Aufruf einer build_children Methode auf dem Vorlage-Modell).
  • Yep, die Sie brauchen, um zu bauen Verbände in update Schleife auf Sie, schauen Sie meine aktuelle Kommentar. Ich bin Entsendung eine Antwort in Kürze.
  • haben Sie versucht, das einwickeln der nested association Attribute im controller?
  • Dup stackoverflow.com/questions/19574595/...?
  • In der Tat, das scheint ein Duplikat zu sein und ich umgesetzt haben, die monkey_patch zur Verfügung gestellt von lakesare in seiner Antwort auf diese Frage.
  • Mögliche Duplikate von Rails 4 Nicht Aktualisiert Verschachtelte Attribute Über JSON
  • Es stellt sich heraus, die Schienen verschachtelte Attribute ist nur die eine Hälfte des Problems.

InformationsquelleAutor rmcsharry | 2017-10-20
Schreibe einen Kommentar