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.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich glaube, Sie vergessen, dass die params.require(:template).Genehmigung( ... ist eine Methode gibt einen Wert zurück, und wenn Sie anrufen, params zu ändern es später, die Sie nur ändern der Parameter nicht zulässig noch. was Sie tun möchten, tauschen Sie die Reihenfolge bei der Ausführung der parameter-manipulation.
UPDATE: wrap_parameters der übeltäter war, denn es war nicht darunter geschachtelten Parameter in den umschlossenen params. dies behebt das Problem
UPDATE: die Antwort implementiert eine andere Lösung
Rails 4 Nicht Aktualisiert Verschachtelte Attribute Via JSON
Dies ist eine lange open request in github!! crazy
https://github.com/rails/rails/pull/19254
Problem
Dein problem ist in deinem
update
Aktion, die Sie zu speichern versuchen die Verbände auf@template
dass nicht noch gebaut werden. Da gibt es keine 'ids' kommen mit dem hash, der update-Funktion einfach ignoriert Sie.Die Lösung
Ist die Iteration über das array der Verein hashes kommen in über der
update
Aktion, und bauen Sie auf die@template
vor dem Aufrufupdate
auf die@template
.Hier ist das sudo-code (habe es nicht ausprobiert, also nicht kopieren und einfügen) :
Modelle
Starke params-definition
Update-Aktion
optional: true
weil Sie immer erstellen Sie die Vorlage zunächst.