I am saving an email to the database and then sending it. I am using the email model to validate the inputs, but I'm not sure how to display the error messages. I am getting an undefined method `errors' for nil:NilClass error for the fullmessage.errors.any? line in the index action(highlighted below)
View
<%= form_tag("/thank_you") do %>
<% if #fullmessage.errors.any? %> # <----- This line
<h3>Errors</h3>
<ul>
<% #fullmessage.errors.full_messages.each do |message| %> # Would also cause an error if exemption not already raised
<li><%= message %></li>
<% end %>
</ul>
<% end %>
<div class="row">
<div class="col-md-5">
<div class="form-group">
<%= text_field_tag :first_name, nil, class: 'form-control', placeholder: 'First Name' %>
</div>
</div>
<div class="col-md-7">
<div class="form-group">
<%= text_field_tag :last_name, nil, class: 'form-control', placeholder: 'Last Name' %>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<%= text_field_tag :email, nil, class: 'form-control', placeholder: 'Email Address' %>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group text-area-wide">
<%= text_area_tag :message, nil, class: 'form-control text-area-wide', placeholder: 'When are you available?' %>
</div>
</div>
</div>
<%= submit_tag 'Get Started', class: 'btn btn-success' %>
<p>Skype required</p>
<% end %>
Controller
def thank_you
#first_name = params[:first_name]
#last_name = params[:last_name]
#email = params[:email]
#message = params[:message] || "Hello!"
#fullmessage = Email.create(first_name: #first_name, last_name: #last_name, email: #email, message: #message)
if #fullmessage.valid?
ActionMailer::Base.mail(
:from => #email,
:to => 'erikvdw#comcast.net',
:subject => "A new contact form message from #{#first_name} #{#last_name}",
:body => #message).deliver
else
redirect_to root_path
flash[:alert] = 'There was an issue with your submission'
end
end
Model
class Email < ActiveRecord::Base
validates_length_of :first_name, :maximum => 25, :minimum => 2
validates_length_of :first_name, :maximum => 30, :minimum => 2
validates_format_of :email, :with => /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
validates_length_of :message, :maximum => 500, :minimum => 20
end
You have two options:
Use render instead of redirect to (this way you'll keep your #fullmessage object.
Save error into flash[:alert] and display it in the view
The 2nd option is more universal, you could add the relevant code to the layout and use it across the whole site. E.g.:
<% if !flash.empty? %>
<div id="flash">
<% flash.keys.each do |k| %>
<div class="alert alert-<%= k %>">
<%= flash[k] %>
</div>
<% end %>
</div>
<% end %>
Nil class means that the #fullmessage is nil and hasn't been set, and nil does not have the method errors, hence the error.
When you redirect, the #fullmessage value will have nothing because http is stateless. Absent caching and cookies, every variable is recreated with every request. think what you are trying to do is display the flash messages, if that is the case you can add the #fullmessage.errors to the flash and be able to display that on the redirect.
Related
I need to send the same message to three different e-mails.
How can I do this?
Something like using a for each?
This is working, but if I just add a field in my view, like:
<div class="form-group">
<%= label_tag(:to, "Recipient's email address") %>
<%= email_field_tag :to, "", class: "form-control" %>
</div>
I get the error:
400 bad request
because of the parameters.
My HTML is:
<h1>Send a message with Mailgun</h1>
<% flash.each do |key, value| %>
<div class="alert alert-success"><%= value %></div>
<% end %>
<%= form_tag(:action => 'create')%>
<div class="form-group">
<%= label_tag(:to, "Recipient's email address") %>
<%= email_field_tag :to, "", class: "form-control" %>
</div>
<div class="form-group">
<%= label_tag(:body, "Message") %>
<%= text_area_tag :body, "", class: "form-control" %>
</div>
<%= submit_tag("Send", :class => "btn btn-primary") %>
And my model:
class HomeController < ApplicationController
def index
end
def create
# Get message value from form
#message = params
# First, instantiate the Mailgun Client with your API key
mg_client = Mailgun::Client.new ('7a9c4084f-b0aacd0-a2b65624')
# Define your message parameters
html_output = render_to_string template: "notifier/send_email"
message_params = {:from => 'postmaster#sandbox671e4d0f627c.mailgun.org',
:to => #message[:to],
:subject => 'Mailgun message via API',
:text => #message[:body],
:html => html_output.to_str,
"o:tag" => 'test'}
# Send your message through the client
mg_client.send_message ('sandboxe6fb741ddb25.mailgun.org'), message_params
# Redirect on success
redirect_to root_path, notice: 'Message was sent.'
end
end
been banging my head on the table over this one. I have another nested form but this one is driving me crazy.
The error is:
TypeError in CompaniesController#create
no implicit conversion of Symbol into Integer
#company = Company.new(company_params)
The controller:
class CompaniesController < ApplicationController
layout 'welcome'
def new
#company = Company.new
end
def create
#company = Company.new(company_params)
if #company.save
flash[:notice] = "New company created successful."
redirect_to admin_accounts_path
else
flash.now[:alert] = "Creation failed, please try again"
render :new
end
end
private
def company_params
params.require(:company).permit(:name, :location, :users_attributes => [:email, :password])
end
end
On the new.html.erb:
<%= render partial: 'form', locals: { company: #company, users_attributes: :users_attributes } %>
This code looks exactly like another nested setup I have, but it works :p
I had read that sometimes changing the params from => to just having a semicolon works, but replacing the user_attributes => with a user_attributes: didn't change anything.
EDIT: form.html.erb
<%= form_for company, url: companies_path do |f| %>
<div class="col-12">
<div class="row">
<div class="col p-0 mr-3">
<div class="form-group">
Company <%= f.label :name %>
<%= f.text_field :name, :placeholder => 'Company name', class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :location %>
<%= f.text_field :location, :placeholder => 'Location', class: 'form-control' %>
</div>
</div>
<div class="col p-0">
<%= f.fields_for users_attributes do |user_f| %>
<div class="form-group">
<%= user_f.label :email %>
<%= user_f.text_field :email, :placeholder => 'Your Email Address', class: 'form-control' %>
</div>
<div class="form-group">
<%= user_f.label :password %>
<%= user_f.password_field :password, :placeholder => 'Password', class: 'form-control' %>
</div>
<% end %>
</div>
<div class="col-12 p-0">
<%= f.submit "Sign-Up", :class => 'btn btn-primary btn-block btn-lg' %>
</div>
</div>
</div>
<% end %>
Use users instead of users_attributes on the form.
Don't forget to define accepts_nested_attributes_for :users in model Company
## new.html.erb
<%= render partial: 'form', locals: { company: #company, users_attributes: :users } %>
I wonder why you didn't put :users into the form directly
I'm working on a simple one-page contact form. Contact model have two attributes: phone and email. Email should be validated on backend (i did it in my model). But user can fill either email or phone in the contact form and send it. No Email field in necessary and i don't know how to make it optional.
contact.rb
class Contact < MailForm::Base
attribute :phone
attribute :email, :validate => /\A([\w\.%\+\-]+)#([\w\-]+\.)+([\w]{2,})\z/i,
presence: false
def headers
{
:subject => "My Contact Form",
:to => "email#admin.com",
:from => %("#{phone}" <#{email}>)
}
end
end
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
flash.now[:notice] = 'Ваша заявка принята!'
render :new
else
flash.now[:notice] = 'Введите корректный email.'
render :new
end
end
private
def contact_params
params.require(:contact).permit(:phone, :email)
end
end
new.html.erb
<%= simple_form_for #contact, html: {class: 'form-inline'} do |f| %>
<div class="form-group">
<div class="col-sm-6">
<%= f.input_field :email, class: "form-control", placeholder: "email", required: false %>
</div>
</div>
<div class="form-group">
<div class="col-sm-6">
<%= f.input_field :phone, class: "form-control", placeholder: "+7 (095) 123-45-67" %>
</div>
</div>
<div class="form-group">
<div class="col-sm-6">
<%= f.button :submit, 'Submit', :class=> "btn btn-success" %>
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<% flash.each do |key, value| %>
<div class="alert alert-info" role="alert">
<div class="alert alert-<%= key %>"><%= value %></div>
</div>
<% end %>
</div>
</div>
<% end %>
I'd probably go about it this way:
class Contact < MailForm::Base
attribute :phone
attribute :email, :validate => /\A([\w\.%\+\-]+)#([\w\-]+\.)+([\w]{2,})\z/i,
presence: false, allow_blank: true
validate :at_least_a_contact
def headers
{
:subject => "My Contact Form",
:to => "email#admin.com",
:from => %("#{phone}" <#{email}>)
}
end
private
def at_least_a_contact
unless phone.present? || email.present?
errors.add(:contact, "You need at least a contact method")
end
end
end
Use allow_blank: true in your validation in your model.
http://guides.rubyonrails.org/active_record_validations.html#allow-blank
I am working with the mail_form gem. I have already created an specific controller for the contact form and everythink seems right but when I submit any form the view does´nt change from the create one to the create one but the url does. It shows the localhost3000/gmm/contacts(which has changed from localhost3000/gmm/contacts/new). I am worried about this issue; Moreover, the new view shows the e-mail in the name´s field as showed in the image:
"http://2.bp.blogspot.com/-Q4qUs1CHm-M/Voqc-VYiXII/AAAAAAAAAdE/nJMxgpTEu5s/s320/problem1.jpg"
Controller file:
class ContactsController < ApplicationController
def new
#contact = Contact.new
end
def create
#contact=Contact.new(params[:contact])
#contact.request=request
if #contact.deliver
flash.now[:error]=nil
else
flash.now[:error]='Cannot send message.'
render :new
end
end
end
New view:
<body>
<section>
<div class="container">
<div class="row">
<div class="col-lg-8 col-lg-offset-2 text-center">
<h2 class="margin-top-0 wow fadeIn">Get in Touch</h2>
<hr class="primary">
<p>We love feedback. Fill out the form below and we'll get back to you as soon as possible.</p>
</div>
<div class="col-lg-10 col-lg-offset-1 text-center">
<%= form_for #contact do |f| %>
<div class="col-md-6 text-faded">
<%= f.label :name %>
<%= f.text_field :name, required: true, :class => "form-control", :placeholder => "Name"%>
</div>
<div class="col-md-6 text-faded">
<%= f.label :email %>
<%= f.email_field :name, required: true, :class => "form-control", :placeholder => "Email" %>
</div>
<div class="col-md-12 text-faded">
<%= f.label :message %>
<%= f.text_area :message, as: :text, :class => "form-control", :rows=>"9", :placeholder => "Your message here.."%>
</div>
<div class="hidden">
<%= f.label :nickname %><br>
<%= f.text_field :nickname, hint:"leave this field blank"%>
</div>
<div class="col-md-4 col-md-offset-4">
<%= f.submit "Send Message", :class=> "btn btn-primary btn-block btn-lg" %>
</div>
<%end%>
</div>
</div>
</div>
</section>
Model:
class Contact<MailForm::Base
attribute :name, :validate => true
attribute :email, :validate => /\A([\w\.%\+\-]+)#([\w\-]+\.)+([\w]{2,})\z/i
attribute :message, :validate => true
attribute :nickname,:captcha => true
def headers
{
:subject => "Contact Form",
:to => "kurtco_91#hotmail.com",
:to => "yomi.89gm#gmail.com",
:from => %("#{name}" <#email>)
}
end
end
Routes:
Rails.application.routes.draw do
resources :contacts, only: [:new,:create]
get 'gmm/home'
get 'gmm/about'
get 'gmm/services'
get 'gmm/contact'
get '/change_locale/:locale', to: 'settings#change_locale', as: :change_locale
I think it must be a problem with the post verb or my routing but I did rake: routes several times and no progress. Thanks a lot for your help. I really appreciate it
Answer to Email showing in name field is you are actually saving email into name field.
change email field from this:
<%= f.email_field :name, required: true, :class => "form-control", :placeholder => "Email" %>
to this:
<%= f.email_field :email, required: true, :class => "form-control", :placeholder => "Email" %>
Answer to URL issue is:
in your controller after according to my assessment you should save the contact if u need. if contact save successfully you should redirect to new_contact_path.
controller should look like this:
def create
#contact=Contact.new(params[:contact])
#contact.request=request
if #contact.deliver
flash.now[:error]=nil
else
flash.now[:error]='Cannot send message.'
redirect_to new_contact_path
end
end
I'm attempting to validate and save an email from a form with three parameters: :name, :email, and :message, and then send the entire email. Currently, the email will send successfully without validating the parameters or creating an instance of Email.
Controller
def thank_you
#name = params[:name]
#email = params[:email]
#message = params[:message] || "Hello!"
if Email.create(name: #name, email: #email, message: #message)
ActionMailer::Base.mail(
:from => #email,
:to => 'erikvdw#comcast.net',
:subject => "A new contact form message from #{#name}",
:body => #message).deliver
end
end
Model
class Email < ActiveRecord::Base
validates_presence_of :name
validates_format_of :email, :with => /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
validates_length_of :message, :maximum => 500, :minimum => 10
end
View
<%= form_tag("/thank_you") do %>
<div class="row">
<div class="col-md-5">
<div class="input-group">
<%= text_field_tag :name, nil, class: 'form-control', placeholder: 'Your Name' %>
</div>
</div>
<div class="col-md-7">
<div class="input-group">
<span class="input-group-addon" id="basic-addon1">#</span>
<%= text_field_tag :email, nil, class: 'form-control', placeholder: 'Your Email Address' %>
</div>
</div>
</div>
<br>
<div class="row">
<div class="col-md-12">
<div class="input-group text-area-wide">
<%= text_area_tag :message, nil, class: 'form-control text-area-wide', placeholder: 'When are you available?' %>
</div>
</div>
</div>
<br>
<%= submit_tag 'Get Started', class: 'btn btn-success' %>
<p>Skype required</p>
<% end %>
I think your problem in the operation
Email.create
because it's creating a instance in memory and don't save the instance to DB.
You must call save method or check validation method directly - email.valid?, like this:
email = Email.create(name: #name, email: #email, message: #message)
if email.valid?
#send email
end