I am trying to create a sign up flow with Angular client sending user inputs to the server via the $resource service. The User model on the Rails side has a has_secure_password, password_digest field on the model.
Problem is: (1) Rails sends error to Angular client that "password is missing" even though it is not. (2) Password and confirmation seem to not be getting sent by Angular? (3) Password digest is not getting set, remains "nil".
(1) Rails sends error to Angular client that "password is missing" even though it is not.
Object { username: "testuser", first_name: "Test", last_name: "User", email: "[email protected]", password: "password5375", password_confirmation: "password5375" } main.js:157
Object { data: Object, status: 422, headers: headersGetter/<(), config: Object, statusText: " " } main.js:163
"password:can't be blank"
(2) Note that the password & confirmation aren't included in the wrapped "user" hash
Started POST "/api/users.json" for 127.0.0.1 at 2014-10-04 19:04:46 -0400
Processing by UsersController#create as JSON
Parameters: {"username"=>"user3", "first_name"=>"Uss", "last_name"=>"ErThree", "email"=>"[email protected]", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "user"=>{"username"=>"user3", "first_name"=>"Uss", "last_name"=>"ErThree", "email"=>"[email protected]"}}
Can't verify CSRF token authenticity
(0.1ms) begin transaction
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = '[email protected]' LIMIT 1
User Exists (0.1ms) SELECT 1 AS one FROM "users" WHERE "users"."username" = 'user3' LIMIT 1
SQL (164.1ms) INSERT INTO "users" ("created_at", "email", "first_name", "last_name", "updated_at", "username") VALUES (?, ?, ?, ?, ?, ?) [["created_at", Sat, 04 Oct 2014 23:04:46 UTC +00:00], ["email", "[email protected]"], ["first_name", "Uss"], ["last_name", "ErThree"], ["updated_at", Sat, 04 Oct 2014 23:04:46 UTC +00:00], ["username", "user3"]]
(0.8ms) commit transaction
(3) From the console, note that the password digest is not getting set.
User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT 1
=> #<User id: 3, created_at: "2014-10-04 23:04:46", updated_at: "2014-10-04 23:04:46", username: "user3", first_name: "Uss", last_name: "ErThree", email: "[email protected]", password_digest: nil>
1.9.3-p362 :010 > User.last.password_digest
User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT 1
=> nil
app.factory('User', function($resource){
function User() {
this.service = $resource('/api/users/:id.json', {id: '@id'},
{
'update': {method: 'PUT'},
'show': {method: 'GET', isArray: false}
}
);
}
User.prototype.all = function() {
return this.service.query();
};
User.prototype.destroy = function(uid) {
return this.service.remove({id: uid});
};
User.prototype.create = function(attributes) {
return this.service.save(attributes);
};
User.prototype.update = function(attributes) {
return this.service.update(attributes);
};
User.prototype.show = function(uid) {
return this.service.show({id: uid});
}
return new User;
});
app.controller('UsersCreateCtrl', function($scope, User){
$scope.createUser = function(){
$scope.user;
console.log($scope.user);
var newUser = User.create($scope.user).$promise.then(function(data){
console.log(data);
$scope.users.push(newUser);
$scope.user = {};
}, function(msg){
console.log(msg);
angular.forEach(msg.data.errors, function(type, error){
console.log(error + ":" + type);
});
});
};
});
<h4>Register</h4>
<div ng-controller="UsersCreateCtrl">
<form name="form" ng-submit="createUser()" novalidate>
Name: <input name="username" type="text" ng-model="user.username" placeholder="username"/>
First Name: <input name="first_name" type="text" ng-model="user.first_name" placeholder="first name" />
Last Name: <input name="last_name" type="text" ng-model="user.last_name" placeholder="last name" />
Email: <input name="email" type="text" ng-model="user.email" placeholder="email" />
Password: <input name="password" type="text" ng-model="user.password" placeholder="password" />
Confirm Password: <input name="password_confirmation" type="text" ng-model="user.password_confirmation" />
<input type="submit" value="Register">
</form>
</div>
EDIT: Rails UsersController Posted
class UsersController < ApplicationController
respond_to :json
protect_from_forgery with: :null_session
def index
respond_with User.all
end
def create
respond_with User.create(user_params)
end
def destroy
respond_with User.destroy(params[:id])
end
def show
respond_with User.find(params[:id])
end
def update
respond_with User.find(params[:id]).update_attributes(source_params)
end
private
def user_params
params.require(:user).permit(:username, :email, :first_name, :last_name, :password, :password_confirmation)
end
end
I would guess that your rails controller is not allowing password & password confirmation to be passed to the model due to not permitting them in the strong parameters. Either that or you are not including them in the json user object being posted. Since you are most likely doing User.create!(params[:user]), you need to make sure that you have permitted all the params you are expecting:
permitted_params = params[:user].permit(:username, :first_name, :last_name, :email, :password, :password_confirmation)
User.create!(permitted_params)