简体   繁体   中英

Devise if user exists then update

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM