0

I am using ruby on rails try to update user information, but when I submit, the console will show an error saying the user exists and redirect to the correct page. What's wrong with my code?

The error message:

 Started PATCH "/users/6" for ::1 at 2015-06-08 21:27:00 -0500
  Processing by UsersController#update as HTML
  Parameters:  {"utf8"=>"✓",  "authenticity_token"=>"sJm38g36DAYDo4eXdpcIPRX0e40Jp6cECmMwEvhCAEhTlDwwmmgOfXZqeczglNmJ4K9pQXiyXAsRsgP/C8lScg==", "name"=>"test123", "department"=>"123", "commit"=>"Update User",  "id"=>"6"}

 User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE  "users"."id" = ? LIMIT 1  [["id", 6]]   CACHE (0.0ms)
 SELECT   "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", "6"]]   (0.1ms)  
 begin transaction
 User Exists (0.2ms)
  SELECT  1 AS one  FROM "users" WHERE ("users"."email" = 'test@test.com' AND "users"."id" != 6) LIMIT 1    (0.1ms)
rollback transaction
  Redirected to  http://localhost:3000/users/6
Completed 302 Found in 9ms  (ActiveRecord: 0.5ms)

Started GET "/users/6" for ::1 at 2015-06-08 21:27:00 -0500     
  Processing  by UsersController#show as HTML
  Parameters: {"id"=>"6"}  User Load  (0.1ms)
  SELECT  "users".* FROM "users" WHERE "users"."id"
= ? LIMIT 1  [["id", 6]]
  Rendered users/show.html.erb within layouts/application  (0.1ms)
  User Load (0.2ms)
  SELECT  "users".* FROM "users" WHERE  "users"."id" = ? LIMIT 1  [["id", 6]]   CACHE (0.0ms)
  SELECT   "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 6]]
Completed 200 OK in 66ms (Views: 64.3ms | ActiveRecord: 0.3ms)

The edit page

<h1 class="center">Edit name</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">

    <%= form_tag "/users/#{@user.id}", :method => 'patch' do %>

      <p>
        <%= label_tag :name %>
        <%= text_field_tag :name, @user.name %>
      </p>

      <p>
        <%= label_tag :department %>
        <%= text_field_tag :department, @user.dept %>
      </p>

      <input type="submit" name="commit" value="Update User">
    <% end %>
  </div>

</div>

The controller is like this

class UsersController < ApplicationController
  before_action :authorize, only: [:show, :edit, :update]

  def authorize
    @user = User.find_by(id: params[:id])
    if @user.blank? || session[:user_id] != @user.id
      redirect_to root_url, notice: "Nice try!"
    end
  end

  def new 
    @user = User.new 
  end

  def show
  end

  def edit
  end

  def update
    @user = User.find_by(id: params[:id])
    @user.name = params[:name]
    @user.dept = params[:department]
    @user.save
    redirect_to user_path(@user.id)
  end

  def create
    @user = User.new(email: params[:email], 
                    name: params[:name], 
                    password: params[:password],
                    role: params[:role],
                    dept: params[:dept])
    if @user.save
      redirect_to root_url, notice: "Thanks for signing up."
    else
      render "new"
    end
  end
end

The router concerning this part is like:

  # sign up
  get '/signup'               => 'users#new'
  post '/users'               => 'users#create'
  get '/users/:id'            => 'users#show', as: :user
  get '/users/:id/edit'       => 'users#edit', as: 'edit_user'
  patch '/users/:id'          => 'users#update'
RTarson
  • 351
  • 3
  • 23
Eleanor
  • 306
  • 1
  • 4
  • 14
  • 1
    Similar question: http://stackoverflow.com/questions/19037733/why-does-my-rails-rollback-when-i-try-to-user-save – igor_rb Jun 09 '15 at 02:46
  • It's probably going to be something to do with your validations. In your `update` action, change `@user.save` to `@user.save!` for debugging purposes. Instead of gracefully failing, it will throw an exception. This should help you troubleshoot where your problem is. Update your question with the results of this if you still need help. – kobaltz Jun 09 '15 at 03:34
  • 1
    `form_tag` is used for non-model and `form_for` for specific model [Reference](http://apidock.com/rails/ActionView/Helpers/FormHelper/form_for) – Prashant4224 Jun 09 '15 at 04:34
  • Why you are using save in update action. shouldn't you use `update_attributes` or `update` – Pavan Jun 09 '15 at 06:53

2 Answers2

1

The problem is in the form_tag,it should be like this

<%= form_tag({:action => :update}, {:method => :patch}) do %>

Also your code for form_tag looks vulnerable. Changing it to like this will be better.

<%= form_tag update_user_path(@user) do %> 

               or

<%= form_tag user_path(@user), :method => :patch do %>
Pavan
  • 33,316
  • 7
  • 50
  • 76
0

Are you using rails 4?

You should update your controller to conform to strong_parameters if you are.

def update
  @user = User.find(params[:id)
  if @user.update_attributes(user_params)
    redirect_to user_path(@user.id)
  else
    render :edit
  end
end

private

def user_params
  params.require(:user).permit(:name, :dept)
end

Doing this will mean that you have to wrap your name and dept params inside a user scope, eg.

user: { name: "Howard Moon", dept: "Zookeeper" }

But is the standard way to handle params in the controller.

Hope this helps!

EDIT: Link to Strong Parameters which does a better job at explaining this than I can. Haha

RustComet
  • 567
  • 4
  • 15
  • 1
    I think this is not the case. In another model, I also used a way like the above to update two of parameters in a model and it works. I wonder whether it has something to do with my authenticate method. – Eleanor Jun 09 '15 at 03:18
  • In that case the easiest thing to do might be to change `@user.save` to `@user.save!` with the `!`. This won't fix your problem, but it will throw an error if it is not saving the `@user` object. At least that might give you a better idea of what is going on, – RustComet Jun 09 '15 at 04:34
  • Have you try editing your data in `rails console`, check if its valid by `@user.valid?` if false check for error message by `@user.errors`. – Archie Reyes Jun 09 '15 at 09:14