Reputation: 1696
I m building my first REST API using Rails and have a simple question which I am unable to solve.
Basically i am not able to write a params hash into the database from a http PUSH
request.
I have the following user controller under the Api namespace with the create action.
class Api::UserController < ApplicationController
http_basic_authenticate_with :name => "test", :password => "test"
skip_before_action :verify_authenticity_token
def create
@user = User.create(params[:user])
respond_to do |format|
if @user.save
format.json{render json: @user, status: :created, location: @user} #render create full response
else
format.json{render json: @user.errors, status: :unprocessable_entity}
end
end
end
end
The route to this action is
POST /api/user(.:format) api/user#create{:format=>"json"}
The user model has a name and a address string not contained.
To test the REST call i setup the firefox plugins RESTeasy
and RESTclient
with this URL http://localhost:3000/api/user/
and this body { "name": "timoteo", "address": "berlin" }
So far so good. Now after sending this package Webrick gives me this output:
Started POST "/api/user" for ::1 at 2015-08-03 17:06:50 +0200
Processing by Api::UserController#create as JSON
Parameters: {"name"=>"timoteo", "address"=>"berlin"}
(1.2ms) BEGIN
SQL (0.6ms) INSERT INTO "users" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id" [["created_at", "2015-08-03 15:06:50.646169"], ["updated_at", "2015-08-03 15:06:50.646169"]]
(42.8ms) COMMIT
(0.3ms) BEGIN
(0.3ms) COMMIT
Completed 201 Created in 66ms (Views: 1.4ms | ActiveRecord: 48.1ms)
neglecting the two parameter and an empty empty record like this one gets stored in the database(also the REST clients show me the same)
{"id":19,"name":null,"address":null,"created_at":"2015-08-03T15:06:50.646Z","updated_at":"2015-08-03T15:06:50.646Z"}
Can someone give me a hint what might have gone wrong during the way. I assume it is something with the params hash but i could not figure it out yet.
Upvotes: 3
Views: 695
Reputation: 6545
Add validation to your model:
class User < ActiveRecord::Base
validates_presence_of :name
validates_presence_of :address
end
That will disallow saving record with blank attributes.
Then, change your #save
call to #persisted?
in your controller (because record is created immediately after #create
is called, it is already saved or failed)
if @user.persisted?
format.json{render json: @user, status: :created, location: @user} #render create full response
else
format.json{render json: @user.errors, status: :unprocessable_entity}
end
UPD. You could also benefit from whitelisting parameters which you accept:
@user = User.create(params.require(:name, :address))
This way Rails will respond with error, saying parameter is missing, and will not assign any other attributes to user (which you don't want to be assigned).
Upvotes: 1
Reputation: 301
Your params of { "name": "timoteo", "address": "berlin" }
are incorrect when your user creation is @user = User.create(params[:user])
You params should look more like:{ "user": { "name": "timoteo", "address": "berlin" } }
because you're accessing params[:user]
so the user attributes need to belong to the user section of your params.
Adding Validations may help if its incorrect to save a User with no name/address too.
class User < ActiveRecord::Base
validates :name, presence: true
validates :address, presence: true
# etc...
end
Upvotes: 1