Search code examples
ruby-on-railsdeviseember-cli

User attributes edit issue on Ember-cli alongside Rails with Devise


Below is the versions that I am currently using:

  • Ember : 1.13.3
  • Ember Data : 1.13.5
  • jQuery : 1.11.3
  • Ember Simple Auth : 0.8.0
  • Ember Simple Auth Devise : 0.8.0
  • Devise : 3.5.1
  • Ember-cli-rails : 0.3.2

The Ember side acts like the update was successful, but a new API request brings an unaltered user... Below is what Rails output:

22:07:18 web.1  | Processing by Api::V1::UsersController#update as JSON
22:07:18 web.1  |   Parameters: {"user"=>{"full_name"=>"Sample User hghghfg", "display_name"=>"User#1", "password"=>"[FILTERED]", "email"=>"[email protected]", "date_of_birth"=>"2009-09-14T00:00:00.000Z", "gender"=>"male", "facebook_url"=>"", "twitter_url"=>"https://twitter.com/Deovandski", "personal_message"=>"sample personal message", "webpage_url"=>"www.google.com", "is_banned"=>false, "is_banned_date"=>nil, "legal_terms_read"=>true, "privacy_terms_read"=>true, "is_admin"=>true, "is_super_user"=>true, "sign_in_count"=>634, "last_sign_in_at"=>"2015-08-11T02:07:11.600Z", "updated_at"=>"2015-08-11T02:07:11.723Z", "created_at"=>"2015-08-10T03:16:28.314Z", "show_full_name"=>true}, "id"=>"2"}
22:07:18 web.1  |   User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."email" = ? LIMIT 1  [["email", "[email protected]"]]
22:07:18 web.1  |    (0.1ms)  begin transaction
22:07:18 web.1  |   SQL (0.2ms)  UPDATE "users" SET "last_sign_in_at" = ?, "current_sign_in_at" = ?, "sign_in_count" = ?, "updated_at" = ? WHERE "users"."id" = ?  [["last_sign_in_at", "2015-08-11 02:07:11.875566"], ["current_sign_in_at", "2015-08-11 02:07:18.560464"], ["sign_in_count", 636], ["updated_at", "2015-08-11 02:07:18.563145"], ["id", 2]]
22:07:18 web.1  |    (22.1ms)  commit transaction
22:07:18 web.1  |   User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 2]]
22:07:18 web.1  |   CACHE (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", "2"]]
22:07:18 web.1  |    (0.1ms)  begin transaction
22:07:18 web.1  |   User Exists (0.4ms)  SELECT  1 AS one FROM "users" WHERE ("users"."email" = '[email protected]' AND "users"."id" != 2) LIMIT 1
22:07:18 web.1  |   User Exists (0.2ms)  SELECT  1 AS one FROM "users" WHERE ("users"."display_name" = 'User#1' AND "users"."id" != 2) LIMIT 1
22:07:18 web.1  |    (0.1ms)  rollback transaction
22:07:18 web.1  |   CACHE (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", "2"]]
22:07:18 web.1  | Completed 204 No Content in 60ms (ActiveRecord: 23.5ms)

As you can see, there is a rollback transaction in which I could not find why it happens (Check the answer below) or how to get more details out of it (The only information that I was able to get out of it was with Rails Logger, but the information was only the model with errors{} appended at the end). However, creating users is working fine and I do have a similar implementation for another model (posts) which is also working, so by natural deduction, I am leaning towards saying that Devise is the culprit. I did try to implement the non password user update from this blog post, but I still have the same issue.

The project is open source and it is available under Deovandski/Fakktion on github, but here are what I think the most important code snippets:

Rails Router

...
    devise_for :users, controllers: {sessions: 'sessions'}
    namespace :api do
        namespace :v1 do
...
            resources :users
...

Rails User_controller

      ...
      def show
        respond_with user
      end

      def create
        respond_with :api, :v1, User.create(user_params)
      end

      def update
        if user_params[:password].blank?
            user_params.delete(:password)
            user_params.delete(:password_confirmation)
        end
        successfully_updated =  if needs_password?(user, user_params)
                                    user.update(user_params)
                                else
                                    user.update_without_password(user_params)
                                end
        if successfully_updated
            respond_with user, status: :ok
        else
            respond_with user.errors, status: :unprocessable_entity
        end
      end
...

  private
    def user
      User.find(params[:id])
    end
   def needs_password?(user, params)
    params[:password].present?
   end
    def user_params
      params.require(:user).permit(:id, :show_full_name, :full_name, :display_name, :email, :date_of_birth, :gender, :facebook_url, :twitter_url, :personal_message, :webpage_url, :is_banned, :is_banned_date, :legal_terms_read, :privacy_terms_read, :is_admin, :is_super_user, :sign_in_count, :password, :number_of_comments, :number_of_posts, :last_sign_in_at, :reset_password_sent_at, :reset_password_token, :updated_at, :created_at)
    end

Solution

  • Due to the lack of errors or any useful information, this bug hunt took a while and it turned out to end at the user model on the rails end. More specifically, the lack of these exactly two lines:

    validates :password, length: {minimum: 8}, presence: true, on: :create
    validates :password, length: {minimum: 8}, on: :update, allow_blank: true
    

    On a sidenote, now the client can update their information with or without setting a new password (as long as they are authenticated.) My objective is to require the current password when the user tried to make changes, so let me know if you would like to see such implementation.