My forms are object-driven and work with form_for. I'm looking to achieve an /edit page for 1 object with 2 forms. More specifically, I'm looking to enable the user to change his password as well as to change his email on the same page. Depending which form has been submitted, the validations etc. should take the correct measures. So far I'm unable to do this.
I'm using Rails 4.
Problems: My validation Procs seem to be unable to detect mail-change / password-change (see hidden field in views) because I cannot use the hidden field in the Proc. So I have no way of detecting what type of form I'm submitting.
Please tell me if there's a more Rails like way of doing this cleanly and neatly or if the way is right and I'm just completely missing something.
Here are the files:
controllers/accounts_controller.rb
def edit
set_pagedata('Account Informationen bearbeiten')
@account = @current_user
end
def update
@account = User.find(@current_user.id)
if @account.update(account_params)
redirect_to account_path
else
render 'edit'
end
end
private
def account_params
params.require(:user).permit(:email, :email_confirmation, :password, :password_confirmation)
end
models/user.rb
class User < ActiveRecord::Base
has_one :admin
has_many :customerships
has_many :customers, :through => :customerships
validates :salutation, presence: { message: 'Die Anrede wird benötigt!', if: :new_record? }
validates :prename, presence: { message: 'Der Vorname wird benötigt!', if: :new_record? }
validates :surname, presence: { message: 'Der Nachname wird benötigt!', if: :new_record? }
validates :email,
presence: { message: 'Die E-Mail Adresse wird benötigt!', if: Proc.new { | c | c.new_record? || c.email.present? } },
uniqueness: { message: 'Diese E-Mail existiert bereits in unserem System!', if: Proc.new { | c | c.new_record? || c.email.present? } }
validates :password,
confirmation: { message: 'Das Passwort wiederholen Feld muss dem Passwort Feld entsprechen!', if: [:new_record?, :password_change?, '!password.nil?'] },
length: { minimum: 5, maximum: 16, message: 'Das Passwort muss mindestens 5 und darf höchstens 16 Zeichen lang sein!', if: [:new_record?, :password_change?, '!password.nil?'] },
presence: { message: 'Das Passwort wird benötigt!', if: [:new_record?, :password_change?, '!password.nil?'] }
has_secure_password :validations => false
def admin?
Admin.find_by_user_id(self.id) != nil
end
def password_change?
:edit_type == 'password-change'
end
def mail_change?
:edit_type == 'mail-change'
end
end
views/accounts/edit.html.erb
<div class="flash-stack">
<%= "<p class='text-danger'>#{@account.errors.full_messages.first}</p>".html_safe if @account.errors.any? %>
</div>
<div class="mysd-panel">
<div class="panel-heading">
<h3 class="panel-title">E-Mail Adresse ändern</h3>
</div>
<div class="panel-body">
<%= form_for @account, url: account_path, html: { :class => 'mysd-form' } do |f| %>
<ul class="form-container">
<li>
<%= f.text_field :email, :value => nil, :class => 'form-control', :placeholder => 'Neue E-Mail Adresse' %>
</li>
<li>
<%= f.text_field :password_confirmation, :value => nil, :class => 'form-control', :placeholder => 'Neue E-Mail Adresse wiederholen' %>
</li>
<%= f.hidden_field :edit_type, :value => 'password-change' %>
<%= submit_tag 'Absenden', :class => 'mysd-btn btn-primary' %>
</ul>
<% end %>
</div>
</div>
<div class="mysd-panel">
<div class="panel-heading">
<h3 class="panel-title">Passwort ändern</h3>
</div>
<div class="panel-body">
<%= form_for @account, url: account_path, html: { :class => 'mysd-form' } do |f| %>
<ul class="form-container">
<li>
<%= f.password_field :password, :value => nil, :class => 'form-control', :placeholder => 'Neues Passwort' %>
</li>
<li>
<%= f.password_field :password_confirmation, :value => nil, :class => 'form-control', :placeholder => 'Neues Passwort wiederholen' %>
</li>
<%= f.hidden_field :edit_type, :value => 'mail-change' %>
<%= f.submit 'Absenden', :class => 'mysd-btn btn-primary' %>
</ul>
<% end %>
</div>
</div>