I have a user form in another view which works great to create a user. I want people to complete this form though even if they are already a user.
If they are already a user I would like the form to update their location if they enter anything and save.
User Form
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="form-group">
<%= f.label :location, "Where are you based?" %><br />
<%= f.text_field :location, placeholder: "E.g. London", class: "full-width form-field" %>
</div>
<div class="form-group">
<%= f.label :email, "What is your email?" %>
<%= f.email_field :email, placeholder: "Enter email", class: "full -width form-field" %>
</div>
<div class="actions">
<%= f.button "GO", class: "btn btn-1R btn-orange full-width", id: "submit_button" %>
</div>
<% end %>
I thought I could do a before_validation
method in the model to check if the user exists and create one if not. Would this be correct?
before_validation :check_user, :on => :create
def check_user
@user = User.where(email: self.email).first
unless @user.blank?
@user.update_attributes(:location => self.location)
@user.save
else
puts 'NEW USER'
end
end
This is still throwing the 'Email has already been taken' error.
How can i kill the 'create' method and just cause an update method here? Or am I doing this completely wrong?
I think you want to avoid creating records in your model. It seems like what you are trying to do is combine registrations#create with registrations#update. You could do this by overriding devise's registrations#create method in your registrations controller. So what you can do is check whether your user exists already before building a new resource. Something like this...:
def create
if user = User.where(email: sign_up_params[:email]).first
user.update_attributes(location: sign_up_params[:location])
self.resource = user
else
self.resource = resource_class.new_with_session(sign_up_params || {}, session)
end
resource.save
yield resource if block_given?
if resource.persisted?
if resource.active_for_authentication?
set_flash_message :notice, :signed_up if is_flashing_format?
sign_up(resource_name, resource)
respond_with resource, location: after_sign_up_path_for(resource)
else
set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_flashing_format?
expire_data_after_sign_in!
respond_with resource, location: after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords resource
set_minimum_password_length
respond_with resource
end
end
I managed to fix this by moving the method to the controller and calling
before_action :check_user, only: [:create]
def check_user
@user = User.where(email: sign_up_params[:email]).first
unless @user.blank?
@user.update_attributes(:location => sign_up_params[:location])
@user.save
redirect_to(:back) and return
else
puts 'NEW USER'
end
end
The redirect_to(:back) and return
is what nailed it. :)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.