2017-11-12 1 views
7

Ich habe Dish und Comment Modelle wie unten in meiner Rails 5.1 API App - Code Repo here. Ich brauche Hilfe beim Hinzufügen eines neuen Comment zu einem Dish.PUT mit verschachtelten Objekt

Beitrag

class Dish < ApplicationRecord 
    has_many :comments 
end 

Kommentar

class Comment < ApplicationRecord 
    belongs_to :dish 
end 

Beitrag Serializer (verwendet ActiveModel Seriazlier)

class DishSerializer < ActiveModel::Serializer 
    attributes :id, :name, :image, :category, :label, :price, :featured, :description, :created_at 

    has_many :comments 
end 

Kommentar Serializer

class CommentSerializer < ActiveModel::Serializer 
    attributes :id, :rating, :comment, :author, :date 

    def date 
    object.created_at 
    end 
end 

Beitrag Controller- - Standardschienen

class DishesController < ApplicationController 
    before_action :set_dish, only: [:show, :update, :destroy] 

    # GET /dishes 
    def index 
    @dishes = Dish.all 

    render json: @dishes 
    end 

    # GET /dishes/1 
    def show 
    render json: @dish 
    end 

    # POST /dishes 
    def create 
    @dish = Dish.new(dish_params) 

    if @dish.save 
     render json: @dish, status: :created, location: @dish 
    else 
     render json: @dish.errors, status: :unprocessable_entity 
    end 
    end 

    # PATCH/PUT /dishes/1 
    def update 
    # byebug 
    if @dish.update(dish_params) 
     render json: @dish 
    else 
     render json: @dish.errors, status: :unprocessable_entity 
    end 
    end 

    # DELETE /dishes/1 
    def destroy 
    @dish.destroy 
    end 

    private 
    # Use callbacks to share common setup or constraints between actions. 
    def set_dish 
     @dish = Dish.find(params[:id]) 
    end 

    # Only allow a trusted parameter "white list" through. 
    def dish_params 
     params.require(:dish).permit(:name, :image, :category, :label, :price, :featured, :description) 
    end 
end 

Kommentar-Controller Gerüst - Standardschienen Gerüst

class CommentsController < ApplicationController 
    before_action :set_comment, only: [:show, :update, :destroy] 

    # GET /comments 
    def index 
    @comments = Comment.all 

    render json: @comments 
    end 

    # GET /comments/1 
    def show 
    render json: @comment 
    end 

    # POST /comments 
    def create 
    @comment = Comment.new(comment_params) 

    if @comment.save 
     render json: @comment, status: :created, location: @comment 
    else 
     render json: @comment.errors, status: :unprocessable_entity 
    end 
    end 

    # PATCH/PUT /comments/1 
    def update 
    if @comment.update(comment_params) 
     render json: @comment 
    else 
     render json: @comment.errors, status: :unprocessable_entity 
    end 
    end 

    # DELETE /comments/1 
    def destroy 
    @comment.destroy 
    end 

    private 
    # Use callbacks to share common setup or constraints between actions. 
    def set_comment 
     @comment = Comment.find(params[:id]) 
    end 

    # Only allow a trusted parameter "white list" through. 
    def comment_params 
     params.require(:comment).permit(:rating, :comment, :author) 
    end 
end 

Ausgabe

Wenn ein Nutzer besucht /dishes/:id und fügt einen Kommentar zu einem Gericht über die Front-End-Anwendung (Angular 2), ist die comment Push-to-Array von aktuellen Kommentaren und ich bin PUT /dishes:id mit dem dish Objekt Aufruf mit dem verschachtelten bestehende comments und der neue Kommentar. Das neue comment wird jedoch nicht von den Schienen gespeichert - es wird kein Fehler zurückgegeben, stattdessen wird das Objekt dish zurückgegeben. Allerdings sehe ich Unpermitted parameters: :id, :created_at in rails s Konsole. Wie bekomme ich Schienen, um den neuen Kommentar zu speichern?

Die Seite (dishes/9) von wo ich den Kommentar zu einem Gericht hinzufügen, sieht wie folgt auf der Angular-Client-Seite aus. enter image description here

Rails Server-Protokolle

Auf der Seitenschienen, unten ist das, was ich in params sehen - sehe ich den neuen Kommentar - {"author"=>"JANE7777", "rating"=>3, "comment"=>"COMMENT7777", "date"=>"2017-11-12T12:58:12.555Z"} drin.

Started PUT "/dishes/9" for 127.0.0.1 at 2017-11-12 18:28:12 +0530 
Processing by DishesController#update as HTML 
    Parameters: {"id"=>"9", "name"=>"Uthappizza", "image"=>"images/uthappizza.png", "category"=>"mains", "label"=>"Hot", "price"=>"4.99", "featured"=>true, "description"=>"A unique combination of Indian Uthappam (pancake) and Italian pizza, topped with Cerignola olives, ripe vine cherry tomatoes, Vidalia onion, Guntur chillies and Buffalo Paneer.", "created_at"=>"2017-11-01T04:30:09.407Z", "comments"=>[{"id"=>46, "rating"=>5, "comment"=>"Imagine all the eatables, living in conFusion!", "author"=>"John Lemon", "date"=>"2012-10-16T17:57:28.556Z"}, {"id"=>47, "rating"=>4, "comment"=>"Sends anyone to heaven, I wish I could get my mother-in-law to eat it!", "author"=>"Paul McVites", "date"=>"2014-09-05T17:57:28.556Z"}, {"id"=>48, "rating"=>3, "comment"=>"Eat it, just eat it!", "author"=>"Michael Jaikishan", "date"=>"2015-02-13T17:57:28.556Z"}, {"id"=>49, "rating"=>4, "comment"=>"Ultimate, Reaching for the stars!", "author"=>"Ringo Starry", "date"=>"2013-12-02T17:57:28.556Z"}, {"id"=>50, "rating"=>2, "comment"=>"It's your birthday, we're gonna party!", "author"=>"25 Cent", "date"=>"2011-12-02T17:57:28.556Z"}, {"id"=>51, "rating"=>4, "comment"=>"great dish", "author"=>"Jogesh", "date"=>"2017-10-30T05:03:39.656Z"}, {"author"=>"JANE7777", "rating"=>3, "comment"=>"COMMENT7777", "date"=>"2017-11-12T12:58:12.555Z"}], "dish"=>{"id"=>"9", "name"=>"Uthappizza", "image"=>"images/uthappizza.png", "category"=>"mains", "label"=>"Hot", "price"=>"4.99", "featured"=>true, "description"=>"A unique combination of Indian Uthappam (pancake) and Italian pizza, topped with Cerignola olives, ripe vine cherry tomatoes, Vidalia onion, Guntur chillies and Buffalo Paneer.", "created_at"=>"2017-11-01T04:30:09.407Z"}} 
    Dish Load (1.0ms) SELECT "dishes".* FROM "dishes" WHERE "dishes"."id" = $1 LIMIT $2 [["id", 9], ["LIMIT", 1]] 

[25, 34] in C:/apps/railsApi/app/controllers/dishes_controller.rb 
    25: end 
    26: 
    27: # PATCH/PUT /dishes/1 
    28: def update 
    29:  byebug 
=> 30:  if @dish.update(dish_params) 
    31:  render json: @dish 
    32:  else 
    33:  render json: @dish.errors, status: :unprocessable_entity 
    34:  end 
(byebug) params 
<ActionController::Parameters {"id"=>"9", "name"=>"Uthappizza", "image"=>"images/uthappizza.png", "category"=>"mains", "label"=>"Hot", "price"=>"4.99", "featured"=>true, "description"=>"A unique combination of Indian Uthappam (pancake) and Italian pizza, topped with Cerignola olives, ripe vine cherry tomatoes, Vidalia onion, Guntur chillies and Buffalo Paneer.", "created_at"=>"2017-11-01T04:30:09.407Z", "comments"=>[{"id"=>46, "rating"=>5, "comment"=>"Imagine all the eatables, living in conFusion!", "author"=>"John Lemon", "date"=>"2012-10-16T17:57:28.556Z"}, {"id"=>47, "rating"=>4, "comment"=>"Sends anyone to heaven, I wish I could get my mother-in-law to eat it!", "author"=>"Paul McVites", "date"=>"2014-09-05T17:57:28.556Z"}, {"id"=>48, "rating"=>3, "comment"=>"Eat it, just eat it!", "author"=>"Michael Jaikishan", "date"=>"2015-02-13T17:57:28.556Z"}, {"id"=>49, "rating"=>4, "comment"=>"Ultimate, Reaching for the stars!", "author"=>"Ringo Starry", "date"=>"2013-12-02T17:57:28.556Z"}, {"id"=>50, "rating"=>2, "comment"=>"It's your birthday, we're gonna party!", "author"=>"25 Cent", "date"=>"2011-12-02T17:57:28.556Z"}, {"id"=>51, "rating"=>4, "comment"=>"great dish", "author"=>"Jogesh", "date"=>"2017-10-30T05:03:39.656Z"}, {"author"=>"JANE7777", "rating"=>3, "comment"=>"COMMENT7777", "date"=>"2017-11-12T12:58:12.555Z"}], "controller"=>"dishes", "action"=>"update", "dish"=>{"id"=>9, "name"=>"Uthappizza", "image"=>"images/uthappizza.png", "category"=>"mains", "label"=>"Hot", "price"=>"4.99", "featured"=>true, "description"=>"A unique combination of Indian Uthappam (pancake) and Italian pizza, topped with Cerignola olives, ripe vine cherry tomatoes, Vidalia onion, Guntur chillies and Buffalo Paneer.", "created_at"=>"2017-11-01T04:30:09.407Z"}} permitted: false> 
(byebug) c 
Unpermitted parameters: :id, :created_at 
    (0.0ms) BEGIN 
    (0.0ms) COMMIT 
[active_model_serializers] Comment Load (0.0ms) SELECT "comments".* FROM "comments" WHERE "comments"."dish_id" = $1 [["dish_id", 9]] 
[active_model_serializers] Rendered DishSerializer with ActiveModelSerializers::Adapter::Attributes (31.29ms) 
Completed 200 OK in 1901725ms (Views: 37.5ms | ActiveRecord: 5.0ms) 

clientseitige Modelle

Die Dish Modell Comment[] als eines der Mitglieder hat. Wenn ein neuer Kommentar über das Formular hinzugefügt wird, wird die comment an das Array dish.comments gesendet, bevor das Objekt Dish an das Rails-API-Back-End gesendet wird.

Comment Modell in Client-Seite

export class Comment { 
    rating: number; 
    comment: string; 
    author: string; 
    date: string; 
} 

Post Modell in Client-Seite

import { Comment } from './comment'; 
export class Dish { 
    id: number; 
    name: string; 
    image: string; 
    category: string; 
    label: string; 
    price: string; 
    featured: boolean; 
    description: string; 
    comments: Comment[]; 
} 
+0

Haben Sie CSRF-Probleme und den angezeigten Fehler im Zusammenhang mit unzulässigen Parametern überprüft? PUT ist zum Aktualisieren, POST ist zum Erstellen. Sie können versuchen, eine verschachtelte Ressource zu verwenden, oder wenn Sie weiter Push verwenden möchten, fügen Sie access_nested_attributes für in disf.rb für comment.rb hinzu. Versuchen Sie, einen kleinen Testfall zu schreiben, anstatt ihn erneut zu versuchen oder zu testen, um den Code in der byebug-Konsole zu verstehen oder auszuführen. – Sairam

+0

Ich benutze 'Rack-Cors' und habe konfiguriert - meine GET-Anfragen funktionieren gut !! – user3206440

+0

Warum machst du nicht eine separate Aktion comments # create? Deine Lösung ist Hacky. Selbst wenn es funktionieren sollte, sollte man nicht wirklich danach suchen. – AntonTkachov

Antwort

0

Ich würde empfehlen, die Kommentare Controller verwenden und eine verschachtelte Route RESTful bilden.

Zuerst POST die Anfrage, einschließlich der Dish_id zu/Kommentare. Sie versuchen, einen Kommentar zu erstellen, den Dish nicht zu aktualisieren.

Zweitens bilden die verschachtelte Route: /Geschirr /: gericht_id/Kommentare

Hier ist eine Anleitung zur Verschachtelung Ressourcen wie folgt aus: http://guides.rubyonrails.org/routing.html#nested-resources

Der Grund für Fehler ist, dass Sie die erwartete gebrochen haben Parameterstruktur. Für eine PUT sollte Ihr params sein:

{ 
    id: <record to update>, 
    dish: { 
     name: “blah”, 
     comments: [{...},{...}] 
    } 
} 

Auch hier empfehle ich Ihnen wirklich PUT nicht Dish, wenn Sie wollen einfach nur einen Kommentar hinzufügen. Zum Beispiel: das obige wäre wünschenswert, alle Kommentare auf dem Teller zu ersetzen! Wenn Sie einen Datensatz erstellen, erstellen Sie diesen Datensatz und aktualisieren Sie ihn nicht.

Wenn Sie den Dish aktualisieren möchten, wenn ein neuer Kommentar hinzugefügt wird, können Sie einen Callback zum Kommentar-Modell beim Erstellen hinzufügen oder in der Aktion "Kommentar erstellen" des Controllers ausführen.

Verwandte Themen