I have working mail_form contact form with google's smtp service.
I satisfied almost with everything, but form not showing errors for invalid email.
There is an error appears if email field is blank, but if something present in the field and you press "Send message" button nothing happens - validation not allowing send message, but user not informed that something wrong.
contact.rb
class Contact < MailForm::Base
attribute :name
attribute :email, validate: URI::MailTo::EMAIL_REGEXP
attribute :message, validate: true
attribute :file, attachment: true
def headers
{
subject: "My Contact Form",
to: 'MYEMAIL#gmail.com',
from: %("#{name}" <#{email}>)
}
end
end
views/contacts/new.html.haml
= form_with model: #contact do |f|
= f.label :name
= f.text_field :name, required: true, class: "text-field"
= f.label :email
= f.text_field :email, required: true, class: "text-field", placeholder: "email#example.com"
= f.label :message
= f.text_area :message, rows: 6, required: true, class: "text-field"
= f.label :files, class: "inline-block p-1 pt-2"
= f.file_field :file, class: "block p-1 font-body text-sm"
= f.submit t('send_message'), class: "submit"
contacts_controller.rb
class ContactsController < ApplicationController
def new
#contact = Contact.new
end
def create
#contact = Contact.new(contact_params)
#contact.request = request
if #contact.deliver
redirect_to contacts_path, notice: 'Message sent!'
else
flash.now[:error] = 'Could not send message'
render :new
end
end
private
def contact_params
params.require(:contact).permit(:name, :email, :message, :file)
end
end
I have tried many things to show error messages, which have worked in my previous projects, but can't make it work with mail_form contact form.
Related
An admin account creates a user account, this automatically generates a username determined by the user's first and surname.
Once the username is created I want the user to be able to update it only once - Note: This can be at any time or after multiple logins, but once the username has been changed once it needs to be set in stone.
Using Rails and simple_form. The edit form is below.
= simple_form_for(current_user) do |f|
= f.error_notification
.form-inputs
= f.input :name, required: true, label: 'Name'
= f.input :username, required: true
= f.input :email, required: true
= f.input :password, required: true, placeholder: ("#{#minimum_password_length} characters minimum" if #minimum_password_length)
= f.input :password_confirmation, required: true
.form-actions
= f.button :submit, "Update Profile", class: 'btn btn-primary btn-block btn-lg'
Admin/Users controller.
def create
#user = User.new(user_params)
#user.password = SecureRandom.base64()
nameArray = #user.name.split(' ')
#user.username = nameArray[0][0].downcase + nameArray[-1][0..6].downcase
respond_to do |format|
if #user.save
#user.send_reset_password_instructions
format.html do
redirect_to [:admin, #user],
notice: "#{#user} was successfully created. A confirmation email was sent to: #{#user.email}"
end
else
format.html do
flash[:alert] = "User #{#user} already exists, or you have not filled in all of the required fields."
render :new
end
end
end
end
Thanks in advance.
Add new column to User like :edited
def change
add_column :users, :eited, :boolean, default: false
end
In your model User add calback after_update
class User < ApplicationRecord
after_update :set_edited!
before_update :check_if_edited!
def is_edited?
edited?
end
private
def check_if_edited!
# there you can set the error message or what you want
errors.add(:base, :invalid, message: "Your message")) if edited?
end
def set_edited!
transaction do
self.edited = true
self.save!
end
end
end
In your user controller add restriction to update user if is_edited?
def update
if current_user.is_edited?
// preform action
end
end
P.S. migrate logic to assign attributes to model User
class User < ApplicationRecord
after_create :assign_attributes
private
def assign_attributes
transaction do
self.password = SecureRandom.base64()
name_array = name.split(' ')
self.username = nameArray[0][0].downcase + nameArray[-1][0..6].downcase
self.save!
end
end
end
According to me the best way would be to use call_back in user model:
before_update{|user|
user.write_user_name_changed unless user.created_at == user.updated_at
}
def write_user_name_changed
self.user_name_changed = params[:username]
true
end
I want to show my validates in "users.rb". Can anyone help?. I've watched some video tutorial then found myself that was not "define new" but I did not know how to resolve this.
user_controller.rb
class UsersController::ApplicationController
def login
if params[:user]
#notice = "LOGIN FAILED"
#email = params[:user][:mailaddress]
#password = params[:user][:password]
#user = User.find_by(mailaddress: #email)
if #user
#member = Member.find_by(user_id: #user.id)
if #member
#hash = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), #member.salt, #password)
if #hash == #member.hashed_password
# SUCCESS
#notice = "LOGIN SUCCESSFULL"
end
end
end
end
end
end
-------
user.rb
class User::ActiveRecord::Base
has_one :member
validates :mailaddress, presence: {message: "Email need inputed"} #want to show this validates in login.html.haml
end
---------------
login.html.haml
= form_for(:user, url:login_path) do |f|
%div.login
= f.label "Email", class:'control-label'
= f.email_field :mailaddress, class: 'form-control'
= f.label "Password", class: 'control-label'
= f.password_field :password, class: 'control-label'
%div.btn-are
= f.submit 'Finish', class: 'btn'
Validations works only on model create/update but not on some actions like login.
Please see the docs for more info.
You can show flash if some params are missing
user_controller.rb
class UsersController::ApplicationController
def login
if params[:user]
unless params[:user][:mailaddress]
flash[:error] = "Email is required"
render :your_login_path
end
#notice = "LOGIN FAILED"
#email = params[:user][:mailaddress]
#password = params[:user][:password]
#user = User.find_by(mailaddress: #email)
if #user
#member = Member.find_by(user_id: #user.id)
if #member
#hash = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), #member.salt, #password)
if #hash == #member.hashed_password
# SUCCESS
#notice = "LOGIN SUCCESSFULL"
end
end
end
end
end
end
- flash.each do |name, msg|
= content_tag :div, msg, class: name
= form_for(:user, url:login_path) do |f|
%div.login
= f.label "Email", class:'control-label'
= f.email_field :mailaddress, class: 'form-control'
= f.label "Password", class: 'control-label'
= f.password_field :password, class: 'control-label'
%div.btn-are
= f.submit 'Finish', class: 'btn'
The code above is untested, but should work.
Here is the flash documentation
But I'm strongly recommend to use devise to perform sign_in/sign_up of users.
I have the following form validations for name and email:
validates :name, presence: true
validates :email, presence: true
In my browser it looks like:
But, when I submit the following form:
= simple_form_for #contact, :url => create_enquiry_path, :method => :post do |form|
= form.input :name
= form.input :email
= form.input :phone
= form.input :website
There are no errors on the page, but I get:
param is missing or the value is empty for: contact
My controller is:
def create
#contact = ContactForm.new(form_params)
if #contact.errors.any?
render :action => :new
flash[:error] = 'Please correct errors.'
else
redirect_to ....
flash[:notice] = 'Thank you for your message. We will contact you soon!'
end
private
def form_params
params.require(:contact).permit(:name, :phone, :email, :website)
end
Could someone please explain what I am doing wrong here?
It appears that your parameters dictionary is structured differently than you're expecting. If your params dictionary is coming to your controller like:
{ :name => 'John', :email => 'john.smith#abc.ca', ...... }
Then change your form_params method to:
def form_params
params.permit(:name, :phone, :email, :website)
end
If your params dictionary is coming to your controller like:
{ :contact_form => { :name => 'John', :email => 'john.smith#abc.ca', ...... } }
Then change your form_params method to (based on #JiříPospíšil's suggestion):
def form_params
params.require(:contact_form).permit(:name, :phone, :email, :website)
end
If the name of the model is ContactForm, then form_params should reference :contact_form, not :contact.
I am new to Rails. Getting the error below. I understand what the issue is, but not sure how to fix it?
Error - param is missing or the value is empty: customer
def customer_params
params.require(:customer).permit(
:first_name,
:last_name,
:email,
:password,
:password_confirmation)
end
end
DetailsController.rb
class My::Account::DetailsController < MyController
def show
#customer = current_user
end
def update
#customer = current_user
#customer.update_attributes(customer_params)
if #customer.errors.any?
render :action => :show
else
redirect_to my_account_details_path, :notice => 'Account details updated'
end
end
private
def customer_params
params.require(:customer).permit(
:first_name,
:last_name,
:email,
:password,
:password_confirmation)
end
end
View
.account.container
.row
= render :partial => '/my/account/sidebar'
.section
%h2 Your account details
= simple_form_for #customer, :url => my_account_details_path, :method => :put, :html => { :class => 'form-horizontal'} do |form|
.field
= form.input :first_name
.field
= form.input :last_name
.field
= form.input :email, :as => :email
%hr
%h4 Leave password fields blank to keep the existing password
%hr
.field
= form.input :password, :input_html => { :value => '' }
.field
= form.input :password_confirmation, :input_html => { :value => '' }
.field-actions
%button.btn.btn-primary{type: "submit"} Save
It is because it is coming through as user and not customer. Which I believe is because you are using current_user which is a User and not a Customer (guessing from the code). Change it to be params.require(:user).permit(blah)
Recently, I decided to split my User Form into an Edit & Account Form.
User Edit Form
-Name
-Username
-AboutMe
User Account Form
-Email
-Password
-Password Confirmation
The routes work fine and everything gets updated accordingly. But for some reason, when my User Model validates the Email Presence & it Fails, it renders the Edit Form with the appropriate Error Messages as oppose to the Account Form.
How can I set up my Update Method in my Controller to know which form to Render with the appropriate error messages?
Model
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation, :username
validates :username, :presence => true,
:length => { :maximum => 15 },
:format => { :with => VALID_UNAME_REGEX },
:uniqueness => { :case_sensitive => false }
validates :email, presence: true,
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates :password, presence: true, length: { minimum: 6 }, :if => :password #only validate if password changed!
validates :password_confirmation, presence: true, :if => :password
end
Views
Edit View
<%= form_for #user, :html => { :multipart => true } do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="statictitle">Your Profile</div>
<%= f.text_field :username, placeholder: "Username..", :class => "form-control" %>
<%= f.text_field :name, placeholder: "Name", :class => "form-control" %>
<%= f.text_area :bio, placeholder: "About yourself in 160 characters or less...", class: "textinput" %>
<%= f.submit "Update Profile", class: "btn btn-primary" %><br>
<% end %>
Account View
<%= form_for #user, :html => { :multipart => true } do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="statictitle">Your Account</div>
<%= f.text_field :email, placeholder: "Email", :class => "form-control" %>
<%= f.password_field :password, placeholder: "Password", :class => "form-control" %>
<%= f.password_field :password_confirmation, placeholder: "Password Confirmation", :class => "form-control" %>
<%= f.submit "Update Account", class: "btn btn-primary" %><br>
<% end %>
Controller
class UsersController < ApplicationController
def edit
#user = User.find_by_username(params[:id])
end
def account
#title = "Account"
#user = User.find_by_username(params[:id])
end
def update
#user = User.find(current_user.id)
if #user.update_attributes(params[:user])
flash[:success] = "Profile updated"
sign_in #user
redirect_to user_url
else
render 'edit' ###I can't seem to figure out how to render the correct form
end
end
end
Routes
resources :users do
member do
get :account
end
end
You can check the HTTP Referer in this case which will tell you where the request came from and accordingly render your view.
for eg:
if URI(request.referer).path == edit_user_path
render :edit
else
render :account
end