Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Tutorial: Create and Deploy a Contact Form to Production in Ruby on Rails 5

Create a Contact Form in Rails 5

This is a complete, step-by-step tutorial showing how to create a fully functional contact form in production in rails 5. Rather than reinvent things, the following borrows from the best available documentation and tutorials (most notably, this tutorial on making a contact form in development). The finished contact form can be viewed here.

This tutorial uses:

  • heroku for deployment,
  • gmail for the mailer, and
  • github for version control

It would be a good idea to create a new gmail account to use for your mailer now, if you haven't already. If you haven't yet got a heroku account and installed the heroku CLI, it would be easiest to do so now.

Steps

  1. Make a new rails app and cd into it:
rails new contactform --database=postgresql
cd contactform

The --database=postgresql option tells your app to use posgresql, which will prevent various database errors when deploying to heroku. If you forget this option, it's always possible to adjust your gemfile later to specify use of postgres in production.

  1. Create a new github repository (do so in the browser), and let your newly created app know about it:
git init
git add . 
git commit -m "First commit to github repo"
git remote add origin https://github.com/stevecondylios/name_of_new_repository.git
git push -u origin master
  1. Add the following gems to your gemfile:
gem 'bootstrap-sass', '~> 3.3', '>= 3.3.6'
gem 'mail_form'
gem 'jquery-rails', '~> 4.1', '>= 4.1.1'
gem 'dotenv-rails', groups: [:development, :test]
  1. Install the gems with: bundle install

  2. In your app's root directory (i.e. inside /contactform), create a new file called ".env". Inside this new file, simply add the following text (and nothing else), replacing your_gmail_email_address and your_gmail_password with your mailer's gmail address and password respectively (note: no quotations are used):

GMAIL_EMAIL=your_gmail_email_address
GMAIL_PASSWORD=your_gmail_password
  1. Add a single line at the end of your .gitignore file. The line should simply say: .env. This will tell github not to track your your .env file (it would be bad if it did, since this file contains your mailer's credentials). Here's what it should look like (note the only change to this file is on line 27):

  1. In app/assets/javascripts/application.js, there will be a section with javascript libraries (usually 4 lines of code all beginning with "//="). Replace these lines of code with these ones:
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require bootstrap
//= require_tree .
  1. Now create a controller with index action:

rails g controller Home index

Open app/views/home/index.html.erb and replace what's there with this:

<!-- app/views/home/index.html.erb -->

<h1>This is my one page app!</h1>
  <div id="contact">
    <%= render 'contact_form' %>
  </div>
  1. Inside app/views/home/ create a file called _contact_form.html.erb (note the leading underscore indicating that this is a partial - a piece of code which will be called and rendered from the view)
<!-- app/views/home/_contact_form.html.erb -->

<%= form_for @contact, url: home_index_path, remote: true do |f| %>
    <div class="col-md-6">
        <%= f.label :name %></br>
        <%= f.text_field  :name, required: true, class: "contact-form-text-area" %></br>

        <%= f.label :email %></br>
        <%= f.text_field :email, required: true, class: "contact-form-text-area" %></br>

      <%= f.label :message %></br>
      <%= f.text_area :message, rows: 8, cols: 40, required: true, class: "contact-form-text-area",
                        placeholder: "Send me a message"%></br>

      <div class= "hidden">
        <%= f.label :nickname %>
        <%= f.text_field :nickname, :hint => 'Leave this field blank!' %>
      </div>

      <%= f.submit 'Send Message', class: 'btn btn-primary' %>
    </div>
  <% end %>
  <div class="col-md-6" id="flash-message">
    <%= render 'flash' %>
  </div>
  1. Create a second partial called _flash.html.erb containing this:
<!-- app/views/home/_flash.html.erb -->

<% flash.each do |message_type, message| %>
    <%= content_tag(:div, message, class: "alert alert-#{message_type}") %>
<% end %>
  1. Create a file called create.js.erb containing this:
// app/views/home/create.js.erb

// Test for ajax success
console.log("This is the create.js.erb file");
// Render flash message
$('#contact').html("<%= j render 'contact_form' %>");
$('#flash-message').html("<%= j render 'flash' %>").delay(3000).fadeOut(4000);
  1. Make app/config/routes.rb look like this:
# app/config/routes.rb

Rails.application.routes.draw do
 
root      'home#index'
resources :home, only: [:index, :new, :create]
 
end
  1. And make the home_controller.rb file look like this:
# app/controllers/home_controller.rb

class HomeController < ApplicationController
  def index
    @contact = Home.new(params[:home])
  end

  def create
    @contact = Home.new(params[:home])
    @contact.request = request
    respond_to do |format|
      if @contact.deliver
        # re-initialize Home object for cleared form
        @contact = Home.new
        format.html { render 'index'}
        format.js   { flash.now[:success] = @message = "Thank you for your message. I'll get back to you soon!" }
      else
        format.html { render 'index' }
        format.js   { flash.now[:error] = @message = "Message did not send." }
      end
    end
  end
end
  1. Create a file named home.rb in app/models/, then add the following and change your_email@your_domain.com to the email address you want the contact form to send to (e.g. your personal email address) - keep the double quotations
# app/models/home.rb

class Home < 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 => "Contact Form Inquiry",
      :to => "your_email@your_domain.com",
      :from => %("#{name}" <#{email}>)
    }
  end
end
  1. Give our form some basic styling by adding the following to app/assets/stylesheets/home.scss:
// app/assets/stylesheets/home.scss

@import "bootstrap-sprockets";
@import "bootstrap";

body {
  background-color: black;
  color: white;
}
.contact-form-text-area {
  color: black;
}
.hidden { display: none; }
.alert-error {
background-color: #f2dede;
border-color: #eed3d7;
color: #b94a48;
text-align: left;
font-size: .8em;
}

.alert-alert {
background-color: #f2dede;
border-color: #eed3d7;
color: #b94a48;
text-align: left;
font-size: .8em;
}

.alert-success {
background-color: #dff0d8;
border-color: #d6e9c6;
color: #468847;
text-align: center;
font-size: .8em;
}

.alert-notice {
background-color: #dff0d8;
border-color: #d6e9c6;
color: #468847;
text-align: left;
font-size: .8em;
}
  1. Add the following in config/environments/development.rb (if you're unsure where to place it, create some space between the very last 'end' in the file, and place it there):
# config/environments/development.rb

  config.action_mailer.perform_deliveries = true
  config.action_mailer.raise_delivery_errors= true
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    address:              'smtp.gmail.com',
    port:                 587,
    domain:               'gmail.com',
    user_name:            ENV["GMAIL_EMAIL"],
    password:             ENV["GMAIL_PASSWORD"],
    authentication:       'plain',
    enable_starttls_auto: true  }

NOTE: Do not substitute GMAIL_EMAIL and GMAIL_PASSWORD in the above - leave them exactly as they are in the code above, as they are environment variables that are provided to the rails app from the .env file created in step 5.

  1. Now create the postgres database with rake db:create

  2. By default, gmail will block apps it is not familiar with, including yours. So now is the time to toggle your gmail settings to allow less secure apps

The contact form is now ready to use in development. Start the server with rails s and go to localhost:3000 in your browser. Your conctact form should be visible. Enter some dummy responses and click "Send Message". You should receive an email with the contents of the contact form.

Moving the contact form from development into production

  1. Create a new heroku app with:

heroku create new_app_name

  1. Substitute new_app_name for the name of your newly created app in two places in the following, then add the code to config/environments/production (as with development, place this code just inside the very last 'end' in the file):
# config/environments/production

config.action_mailer.default_url_options = { :host => 'new_app_name.herokuapp.com' }  
config.action_mailer.delivery_method = :smtp  
config.action_mailer.perform_deliveries = true  
config.action_mailer.raise_delivery_errors = false  
config.action_mailer.default :charset => "utf-8"  
config.action_mailer.smtp_settings = {
  address:              'smtp.gmail.com',
  port:                 587,
  domain:               'new_app_name.herokuapp.com',
  user_name:            ENV["GMAIL_EMAIL"],
  password:             ENV["GMAIL_PASSWORD"],
  authentication:       'plain',
  enable_starttls_auto: true  }

NOTE: As in development, leave GMAIL_EMAIL and GMAIL_PASSWORD exactly as they are in the above code.

  1. In July 2019, Heroku updated the bundler requirement, so we simply need to upgrade bundler locally (or else we'll get an error message when pushing to Heroku)

Simply run

gem install bundler -v 2.0.2
bundle update --bundler
  1. Now commit your app into your github repository and also to heroku:
git add . 
git commit -m "App ready for first deployment"
git push
git push heroku master
  1. Now your app is on the heroku server, but it's not live just yet, there are a couple more steps to go. Install your gems and set up the database:
heroku run bundle install
heroku run rake db:migrate
  1. Lastly, since github and heroku do not have access to the .env file with your environment variables, we need provide heroku with them (otherwise it will not be able to login to your mailer's email account to send you the emailed contact form). Replace your_gmail_email_address and your_gmail_password with your mailer's credentials (note no quotations) and copy the line into the terminal:
heroku config:set GMAIL_EMAIL=your_gmail_email_address GMAIL_PASSWORD=your_gmail_password

You're done!

Go to your heroku app's url (http://www.new_app_name.herokuapp.com - replace new_app_name with the name of the app you created in step 19), and test out your contact form.

The codebase

Code for this project can be found here.

@rachelwong

This comment has been minimized.

Copy link

@rachelwong rachelwong commented May 5, 2019

Hi Steve. Thank you for writing a really great walkthrough. I have followed your steps and hit a snag with deployment. It seems DOTENV is causing the issue. Is there anything in production.rb that we need to modify or add please? Thank you.

My code following your tutorial is here https://github.com/rachelwong/contact-rails

Screen Shot 2019-05-05 at 10 24 23 pm

@stevecondylios

This comment has been minimized.

Copy link
Owner Author

@stevecondylios stevecondylios commented May 6, 2019

@rachelwong I think you may have added some lines to app/config/application.rb

## RACHEL INSERT
Dotenv::Railtie.load
HOSTNAME = ENV['HOSTNAME']

If you comment these out, commit changes to git and push to heroku, your app should work

@rachelwong

This comment has been minimized.

Copy link

@rachelwong rachelwong commented May 6, 2019

@stevecondylios, thank you so much Steve once again! It worked :-)

@iroshiva

This comment has been minimized.

Copy link

@iroshiva iroshiva commented Nov 5, 2019

Hi, i followed the step. Works perfect on local, but not on heroku.... There were an issue with git push heroku master, i had to delete the gem 'boostrap-sass' and remove the require boostrap in application.js to pass it.(i already set bootstrap alert messages)
When trying to send the informations of the contact forms, i have my bootstrap message saying form is sent, but nothing on my mailing box... Have you an idea?

@stevecondylios

This comment has been minimized.

Copy link
Owner Author

@stevecondylios stevecondylios commented Nov 6, 2019

@iroshiva thanks for the great pickup. Looks like Heroku upgraded to bundler 2.0.2 in June 2019. I have fixed this issue in the tutorial above. To fix your app, all you'll need do is run

gem install bundler -v 2.0.2
bundle update --bundler

Then commit to git and push to heroku.

@iroshiva

This comment has been minimized.

Copy link

@iroshiva iroshiva commented Nov 6, 2019

@stevecondylios thanks, gonna try with this! One more question, i presume i don't have to allow less secure apps on gmail while testing on heroku??

@stevecondylios

This comment has been minimized.

Copy link
Owner Author

@stevecondylios stevecondylios commented Nov 6, 2019

@iroshiva you will still need to allow less secure apps - gmail won't send any email unless you do.

@iroshiva

This comment has been minimized.

Copy link

@iroshiva iroshiva commented Nov 6, 2019

@stevecondylios So if i do it for a client, he will need to do it too ? Not really secure... How can i do it in a professionnal way?

@iroshiva

This comment has been minimized.

Copy link

@iroshiva iroshiva commented Nov 6, 2019

@stevecondylios Allright, i figured it out with heroku sendgrid addon. If you wanna add it, here the step:

  • go to https://elements.heroku.com/addons/sendgrid and choose your plans: sendgrid starter for free up to 12000 mails

  • $ heroku addons:create sendgrid:starter (if it doesn't work, it's because you have to add a credit card on your account heroku)
    ==> it creates a SENDGRID_PASSWORD and SENGRID_USERNAME in the config vars of your heroku app

  • in config/environments/production.rb

      config.action_mailer.default_url_options = { :host => 'new_app_name.herokuapp.com' }  
    

    config.action_mailer.delivery_method = :smtp
    config.action_mailer.perform_deliveries = true
    config.action_mailer.raise_delivery_errors = false
    ActionMailer::Base.smtp_settings = {
    :user_name => ENV['SENDGRID_USERNAME'],
    :password => ENV['SENDGRID_PASSWORD'],
    :domain => 'heroku.com',
    :address => 'smtp.sendgrid.net',
    :port => 587,
    :authentication => :plain,
    :enable_starttls_auto => true
    }

  • git add

  • git push origin master

  • git push heroku master

  • with Gmail, put the mail in spam !!!!

get from the end of https://www.youtube.com/watch?v=QIoORYeBdhs

@wintervt

This comment has been minimized.

Copy link

@wintervt wintervt commented Nov 14, 2019

Hi. Works perfectly in development.

Interestingly in production, I looked at XHR requests and getting 200 (also set up a model to save the form detail in the db when the email is sent and that works perfectly too), however the email isn't coming through.

The form is at: http://milantoth-portfolio.herokuapp.com/contact

Do I need to change the domain to match the above?

This is my production.rb setup:

config.action_mailer.default_url_options = { :host => 'milantoth-portfolio.herokuapp.com' }
config.action_mailer.delivery_method = :smtp
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = false
config.action_mailer.default :charset => "utf-8"
config.action_mailer.smtp_settings = {
address: 'smtp.gmail.com',
port: 587,
domain: 'milantoth-portfolio.herokuapp.com',
user_name: ENV["GMAIL_EMAIL"],
password: ENV["GMAIL_PASSWORD"],
authentication: 'plain',
enable_starttls_auto: true }

@stevecondylios

This comment has been minimized.

Copy link
Owner Author

@stevecondylios stevecondylios commented Nov 14, 2019

@wintervt your production.rb code is fine, no need to change the domain (or the host). You could try heroku config to ensure the environment variables set correctly on heroku. And did you allow less secure apps in gmail? It could also have gone to spam (worth checking)

@wintervt

This comment has been minimized.

Copy link

@wintervt wintervt commented Nov 17, 2019

@stevecondylios thanks, had a space in my password, such a newbie error... works perfectly now :)

@limjy0114

This comment has been minimized.

Copy link

@limjy0114 limjy0114 commented Jan 14, 2020

`Started POST "/home" for ::1 at 2020-01-14 15:09:18 +0800
Processing by HomeController#create as JS
Parameters: {"home"=>{"name"=>"lim jin yung", "email"=>"jinyung0069@gmail.com", "message"=>"wevrv4", "nickname"=>""}, "commit"=>"Send Message"}
Rendering /home/lim/.rvm/gems/ruby-2.5.1/gems/mail_form-1.8.0/lib/mail_form/views/mail_form/contact.erb
Rendered /home/lim/.rvm/gems/ruby-2.5.1/gems/mail_form-1.8.0/lib/mail_form/views/mail_form/contact.erb (Duration: 0.5ms | Allocations: 319)
MailForm::Notifier#contact: processed outbound mail in 1.4ms
Delivered mail 5e1d691e21089_72162add9bbc5ea068791@lim-Vostro-5468.mail (2.3ms)
Date: Tue, 14 Jan 2020 15:09:18 +0800
From: lim jin yung jinyung0069@gmail.com
To: jinyung.lim@afiintra.com
Message-ID: 5e1d691e21089_72162add9bbc5ea068791@lim-Vostro-5468.mail
Subject: Contact Form Inquiry
Mime-Version: 1.0
Content-Type: text/html;
charset=UTF-8
Content-Transfer-Encoding: 7bit

Contact Form Inquiry

Name: lim jin yung

Email: jinyung0069@gmail.com

Message: wevrv4

Rendering home/create.js.erb
Rendered home/_flash.html.erb (Duration: 0.1ms | Allocations: 23)
Rendered home/_contact_form.html.erb (Duration: 3.0ms | Allocations: 1072)
Rendered home/_flash.html.erb (Duration: 0.1ms | Allocations: 22)
Rendered home/create.js.erb (Duration: 5.6ms | Allocations: 4226)
Completed 200 OK in 12ms (Views: 6.4ms | ActiveRecord: 0.0ms | Allocations: 8547)`

Hi, thanks for the tutorial and I've followed the steps but I'm not receiving any email from the website but my terminal show these message. I wonder what's wrong in my code? I've already allowed less secure apps in my gmail as well

Thanks

@stevecondylios

This comment has been minimized.

Copy link
Owner Author

@stevecondylios stevecondylios commented Jan 14, 2020

@limjy0114 Completed 200 OK in 12ms (Views: 6.4ms | ActiveRecord: 0.0ms | Allocations: 8547) looks like your app worked. Did you allow less secure apps to ensure gmail sends the email?

@limjy0114

This comment has been minimized.

Copy link

@limjy0114 limjy0114 commented Jan 14, 2020

Yes I did, checked several times :(
Screenshot from 2020-01-14 15-37-03

@stevecondylios

This comment has been minimized.

Copy link
Owner Author

@stevecondylios stevecondylios commented Jan 14, 2020

@limjy0114 it's also possible that it sent correctly, but that the incoming email got caught by spam filters. Worth checking your spam folder

@limjy0114

This comment has been minimized.

Copy link

@limjy0114 limjy0114 commented Jan 15, 2020

@stevecondylios I'm using Ubuntu Linux and is it going to affect the result of this tutorial? Moreover I haven't set up my mail for mail application in the desktop. And also I've checked everywhere in my mailbox and there's nothing inside :((

@stevecondylios

This comment has been minimized.

Copy link
Owner Author

@stevecondylios stevecondylios commented Jan 15, 2020

@limjy0114 Heroku runs on Ubuntu so it definitely can work on Ubuntu, although I don't know if you'd need to configure some outbound mail / firewall / port setting(s). I'm on mac, so I'm not sure what those settings (if any) could be.

Regarding the spam filter, just to confirm, the spam filter that matters is the spam filter on the account you're sending to (i.e. the one in Step 14).

@limjy0114

This comment has been minimized.

Copy link

@limjy0114 limjy0114 commented Jan 15, 2020

@stevecondylios I've manage to received my emails after I've changed the code below from production.rb to development.rb, but does this works after the website is in production already? Really appreciate for your reply and help.

config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: 'smtp.gmail.com',
port: 587,
domain: 'gmail.com',
user_name: ENV["GMAIL_EMAIL"],
password: ENV["GMAIL_PASSWORD"],
authentication: 'plain',
enable_starttls_auto: true }

@stevecondylios

This comment has been minimized.

Copy link
Owner Author

@stevecondylios stevecondylios commented Jan 15, 2020

@limjy0114 It's only a few steps to move the app from development to production. Follow each step carefully, especially step 20 (as some things differ between production.rb and development.rb).

@limjy0114

This comment has been minimized.

Copy link

@limjy0114 limjy0114 commented Jan 17, 2020

@stevecondylios Alright!! Really appreciate for all the help and replies!! :)) Thank you!!

@limjy0114

This comment has been minimized.

Copy link

@limjy0114 limjy0114 commented Jan 30, 2020

@stevecondylios Sorry to interrupt you again, but what if I'm putting the contact form in a 'contact_us' page instead of 'index' page? what should i change the url in _contact_form.html.erb ?? I've tried changing from home_index_path to contact_us_path / home_contact_us_path but it doesn't work. What should I change in my code.
p/s: I've also change the the controller as below image since it's in contact_us page
image

@stevecondylios

This comment has been minimized.

Copy link
Owner Author

@stevecondylios stevecondylios commented Jan 30, 2020

@limjy0114 You'll need to specify the custom controller method in app/views/home/_contact_form.html.erb like so <%= form_for @contact, url: 'home#contact_us', remote: true do |f| %>.

Don't forget to create a route as well; by adding get 'contact_us' => 'home#contact_us' to app/config/routes.rb.

@limjy0114

This comment has been minimized.

Copy link

@limjy0114 limjy0114 commented Feb 5, 2020

@stevecondylios it works!! Thank you so much!! :)

@stevecondylios

This comment has been minimized.

Copy link
Owner Author

@stevecondylios stevecondylios commented Feb 5, 2020

@limjy0114 glad to hear it! Well done!

@afiintra

This comment has been minimized.

Copy link

@afiintra afiintra commented Feb 5, 2020

@stevecondylios Hi, the article is very useful and informative. However, is it possible to let the user to choose the recipient in the form using radio button? For example after adding a radio button in the form , then in the home.rb we do something like:

`class Home < MailForm::Base
attribute :name, :validate => true
attribute :email, :validate => /\A([\w.%+-]+)@([\w-]+.)+([\w]{2,})\z/i
attribute :message
attribute :enquiry

def headers
  if @contact.enquiry == "customer service"
       then email = "customer@sample.com"
  else email = "sales@sample.com"
  end
  {
    :subject => "Contact Form Inquiry",
    :to => email,
    :from => %("#{name}" <#{email}>)
  }
end

end`

@stevecondylios

This comment has been minimized.

Copy link
Owner Author

@stevecondylios stevecondylios commented Feb 14, 2020

@afiintra sorry I haven't had time to help. How did you go? If you solved, you could post how you did it

@bdarab

This comment has been minimized.

Copy link

@bdarab bdarab commented Feb 23, 2020

Help Please!!!! I'm stuck!

ActionController::RoutingError (No route matches [POST] "/home/index"): Why?

Started POST "/home/index" for ::1 at 2020-02-23 22:28:02 +0100

ActionController::RoutingError (No route matches [POST] "/home/index"):

actionpack (5.2.4.1) lib/action_dispatch/middleware/debug_exceptions.rb:65:in call' web-console (3.7.0) lib/web_console/middleware.rb:135:in call_app'
web-console (3.7.0) lib/web_console/middleware.rb:30:in block in call' web-console (3.7.0) lib/web_console/middleware.rb:20:in catch'
web-console (3.7.0) lib/web_console/middleware.rb:20:in call' actionpack (5.2.4.1) lib/action_dispatch/middleware/show_exceptions.rb:33:in call'
railties (5.2.4.1) lib/rails/rack/logger.rb:38:in call_app' railties (5.2.4.1) lib/rails/rack/logger.rb:26:in block in call'
activesupport (5.2.4.1) lib/active_support/tagged_logging.rb:71:in block in tagged' activesupport (5.2.4.1) lib/active_support/tagged_logging.rb:28:in tagged'
activesupport (5.2.4.1) lib/active_support/tagged_logging.rb:71:in tagged' railties (5.2.4.1) lib/rails/rack/logger.rb:26:in call'
sprockets-rails (3.2.1) lib/sprockets/rails/quiet_assets.rb:13:in call' actionpack (5.2.4.1) lib/action_dispatch/middleware/remote_ip.rb:81:in call'
actionpack (5.2.4.1) lib/action_dispatch/middleware/request_id.rb:27:in call' rack (2.2.2) lib/rack/method_override.rb:24:in call'
rack (2.2.2) lib/rack/runtime.rb:22:in call' activesupport (5.2.4.1) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in call'
actionpack (5.2.4.1) lib/action_dispatch/middleware/executor.rb:14:in call' actionpack (5.2.4.1) lib/action_dispatch/middleware/static.rb:127:in call'
rack (2.2.2) lib/rack/sendfile.rb:110:in call' railties (5.2.4.1) lib/rails/engine.rb:524:in call'
puma (3.12.2) lib/puma/configuration.rb:227:in call' puma (3.12.2) lib/puma/server.rb:674:in handle_request'
puma (3.12.2) lib/puma/server.rb:476:in process_client' puma (3.12.2) lib/puma/server.rb:334:in block in run'
puma (3.12.2) lib/puma/thread_pool.rb:135:in `block in spawn_thread'
Started GET "/cable" for ::1 at 2020-02-23 22:28:11 +0100
Started GET "/cable/" [WebSocket] for ::1 at 2020-02-23 22:28:11 +0100
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
OnlineChannel is transmitting the subscription confirmation
ChatroomChannel is transmitting the subscription confirmation
ChatroomChannel is streaming from chatroom_channel

@stevecondylios

This comment has been minimized.

Copy link
Owner Author

@stevecondylios stevecondylios commented Feb 23, 2020

@bdarab the error message says your app can’t find the route. Does routes.rb look exactly like it does in step 12?

@bdarab

This comment has been minimized.

Copy link

@bdarab bdarab commented Feb 24, 2020

Hi Steve! Thanks for your prompt response. No! the routes are different, because I did not set it up as an independent app. I added it to an existing app with different routes. my route.rb is as follows :

Rails.application.routes.draw do

get 'home/index'
root 'pages#index'
get 'about', to: 'pages#about'
get 'contact', to: 'home#index'
get 'signup', to: 'users#new'
post 'signup', to: 'users#create'
get 'login', to: 'sessions#new'
post 'login', to: 'sessions#create'
get 'logout', to: 'sessions#destroy'
get 'chatroom', to: 'chatroom#index'
post 'message', to: 'messages#create'
resources :home, only: [:index, :new, :create]

mount ActionCable.server, at: '/cable'

resources :users
resources :articles

end

@iroshiva

This comment has been minimized.

Copy link

@iroshiva iroshiva commented Apr 3, 2020

Hi !

I set the contact-form in a homepage and use the sendgrid addon on heroku.
The message is sent according to heroku logs, but i don't receive it...
When i clic on the addon sendgrid, i've got this issue : SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data

Why ???

Thx

@stevecondylios

This comment has been minimized.

Copy link
Owner Author

@stevecondylios stevecondylios commented Apr 4, 2020

@iroshiva that could happen for any of a number of reasons - I'm not totally sure as I am not using the sendgrid addon.

I see the error message reported when

Your best bet may be to check that none of those things are happening

@cecileRx

This comment has been minimized.

Copy link

@cecileRx cecileRx commented Apr 7, 2020

Hello and thanks for the great tuto!
I have implemented the contact form and it worked well on local. I deployed the app on heroku and everything was ok except the contact form got a 500 error. I realized I forgot to follow step 20 so I added the code on config/environments/production.

Now when I push to Heroku I have this error:

Preparing app for Rails asset pipeline
remote: Running: rake assets:precompile
remote: rake aborted!
remote: NameError: undefined local variable or method config' for main:Object remote: /tmp/build_59279648c7463ce057feb0dc73e67818/config/environments/production.rb:97:in

'
remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in require' remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in block in require_with_bootsnap_lfi'
remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in register' remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in require_with_bootsnap_lfi'
remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in require' remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.4.1/lib/active_support/dependencies.rb:291:in block in require'
remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.4.1/lib/active_support/dependencies.rb:257:in load_dependency' remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.4.1/lib/active_support/dependencies.rb:291:in require'
remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/railties-5.2.4.1/lib/rails/engine.rb:608:in block (2 levels) in <class:Engine>' remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/railties-5.2.4.1/lib/rails/engine.rb:607:in each'
remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/railties-5.2.4.1/lib/rails/engine.rb:607:in block in <class:Engine>' remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/railties-5.2.4.1/lib/rails/initializable.rb:32:in instance_exec'
remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/railties-5.2.4.1/lib/rails/initializable.rb:32:in run' remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/railties-5.2.4.1/lib/rails/initializable.rb:61:in block in run_initializers'
remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/railties-5.2.4.1/lib/rails/initializable.rb:50:in each' remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/railties-5.2.4.1/lib/rails/initializable.rb:50:in tsort_each_child'
remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/railties-5.2.4.1/lib/rails/initializable.rb:60:in run_initializers' remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/railties-5.2.4.1/lib/rails/application.rb:361:in initialize!'
remote: /tmp/build_59279648c7463ce057feb0dc73e67818/config/environment.rb:5:in <main>' remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in require'
remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in block in require_with_bootsnap_lfi' remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in register'
remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in require_with_bootsnap_lfi' remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in require'
remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.4.1/lib/active_support/dependencies.rb:291:in block in require' remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.4.1/lib/active_support/dependencies.rb:257:in load_dependency'
remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.4.1/lib/active_support/dependencies.rb:291:in require' remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/railties-5.2.4.1/lib/rails/application.rb:337:in require_environment!'
remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/railties-5.2.4.1/lib/rails/application.rb:520:in block in run_tasks_blocks' remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/sprockets-rails-3.2.1/lib/sprockets/rails/task.rb:62:in block (2 levels) in define'
remote: /tmp/build_59279648c7463ce057feb0dc73e67818/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/exe/rake:27:in `<top (required)>'
remote: Tasks: TOP => environment
remote: (See full trace by running task with --trace)
remote:
remote: !
remote: ! Precompiling assets failed.
remote: !
remote: ! Push rejected, failed to compile Ruby app.

I updated the bundler but it still not working. Anyone could help please? Thanks!!
Cécile

@stevecondylios

This comment has been minimized.

Copy link
Owner Author

@stevecondylios stevecondylios commented Apr 8, 2020

@cecileRx the app is failing to compile, most likely due to either a syntax error in config/environments/production.rb (take a look toward the bottom of this to see how the code should be inserted - don't forget the final end), or perhaps the environment variables didn't set correctly in heroku (you can see if they set correctly with heroku config).

@cecileRx

This comment has been minimized.

Copy link

@cecileRx cecileRx commented Apr 8, 2020

Thank you so much Steve, my code misses the 'end' on the production file! Another issue I am still not able to debug: My contact form doesn't empty itself after the success alert. The 'home' page is not rendered again, despite the code below:

class PagesController < ApplicationController
def home
@contact = Pages.new(params[:pages])
@tours = Tour.order(:id)
@leaks = Leak.all
end

def create
@contact = Pages.new(params[:pages])
@contact.request = request
respond_to do |format|
if @contact.deliver
# re-initialize Pages object for cleared form
@contact = Pages.new
format.html { render 'home' }
format.js { flash.now[:success] = @message = "Thank you for your message. I'll get back to you soon!" }
else
format.html { render 'home' }
format.js { flash.now[:error] = @message = "Message did not send." }
end
end
end
end

Thanks again for your suggestions!

@stevecondylios

This comment has been minimized.

Copy link
Owner Author

@stevecondylios stevecondylios commented Apr 8, 2020

@cecileRx I can't know for sure without reviewing your code, but some ideas.

Models are typically singular (i.e. Pages.new should be Page.new).

I think your controller, view and routes are all consistent already, but just in case, since you're using a home method in the pages controller, the form should resemble:

<%= form_for @contact, url: 'pages#home', remote: true do |f| %>

and routes (app/config/routes.rb) should look something like

get 'contact' => 'pages#home' 
@cecileRx

This comment has been minimized.

Copy link

@cecileRx cecileRx commented Apr 8, 2020

Thanks again, yes the controller, view, routes and form code are ok. I am going to search deeper. Would you say it's a JS issue? Do you have advice about tools for me to help to debug?

@stevecondylios

This comment has been minimized.

Copy link
Owner Author

@stevecondylios stevecondylios commented Apr 14, 2020

@cecileRx

It could be a JS issue, but it sounds like something's not quite right in the controller. As for debugging, I recommend carefully reading the server logs and comparing what happened to what you were expecting to happen. The byebug gem is an amazing tool, and could be very helpful in this case

If debugging doesn't yield results, try starting again from the beginning - it's good practice and often faster than debugging, especially second time around!

@Tshamp7

This comment has been minimized.

Copy link

@Tshamp7 Tshamp7 commented Jul 19, 2020

Im having an issue where I cant get the flash to render properly (at all). Ive never really done anything with AJAX or embedding ruby in javascript files. Is there some sort of dependency I need to include so my js.erb file runs okay? I think it has something to do with that file as I have checked all the logic and everything seems to be triggering okay.

@wescreations

This comment has been minimized.

Copy link

@wescreations wescreations commented Jul 31, 2020

@stevecondylios

Here's my production.rb file

Everything works fine locally, but in heroku the emails just don't make it to my gmail. I allowed less secure apps, also the environment variables are 100% working. App works on heroku and all, message is submitted fine, but no email received, not in spam either.

Any ideas here anyone? Also, there's no error in my log to share or I would

config.action_mailer.default_url_options = { :host => 'poliking.herokuapp.com' }
config.action_mailer.delivery_method = :smtp
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = false
config.action_mailer.default :charset => "utf-8"
config.action_mailer.smtp_settings = {
address: 'smtp.gmail.com',
port: 587,
domain: 'poliking.herokuapp.com',
user_name: ENV["GMAIL_EMAIL"],
password: ENV["GMAIL_PASSWORD"],
authentication: 'plain',
enable_starttls_auto: true }

@toluooshy

This comment has been minimized.

Copy link

@toluooshy toluooshy commented Sep 2, 2020

@stevecondylios

Here's my production.rb file

Everything works fine locally, but in heroku the emails just don't make it to my gmail. I allowed less secure apps, also the environment variables are 100% working. App works on heroku and all, message is submitted fine, but no email received, not in spam either.

Any ideas here anyone? Also, there's no error in my log to share or I would

config.action_mailer.default_url_options = { :host => 'poliking.herokuapp.com' }
config.action_mailer.delivery_method = :smtp
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = false
config.action_mailer.default :charset => "utf-8"
config.action_mailer.smtp_settings = {
address: 'smtp.gmail.com',
port: 587,
domain: 'poliking.herokuapp.com',
user_name: ENV["GMAIL_EMAIL"],
password: ENV["GMAIL_PASSWORD"],
authentication: 'plain',
enable_starttls_auto: true }

I have a similar issue. Any luck?

@Ravemaster8

This comment has been minimized.

Copy link

@Ravemaster8 Ravemaster8 commented Oct 9, 2020

@stevecondylios
Here's my production.rb file
Everything works fine locally, but in heroku the emails just don't make it to my gmail. I allowed less secure apps, also the environment variables are 100% working. App works on heroku and all, message is submitted fine, but no email received, not in spam either.
Any ideas here anyone? Also, there's no error in my log to share or I would
config.action_mailer.default_url_options = { :host => 'poliking.herokuapp.com' }
config.action_mailer.delivery_method = :smtp
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = false
config.action_mailer.default :charset => "utf-8"
config.action_mailer.smtp_settings = {
address: 'smtp.gmail.com',
port: 587,
domain: 'poliking.herokuapp.com',
user_name: ENV["GMAIL_EMAIL"],
password: ENV["GMAIL_PASSWORD"],
authentication: 'plain',
enable_starttls_auto: true }

I have a similar issue. Any luck?

I have the same issue. I am also getting the following in both the heroku logs and localhost logs:

@wescreations @toluooshy

Having to do the following was the solution for me.

http://www.google.com/accounts/DisplayUnlockCaptcha

@stevecondylios I am not getting any of the flash messages. The console is asking me to define the $ that's in the create.js.erb.

EDIT:

http://hanspreeker-portfolio.herokuapp.com/ is the portfolio I used it on. Currently the mailing stopped as well, but the console looks perfect, so I don't know how it happened.

https://github.com/Ravemaster8/developer_portfolio Here's the code on my github. Currently trying anything and everything to make it work again XD. Want to launch my portfolio this weekend.

@SLegrez

This comment has been minimized.

Copy link

@SLegrez SLegrez commented Oct 26, 2020

@Ravemaster8 @toluooshy Same problem as yours, everything works fine in development (i receive the mails), no console errors on heroku but i dont receive the mails this time. Also checked the spams.

If someone has an idea... @stevecondylios

@Ravemaster8

This comment has been minimized.

Copy link

@Ravemaster8 Ravemaster8 commented Oct 27, 2020

@Ravemaster8 @toluooshy Same problem as yours, everything works fine in development (i receive the mails), no console errors on heroku but i dont receive the mails this time. Also checked the spams.

If someone has an idea... @stevecondylios

@SLegrez

I know what is happening, google(gmail) Is blocking this. Somewhere in this post you'll see someone talking about sendgrid, I believe that is the solution. I am currently working on something else, but I will chase that solution pretty soon as well.

@SLegrez

This comment has been minimized.

Copy link

@SLegrez SLegrez commented Oct 28, 2020

@Ravemaster8 I've tried with Sendgrid, it works in development but not in production unfortunately... :(
Nothing in the spams either

@przemo88

This comment has been minimized.

Copy link

@przemo88 przemo88 commented Nov 20, 2020

Hi Steve, tell me how can i assign css styles for the form?
My code:

Email form - index.html.erb
`

Contact Form

<%= form_for @DaTa, url: 'email#index', remote: true do |f| %>

<div class="col-lg-8 offset-lg-2">
  <%= f.label :name, class: "col-lg-4 offset-lg-4 form_text" %>
  <%= f.text_field :name, class: "col-lg-12" %>
</div>

<div class="col-lg-8 offset-lg-2">
  <%= f.label "Email", class: "col-lg-4 offset-lg-4 form_text" %>
  <%= f.text_field :email, class: "col-lg-12", type: 'email' %>
</div>

<div class="col-lg-8 offset-lg-2">
  <%= f.label "Message", class: "col-lg-4 offset-lg-4 form_text" %>
  <%= f.text_area(:message, cols: 40, rows: 10, class: "col-lg-12") %>
</div>

  <div class="col-lg-8 offset-lg-2">
  <%= f.submit "Send", class: "col-lg-2 mt-50 offset-lg-5" %>
  </div>
</div>

<% end %>
`

en.yml
mail_form: errors: models: email: attributes: name: blank: "My custom message goes here"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.