Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails create or update Users

I am very very new to Rails and am struggling a little.

I have users that follow a basic sign up, edit process.

I have a situation where a user can be 'part registered', i.e a users email address in the db with a random password as they where put in there via an invite process by an existing user.

When an invited user who already technically exists in the db tries to register I get 'email already exists' since I do have uniqueness checks applied to the user object and a unique index on the table.

I did turn this off and using if statements within the create method to see if the user exists and checked other values did an update or a new and save. All of the if conditions were ignored and a new user was created.

What I want to do is use the same registration form that 'creates' a user to update an existing 'part registered' user with their entered password and name if they exist (email address check) and other db flags are set to true. if the user does exist but the conditions not met load a 'forgot password' page or if user is a new user create and save it.

Any assistance or advice on how to achieve the above would be brill.

Thanks

Vicky


Here is my set up:

User class

class User < ActiveRecord::Base
  attr_accessor :password
  attr_accessible :email, :name, :password, :password_confirmation, :tandc

  email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

  validates :name, :presence => true,
                   :length => { :maximum => 50 }

  validates :email, :presence => true,
                    :format => {:with => email_regex },
                    :uniqueness => { :case_sensitive => false }

  validates :password,  :presence => true,
                        :confirmation => true,
                        :length => { :within => 6..40 }

  validates :tandc, :presence => true

  before_save :encrypt_password
  .
  .
  .
end

I have a UsersController with the following

  def new
    @user = User.new
    @title = "Sign Up"
  end

def create
 if @user.save
    sign_in @user
    redirect_to @user
 else
    @title = "Sign up"
    render 'new'
 end
end

def update
  if @user.update_attributes(params[:user])
    redirect_to @user
  else
   @title = "Edit"
   render 'edit'
  end
end
.
.
.

I have views: user > new.html.erb

<%= form_for(@user, :html => { :class => "validateUser", :name =>"edit_user"}) do |f| %>
  .
  .
  .
  form stuff here
  .
  .
  .
<% end %>

and user > edit.html.erb

  <%= form_for(@user, :html => { :class => "validateUser", :name =>"edit_user"}) do |f| %>
  .
  .
  .
  form stuff here
  .
  .
  .
  <% end %>

my routes for users are as follows

    users GET    /users(.:format)                users#index
          POST   /users(.:format)                users#create
 new_user GET    /users/new(.:format)            users#new
edit_user GET    /users/:id/edit(.:format)       users#edit
     user GET    /users/:id(.:format)            users#show
          PUT    /users/:id(.:format)            users#update
          DELETE /users/:id(.:format)            users#destroy
like image 306
vlwills Avatar asked Nov 22 '25 07:11

vlwills


2 Answers

A quick, but not elegant solution could be:

def create
 if user = User.find_by_email(params[:user][:email])
    if user.part_registered?
       user.update_attributes(params[:user])
       user.save
       sign_in user
       redirect_to user
    else
       @user = User.new(params[:user])
       if @user.save
       # just to trigger the error messages ...
       else
          @title = "Sign up"
          render 'new'
       end
    end
 else
    @user = User.new(params[:user])
    if @user.save
       sign_in @user
       redirect_to @user
    else
       @title = "Sign up"
       render 'new'
    end
 end
end

Sorry, i don't have time right now to optimize these conditions

like image 69
rails_has_elegance Avatar answered Nov 24 '25 21:11

rails_has_elegance


First off, don't remove the unique index on the user's email. You need that to be unique if you are using it as the natural key of the model, aka signing in with it.

Ask yourself, what is the point of an invitation? I have a sneaking suspicion creating a new user is not really what you want the application to do... what if the user never takes up the inviter on the invitation?

Instead you could make an Invitation object with the user's email and the inviter (if that is the point of an invitation.) Then you could give a link that passes in the invitation as a parameter: <%= link_to new_user_url, email: invitation_email_here %> and put that link in, say, an email to the invited user.

In users/new.html.erb you could pass in the value to pre-fill the form with the email:

<%= f.email_field :email, value: params[:email] %>


Also, I would put your form in a partial to not repeat yourself.

The way form_for works, if @user is new, it will issue a POST request with the filled in values to the create action of the UsersController. If @user is an existing model, it will fill the form with the existing values, issue a PUT request to the update action of the UsersController.

Long story short the edit and new views can have the identical form. To simply display the same form, make a partial in the users/ veiws directory.

<!-- app/views/users/_form.html.erb -->
<%= form_for(@user, html: { class: "validateUser" }) do |f| %>
  ...
<% end %>

And then in the views where you would put the form, put <%= render 'users/form' %>

like image 24
AJcodez Avatar answered Nov 24 '25 23:11

AJcodez