web-dev-qa-db-fra.com

Comment dois-je formater une requête JSON POST à mon application Rails?

Mon Rails a une classe de joueur qui fonctionne parfaitement. Les joueurs peuvent être créés, supprimés et mis à jour depuis mon panneau de contrôle Rails sans aucun problème).

J'aimerais qu'un homologue distant puisse se joindre au plaisir en créant des joueurs à l'aide d'une demande JSON. En suivant les conseils des Rails commentaires générés automatiquement au-dessus de ma méthode de création: # POST /players.json J'ai commencé à envoyer des demandes à localhost:3000/players.json

Le JSON

{
    "player": {
    "name": "test",
    "room_id": 0,
    "skin_id": 1,
    "head_id": 2,
    "torso_id": 3,
    "legs_id": 4,
    "x_position": 5,
    "y_position": 6,
    "direction": 7,
    "action": "",
    "gender": "f"
    }
}

Cependant, je rencontre ce message d'erreur:

ActionController::ParameterMissing in PlayersController#create param not found: player

Donc je suppose que ma question est: Comment dois-je structurer le JSON que j'envoie?

Informations supplémentaires:

  • Version Ruby: 2.0
  • Version des rails: 4.0
  • J'ai essayé d'envoyer mes demandes en utilisant Postman

Mise à jour - Paramètres du joueur

Voici la méthode de paramétrage du lecteur de mon contrôleur (comme demandé):

def player_params
    params.require(:player).permit(:name, :room_id, :skin_id, :head_id, :torso_id, :legs_id, :x_position, :y_position, :direction, :action, :gender)
end

Mise à jour 2 - Contrôleur de joueur

class PlayersController < ApplicationController
  before_action :set_player, only: [:show, :edit, :update, :destroy]
  skip_before_filter :verify_authenticity_token, :if => Proc.new { |c| c.request.format == 'application/json' }

  # GET /players
  # GET /players.json
  def index
    @players = Player.all
  end

  # GET /players/1
  # GET /players/1.json
  def show
  end

  # GET /players/new
  def new
    @player = Player.new
  end

  # GET /players/1/edit
  def edit
    @rooms = Room.all.map { |room| [room.name, room.id] }
  end

  # POST /players
  # POST /players.json
  def create
    @player = Player.new(player_params)

    respond_to do |format|
      if @player.save
        format.html { redirect_to @player, notice: 'Player was successfully created.' }
        format.json { render action: 'show', status: :created, location: @player }
      else
        format.html { render action: 'new' }
        format.json { render json: @player.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /players/1
  # PATCH/PUT /players/1.json
  def update
    respond_to do |format|
      if @player.update(player_params)
        format.html { redirect_to @player, notice: 'Player was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @player.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /players/1
  # DELETE /players/1.json
  def destroy
    @player.destroy
    respond_to do |format|
      format.html { redirect_to players_url }
      format.json { head :no_content }
    end
  end

  def manage_furni
    @player = Player.find(params[:id])
    @furni = Furni.all
  end

  def add_furni
    player = Player.find(params[:id])
    player.furnis << Furni.find(params[:furni])
    redirect_to manage_furni_path(player)
  end

  def remove_furni
    player = Player.find(params[:id])
    item = InventoryItem.find(params[:item])
    player.inventory_items.delete(item)
    redirect_to manage_furni_path(player)
  end

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

    # Never trust parameters from the scary internet, only allow the white list through.
    def player_params
      params.require(:player).permit(:name, :room_id, :skin_id, :head_id, :torso_id, :legs_id, :x_position, :y_position, :direction, :action, :gender)
    end
end

Mise à jour 3: journaux

(
    "Processing by PlayersController#create as JSON",
    "Completed 400 Bad Request in 31ms",
    "ActionController::ParameterMissing (param not found: player):",
    "app/controllers/players_controller.rb:103:in `player_params'",
    "app/controllers/players_controller.rb:40:in `create'",
    "Rendered /Users/drewwyatt/.rvm/gems/Ruby-2.0.0-p247/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/_source.erb (0.5ms)",
    "Rendered /Users/drewwyatt/.rvm/gems/Ruby-2.0.0-p247/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/_trace.erb (0.9ms)",
    "Rendered /Users/drewwyatt/.rvm/gems/Ruby-2.0.0-p247/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (0.8ms)",
    "Rendered /Users/drewwyatt/.rvm/gems/Ruby-2.0.0-p247/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (16.3ms)"
){
}
38
drewwyatt

Tout d'abord, je pense que votre format de données est correct et n'est pas le problème ici. Lorsque j'ai rencontré exactement le même problème, c'est parce que je n'ai pas envoyé le Content-Type: application/json en-tête avec ma demande.

Dans Postman, vous pouvez sélectionner le format de données "brut" puis "JSON (application/json)" pour inclure cet en-tête. Dans mon cas, cela ressemble à ceci:

Screenshot of sending a JSON request to a Rails application in Postman

Alternativement, vous pouvez également l'essayer avec curl ( source ):

curl -X POST -H "Content-Type: application/json" -d '{"player": {"name": "test","room_id": 0,"skin_id": 1,"head_id": 2,"torso_id": 3,"legs_id": 4,"x_position": 5,"y_position": 6,"direction": 7,"action": "","gender": "f"}}' localhost:3000/players.json

Si vous omettez le -H "Content-Type: application/json", vous recevrez une réponse 400 avec l'erreur "param not found", si vous l'incluez, cela devrait fonctionner.

68
Michael Osl

Si vous essayez ceci:

via Postman - Sous l'onglet données du formulaire, vous devez avoir les variables comme:

player[name]
player[room_id]
.
.

via jQuery:

$.ajax({ url: 'url', type: 'post', data: { player: { name: 'Test', room_id: '0' } } })
6
jesal