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
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
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' %>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With