2017-11-12 83 views
7

Mam modele Dish i takie jak poniżej w mojej aplikacji Rails 5.1 API - kod repo here. Potrzebuję pomocy w dodaniu nowego Comment do Dish.PUT z obiektem zagnieżdżonym

post

class Dish < ApplicationRecord 
    has_many :comments 
end 

Komentarz

class Comment < ApplicationRecord 
    belongs_to :dish 
end 

post serializer (używa ActiveModel Seriazlier)

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

    has_many :comments 
end 

Komentarz serializer

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

    def date 
    object.created_at 
    end 
end 

post Controller - domyślne szyny rusztowania

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 

komentarz Controller - domyślne szyny rusztowania

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 

Issue

Gdy użytkownik odwiedza /dishes/:id i dodaje komentarz do naczynia za pośrednictwem aplikacji front-end (kątowa 2), przy czym comment jest push tablicy bieżących komentarzy i dzwonię PUT /dishes:id z obiektem dish zagnieżdżony z istniejący comments i nowy komentarz. Jednak nowy comment nie jest zapisywany przez szyny - nie zwracany jest błąd, zwracany jest obiekt dish. Jednak widzę Unpermitted parameters: :id, :created_at w konsoli rails s. Jak uzyskać szyny, aby zapisać nowy komentarz?

Strona (dishes/9) skąd dodam komentarz do anteny wygląda jak poniżej po stronie klienta Angular. enter image description here

Szyny logi serwera

Po stronie szyny, poniżej jest to, co widzę w params - Widzę nowy komentarz - {"author"=>"JANE7777", "rating"=>3, "comment"=>"COMMENT7777", "date"=>"2017-11-12T12:58:12.555Z"} tam.

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) 

modele Client-side

Model Dish ma Comment[] jako jeden z członków. Po dodaniu nowego komentarza za pomocą formularza, comment jest przekazywana do macierzy dish.comments przed wysłaniem obiektu Dish do zaplecza Rails API.

Comment model stronie klienta

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

Post model stronie klienta

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

czy sprawdziłeś problemy z CSRF i wyświetlany błąd związany z niedozwolonymi parametrami? PUT służy do aktualizacji, POST do tworzenia. Możesz spróbować użyć zagnieżdżonego zasobu lub jeśli chcesz nadal używać push add accepts_nested_attributes dla in dish.rb dla comment.rb. Spróbuj napisać mały przypadek testowy zamiast ponawiać próbę lub testować z interfejsu użytkownika, aby pomóc zrozumieć lub uruchomić kod w konsoli byebug. – Sairam

+0

Używam 'rack-cors' i skonfigurowałem - moje żądania GET działają dobrze !! – user3206440

+0

Dlaczego nie tworzysz osobnych komentarzy akcji # utworzyć? Twoje rozwiązanie jest zhakowane. Nawet jeśli to zadziała, nie jest to coś, czego naprawdę powinieneś szukać. – AntonTkachov

Odpowiedz

0

polecam użyć kontrolera komentarze i tworzyć zagnieżdżone trasę być spokojny.

Po pierwsze, POST żądanie, w tym dish_id to/comments. Próbujesz utworzyć komentarz, a nie aktualizować Danie.

drugie, tworząc zagnieżdżone trasę: /zastawa /: dish_id/komentarze

Oto przewodnik do gniazdowania zasobów tak: http://guides.rubyonrails.org/routing.html#nested-resources

Powodem do błędu jest to, że masz złamane oczekiwany struktura parametrów. Dla Połóż params powinno być:

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

Ponownie, naprawdę polecam nie umieścić w Dish jeśli chcesz po prostu dodać komentarz. Na przykład: powyższe byłoby pożądane, aby zastąpić wszystkie komentarze na Dish! Jeśli tworzysz rekord, utwórz ten rekord, nie aktualizuj jego elementu nadrzędnego.

Jeśli chcesz zaktualizować Naczynie po dodaniu nowego komentarza, możesz dodać wywołanie zwrotne do modelu komentarza przy tworzeniu lub zrobić to w akcji tworzenia komentarza Komentarz.