Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How should I format a JSON POST request to my rails app?

My Rails app has a player class that works perfectly. Players can be created, deleted, and updated from my rails control panel without any issues.

I would like a remote counterpart to be able to join in the fun by creating players using a JSON request. Following the advice of the auto generated Rails comments above my create method : # POST /players.json I have started sending requests to localhost:3000/players.json

The 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"     } } 

However, I am running into this error message:

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

So I guess my question is: How should I structure the JSON I am sending?

Additional info:

  • Ruby Version: 2.0
  • Rails Version: 4.0
  • I have tried sending my requests using Postman

Update - Player Params

Here is the player params method from my controller (as requested):

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 

Update 2 - Player controller

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 

Update 3: logs

(     "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)" ){ } 
like image 484
drewwyatt Avatar asked Sep 09 '13 00:09

drewwyatt


People also ask

Can we send JSON object in post request?

To post JSON to a REST API endpoint, you must send an HTTP POST request to the REST API server and provide JSON data in the body of the POST message. You also need to specify the data type in the body of the POST message using the Content-Type: application/json request header.

How do I send a POST request with JSON payload?

To send the JSON with payload to the REST API endpoint, you need to enclose the JSON data in the body of the HTTP request and indicate the data type of the request body with the "Content-Type: application/json" request header.


2 Answers

First of all, I think your data format is ok and is not the problem here. When I ran exactly into the same problem it was because I did not send the Content-Type: application/json header along with my request.

In Postman, you can select the 'raw' data format and then 'JSON (application/json)' to include this header. In my case it looks like this:

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

Alternatively, you can also try it with 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

If you omit the -H "Content-Type: application/json", then you will receive a 400 response with the "param not found" error, if you include it it should work.

like image 61
Michael Osl Avatar answered Oct 17 '22 08:10

Michael Osl


If you are trying this:

via Postman - Under form-data tab, you need to have the vars as :

player[name] player[room_id] . . 

via jQuery:

$.ajax({ url: 'url', type: 'post', data: { player: { name: 'Test', room_id: '0' } } }) 
like image 43
jesal Avatar answered Oct 17 '22 09:10

jesal