Search code examples
ruby-on-railsruby

How to get value from form in ruby on rails


I am working on a ruby on rail project recently and I have to customize the devise recoverable controller by myself.

Here is the code in the devise/view

<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %>
  <%= render "devise/shared/error_messages", resource: resource %>

  <div class="field">
    <p><%= f.label :email %></p>
    <p><%= f.email_field :email, autofocus: true, autocomplete: "email" %></p>
  </div>

  <div class="actions">
    <%= f.submit "Send me password reset instructions" %>
  </div>
<% end %>

And this is the controller I am trying to make it work.

  # POST /resource/password
  def create
     @user = User.find_by_email(params[:email])
     if @user.some_condition?
       PasswordMailer.with(user: @user).reset.deliver_now
       redirect_to '/', notice: 'If an account with that email was found, we have sent a link to       reset password'
     else
       super
     end
  end

I am trying to make devise send a different email if user meet some condition but this doesn't work. Could someone help me out.

I am trying to find someone debug my code.


Solution

  • Your error is that you are using params[:email] but it should be resource_params[:email]. That would fix your immediate issue.

    The problem is now you are bypassing bits of devise config and password reset mechanics, including the token creation which will cause the reset to fail.

    Instead of overriding the controller, I would override the method in the User class that the controller is calling to send the email. That will leave the devise config parts in tact.

    For example:

    class User < ApplicationRecord
      def send_reset_password_instructions_notification(token)
        if some_condition?
          PasswordMailer.with(user: @user, token: token).reset.deliver_now
        else
          send_devise_notification(:reset_password_instructions, token, {})
        end
      end
    end
    

    This way you are not overriding more than you need to. Your original example was overriding a lot of Devise mechanics that would have to be accounted for, creating the token being chief among them.


    For a clear view of all that you were overriding, here's the call chain to follow.

    Devise::PasswordsController#create Devise::Models::Recoverable.send_reset_password_instructions Devise::Models::Recoverable#send_reset_password_instructions Devise::Models::Recoverable#send_reset_password_instructions_notification