Reputation: 467
I'm trying to write a simple PATCH endpoint in ROR to update a User. Here's what I have:
def update
@user = User.find(params[:id])
if @user.update_attributes(name: params[:name],
username: params[:username],
email: params[:email],
bio: params[:bio])
render json: {
message: 'User Updated Successfully',
id: @user.id,
name: @user.name,
username: @user.username,
email: @user.email,
bio: @user.bio
}, status: 200
else
render json: {
message: 'Validation Failed',
errors: @user.errors.full_messages
}, status: 422
end
end
def user_params
{
device_token: params[:device_token],
id: params[:id],
name: params[:name],
username: params[:username],
email: params[:email],
bio: params[:bio],
password: params[:password],
password_confirmation: params[:password_confirmation]
}
end
The update method fails the 'if' and returns 422 to my client. I'm not quite sure what I'm doing wrong. I'm thinking that since Password/Confirmation are required when creating a user, that it's failing because they aren't provided in the parameters for this method. Am I totally off base? If not, is there any way around this snag? Thanks in advance.
------edit-------
From the rails console
[3] pry(main)> @user.update_attributes({'name' => 'Jason Smith', 'username' => 'smithja', 'email' => '[email protected]', 'bio' => ''})
(0.2ms) BEGIN
User Exists (0.9ms) SELECT 1 AS one FROM "users" WHERE (LOWER("users"."email") = LOWER('[email protected]') AND "users"."id" != 14) LIMIT 1
(0.3ms) ROLLBACK
=> false
[4] pry(main)> @user.update_attributes({'name' => 'Jason Smith', 'username' => 'smithja', 'email' => '[email protected]', 'bio' => '', 'password' => 'foobar', 'password_confirmation' => 'foobar'})
(0.2ms) BEGIN
User Exists (0.5ms) SELECT 1 AS one FROM "users" WHERE (LOWER("users"."email") = LOWER('[email protected]') AND "users"."id" != 14) LIMIT 1
SQL (0.5ms) UPDATE "users" SET "bio" = $1, "email" = $2, "name" = $3, "password_digest" = $4, "updated_at" = $5, "username" = $6 WHERE "users"."id" = 14 [["bio", ""], ["email", "[email protected]"], ["name", "Jason Smith"], ["password_digest", "$2a$10$XvOv1EchEeWAEczbKKTbC.l5svoSTA807Y0dgOMFOh3xUi5uC.vaW"], ["updated_at", "2014-09-08 17:39:50.240324"], ["username", "smithja"]]
(0.5ms) COMMIT
=> true
I don't want to have to enter the password.
Upvotes: 0
Views: 1351
Reputation: 13621
Yeah 422 is when validations fail. Update your validations to only require password & password_confirmation on create. If you're using has_secure_password, it should do this for you.
Also, no need to manually build out your JSON:
render @user.as_json.merge({:message => 'User Updated Successfully'}).to_json
The as_json method converts it to a hash object, which can be used to create a json string. This includes all the database attributes by default. The to_json then takes the modified hash and returns the string value.
Though honestly, i would only pass a message back to JSON that the server needs to determine. So error messages for example for a badly formatted email are great to pass through JSON. A success message can be handled by the client easily enough.
Upvotes: 1