I would like to use ruby mail_form and Heroku Sendgrid to allow users to send me an email. I have set up the following Contact class in apps/models/contact.rb
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 => "example#email.com",
:from => %("#{name}" <#{email}>)
}
end
end
However, when I visit the page where I have set up my form, I receive the following error message:
undefined local variable or method `email' for Contact:Class
Commenting out the email attribute defined in my Contact class produces similar errors in subsequent attributes message: and nickname:
Below is my Contacts controller, contacts_controller.rb
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] = "Oops! There was an error."
render :new
end
end
end
and my form, new.html.erb
<% provide(:title, "Contact") %>
<h1>Contact</h1>
<%= form_for #contact do |f| %>
<%= f.label :name %><br>
<%= f.text_field :name, required: true %>
<br>
<%= f.label :email %><br>
<%= f.text_field :email, required: true %>
<br>
<%= f.label :message %><br>
<%= f.text_area :message, as: :text %>
<div class="hidden">
<%= f.label :nickname %><br>
<%= f.text_field :nickname, hint: "Leave this field blank." %>
</div>
<%= f.submit "Send Message", class: "btn" %>
<% end %>
<ul class="pager">
<li>Previous</li>
</ul>
Any help or suggestions would be greatly appreciated!
You omitted double quotes in the from option.
def headers
{
:subject => "Contact Form",
:to => "example#email.com",
:from => %("#{name}" <#{email}>)
}
end
Related
I am new to rails. I have created an app and a simple contact form. When I fill the contact form out it seems to submit everything fine. I don't get any errors, and the console shows that it worked.
However I am not receiving these emails in my inbox or spam folder. Can anyone tell me what I am doing wrong?
I followed this tutorial
Routes
match '/contacts', to: 'contacts#new', via: 'get'
resources "contacts", only: [:new, :create]
Contacts Controller
class ContactsController < ApplicationController
def new
#contact = Contact.new
end
def create
#contact = Contact.new(params[:contact])
#contact.request = request
if #contact.deliver
redirect_to root_path
flash.now[:notice] = 'Thank you for your message. We will contact you soon!'
else
flash.now[:error] = 'Cannot send message.'
render :new
end
end
end
Model
class Contact < MailForm::Base
attribute :name, :validate => true
attribute :email, :validate => /\A([\w\.%\+\-]+)#([\w\-]+\.)+([\w]{2,})\z/i
attribute :message
attribute :nickname, :captcha => true
# Declare the e-mail headers. It accepts anything the mail method
# in ActionMailer accepts.
def headers
{
:subject => "My Contact Form",
:to => "myemail#gmail.com",
:from => %("#{name}" <#{email}>)
}
end
end
New.html.erb
<div align="center">
<h3>Send A message to Us</h3>
<%= simple_form_for #contact, :html => {:class => 'form-horizontal' } do |f| %>
<%= f.input :name, :required => true %>
<%= f.input :email, :required => true %>
<%= f.input :message, :as => :text, :required => true %>
<div class= "hidden">
<%= f.input :nickname, :hint => 'Leave this field blank!' %>
</div>
<div>
</br>
<%= f.button :submit, 'Send message', :class=> "btn btn-primary" %>
</div>
<% end %>
</div>
Create.html.erb
<div>
<% flash.each do |key, value| %>
<div>
×
<%= value %>
</div>
<% end %>
</div>
I am using active_attr and simple_form.
When I navigate to the page that should show my form I get the following error:
undefined method `new_record?' for #<Message body: nil, email: nil, name: nil, subject: nil>
Here is my model:
class Message
include ActiveAttr::Model
attribute :name
attribute :email
attribute :subject
attribute :body
validates :name, :email, :subject, :body, :presence => true
validates :email, :format => { :with => %r{.+#.+\..+} }, :allow_blank => true
end
My Controller:
class ContactController < ApplicationController
def new
#message = Message.new
end
def create
#message = Message.new(params[:message])
if #message.valid?
NotificationsMailer.new_message(#message).deliver
redirect_to(root_path, :notice => "Message was successfully sent.")
else
flash.now.alert = "Please fill all fields."
render :new
end
end
end
And finally my view:
<%= simple_form_for #message, :url => contact_path do |f| %>
<%= f.input :name %>
<%= f.input :email %>
<%= f.input :subject %>
<%= f.input :body %>
<%= f.button :wrapped, :submit %>
<% end %>
Apparently the extra functionality I included to make a wrapped button for twitter bootstrap as found on https://github.com/plataformatec/simple_form/wiki/Twitter-Bootstrap-v2-and-simple_form-v2 broke it.
This error was due to a bug in active_attr that was fixed in v0.7.0. Upgrading resolves the issue.
I have been having some serious trouble all weekend trying to get this basic contact form to work correctly.
Effectively I want the user to be able to complete the form, hit send and have the message send straight to a predefined email address.
The error I am continually getting is:
NoMethodError in Messages#new
Showing C:/Sites/jobapp_v2/app/views/messages/new.html.erb where line #1 raised:
undefined method `[]' for nil:NilClass
Extracted source (around line #1):
1: <%= form_for #message, :url => contact_path do |f| %>
2:
3: <div class="field">
4: <%= f.label :name %>
I have the following setup:
Messages controller
class MessagesController < ApplicationController
def new
#user = current_user
#message = Message.new
end
def create
#message = Message.new(params[:message])
if #message.valid?
NotificationsMailer.new_message(#message).deliver
redirect_to(root_path, :notice => "Message was successfully sent.")
else
flash.now.alert = "Please fill all fields."
render :new
end
end
end
Message Model
class Message < ActiveRecord::Base
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :name, :email, :subject, :body
validates :name, :email, :subject, :body, :presence => true
validates :email, :format => { :with => %r{.+#.+\..+} }, :allow_blank => true
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
end
def persisted?
false
end
end
Routes.rb
JobappV2::Application.routes.draw do
devise_for :users
resources :newsletters
match "contact" => "messages#new", :as => "contact", :via => :get
match "contact" => "messages#create", :as => "contact", :via => :post
get "pages/about"
get "pages/contact"
get "pages/terms"
resources :jobs
resources :users do
resources :jobs
end
root :to => 'jobs#index'
end
NotificationsMailer.rb
class NotificationsMailer < ActionMailer::Base
default :from => "advertise#artisanmag.co.uk"
default :to => "tom.pinchen#artisanmag.co.uk"
def new_message(message)
#message = message
mail(:subject => "Hello")
end
end
Views/notification_mailer/new_message.text.erb
Name: <%= #message.name %>
Email: <%= #message.email %>
Subject: <%= #message.subject %>
Body: <%= #message.body %>
Views/messages/new.html.erb
<%= form_for #message, :url => contact_path do |f| %>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :email %>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :subject %>
<%= f.text_field :subject %>
</div>
<div class="field">
<%= f.label :body %>
<%= f.text_area :body %>
</div>
<%= f.submit "Send" %>
<% end %>
I really for can't work out at all what is causing this undefined method error so any help people can offer would really be much appreciated! Thanks in Advance :)
The way you have hooked things up, you don't need :url => contact_path
<%= form_for #message do |f| %>
will work just fine.
I'd like to pass the parameter recipient to controller. I can show it in my view like this:
#recipient.username
How can I pass this value to params[:message][:recipient]? Note that I do not have a model called "Message".
controllers/messages_controller.rb
def deliver
recipient = User.find_by_username(params[:recipient])
subject = params[:subject]
body = params[:body]
current_user.send_message(recipient, body, subject)
redirect_to :controller => 'messages', :action => 'received'
flash[:notice] = "message sent!"
end
views/messages/new.html.erb
<td><%= #recipient.username if #recipient %></td>
<%=form_for :messages, url: url_for( :controller => :messages, :action => :deliver ) do |f| %>
<div class="field">
<%= f.label :subject %><br />
<%= f.text_field :subject %>
</div>
<div class="field">
<%= f.label :body %><br />
<%= f.text_field :body %>
</div>
<div class="actions">
<%= f.submit %>
<% end %>
You could do this by assigning an attr_accessible key for your Recipient and assign it to the form.
form_for :message do |f|
f.hidden_field :recipient_id, :value => #recipient.id.to_i
f.text_field :message
f.submit
end
once you pass this to your create action you are able to check params[:message][:recipient_id]
and pass this to the db.
Have fun
Bassicaly my problem what to do if i have 3 forms and one submit button.
I want to create a form which sends email to each recipient and then create new record in free_registration_coupons table.
I need validation of email for this form.
Model FreeRegistrationCoupon: recipient_email, token, sender_id
For now i have this:
class FreeRegistrationCouponsController < ApplicationController
def send_invitations
emails = [params[:recipient_email_1], params[:recipient_email_2], params[:recipient_email_3]]
emails.reject!{ |e| e.eql?("") }
if emails.present?
emails.each do |e|
FreeRegistrationCoupon.create(:recipient_email => e, :sender_id => current_user.id)
#MAILER
end
redirect_to root_path, :notice => "You just send #{emails.size} invitations!"
else
redirect_to(:back)
end
end
end
class FreeRegistrationCoupon < ActiveRecord::Base
before_save :generate_token
attr_accessor :recipient_email, :sender_id
validates :recipient_email, :presence => true, :email => true
def generate_token
self.token = SecureRandom.hex
end
end
This is form which is in other controller CarsController#confirm:
<%= form_tag :controller => 'free_registration_coupons', :action => "send_invitations" do %>
<!-- errors -->
<%= label_tag :recipient_email_1 %>
<%= text_field_tag :recipient_email_1 %>
<%= label_tag :recipient_email_2 %>
<%= text_field_tag :recipient_email_2 %>
<%= label_tag :recipient_email_3 %>
<%= text_field_tag :recipient_email_3 %>
<%= submit_tag %>
<% end %>
I think you should have defined your form using:
<%= form_tag :controller => 'free_registration_coupons', :action => "send_invitations" do %>
<%= #error_message %>
<%= label_tag "recipient_email[1]" %>
<%= text_field_tag "recipient_email[1]" %>
<%= label_tag "recipient_email[2]" %>
<%= text_field_tag "recipient_email[2]" %>
<%= label_tag "recipient_email[3]" %>
<%= text_field_tag "recipient_email[3]" %>
<%= submit_tag %>
<% end %>
This way it will be easier to treat all email address on your controller and you can track those errors to display them afterwards:
class FreeRegistrationCouponsController < ApplicationController
def send_invitations
emails = params[:recipient_email]
emails.reject!{ |param, value| value.eql?("") }
errors = []
if emails.any?
emails.each do |param, value|
validation_result = FreeRegistrationCoupon.save(:recipient_email => value, :sender_id => current_user.id)
#MAILER
end
redirect_to root_path, :notice => "You just send #{emails.size} invitations!"
else
#error_message = "You have to include, at least, one e-mail address!"
render :name_of_the_action_that_called_send_invitations
end
end
end
I didnt test this code. Hope it helps!