uninitialized constant on Rails 4 - ruby-on-rails

I'm trying to build my first contact form, that would send someone's name, email and message to my email address to me. I've seen quite a lot of tutorials and answered questions on stackoverflow, but it didn't help me to fix the problem I'm having. I know it has something to do with the routing but I can't figure what and why.
I'm getting the following error:
Routing Error
uninitialized constant ContactController
Here are my files :
routes.rb
match '/send_mail', to: 'contact#send_mail', via: 'post'
match '/mail', to: 'contact#contact', via: 'get'
controllers/contacts_controller.rb
def send_mail
name = params[:name]
email = params[:email]
body = params[:comments]
ContactMailer.contact_email(name, email, body).deliver
redirect_to contact_path, notice: 'Message sent'
end
mailers/contact_mailer.rb
class ContactMailer < ActionMailer::Base
default to: 'mymail#gmail.com'
def contact_email(name, email, body)
#name = name
#email = email
#body = body`enter code here`
mail(from: email, subject: 'Contact Request')
end
end
views/contact.html.twig
<div class="container-content">
<div class="container">
<%= form_tag(send_mail_path) do %>
<div class="form-group">
<%= label_tag 'name', 'Name' %>
<%= text_field_tag 'name', nil, class: 'form-control', placeholder: 'John Doe' %>
</div>
<div class="form-group">
<%= label_tag 'email', 'Email' %>
<%= email_field_tag 'email', nil, class: 'form-control', placeholder: 'johndoe#domain.com' %>
</div>
<div class="form-group">
<%= label_tag 'comments', 'Comments' %>
<%= text_area_tag 'comments', nil, class: 'form-control', rows: 4, placeholder: 'How can I help you?' %>
</div>
<%= submit_tag nil, class: 'btn btn-default btn-about' %>
<% end %>
</div>
</div>
views/contact_email.html.erb
<!DOCTYPE html>
<html>
<head>
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<p>Mail received from <%= "#{ #name } (#{ #email }):" %></p>
<p><%= #body %></p>
</body>
</html>
config/initializers.rb
module Contact
class Application < Rails::Application
config.action_mailer.delivery_method = :sendmail
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
config.active_record.raise_in_transactional_callbacks = true
end
end
initializers/stmp_config.rb
config.action_mailer.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:domain => "gmail.com",
:user_name => "mymail#gmail.com",
:password => "password",
:authentication => :login,
:enable_starttls_auto => true
}
As I'm newbie in the rails world, I'm not sure at all of what I'm doing, but I've seen a lot of tutorials where people had a code similar to mine, but no one seems to have this problem
Where did i go wrong ?
Thank you in advance

You may want to change your routes.rb as follows (contacts instead of contact):
match '/send_mail', to: 'contacts#send_mail', via: 'post'
match '/mail', to: 'contacts#contact', via: 'get'

Thats one way to create a contact form - however its not really a Rails app. Its just an app that happens to be using Rails.
This is how you can use the Rails conventions to make this more robust and less messy.
Model
Lets generate a model and migration:
$ rails g model enquiry name:string email:string body:text
Then we run the migration:
$ rake db:migrate
So why create a model if we are just sending an email? Because email fails. And you don't want to lose important enquiries from potential customers.
We also want our model to validate that the user provides the required fields:
# app/models/enquiry.rb
model Enquiry < ActiveRecord::Base
validates_presence_of :name, :email, :body
validates_format_of :email, with: /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
end
Controller
Lets create a RESTful route:
# config/routes.rb
# ...
resources :enquiries, only: [:new, :create]
Note that we are calling it enquiries. Instead of using an procedure oriented send_contact route we have the resource enquiries which gives us conventions for how to show, create and update it.
You can see what routes are generated with $ rake routes.
See Resource Routing: the Rails Default.
Lets create a controller for our new route:
# app/controllers/enquiries_controller.rb
# note controllers use the plural form
class EnquiriesController < ApplicationController
# GET '/enquiries/new'
def new
#enquiry = Enquiry.new
end
# POST '/enquiries'
def create
#enquiry = Enquiry.new(enquiry_params)
if #enquiry.save
ContactMailer.contact_email(name, email, body).deliver
redirect_to root_path, success: 'Thanks for getting in touch, we will look into it ASAP.'
else
render :new
end
end
private
def enquiry_params
params.require(:enquiry).permit(:name, :email, :body)
end
end
View
We also need a form:
# app/views/enquiries/new.html.erb
<%= form_for(#enquiry) do |f| %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :name %>
</div>
<div class="form-group">
<%= f.label :body %>
<%= f.text_area :body %>
</div>
<%= f.submit %>
<% end %>
By using a form builder and a model our form will automatically "play back" the values if the user submits an invalid form.

Your problem in 'ContactController' - it's must be in plural: 'ContactsController'!

Related

No route matches {:action=>"partner_update", :controller=>"users"}

i'm new in rails so i tried to do this to add a role, making a form to update and if the user update succsessfully add the role.
note: i'm using devise and rolify with cancancan
routes
get 'users/becomepartner' => 'users#becomepartner' do
collection do
patch 'update_partner'
end
end
and this is my users controller
def becomepartner
#user = current_user
end
def update_partner
#user = User.find(current_user.id)
if #user.update_with_password(partner_params)
self.add_role(:partner)
# Sign in the user by passing validation in case their password changed
bypass_sign_in(#user)
redirect_to root_path, notice: 'now you can create'
else
render :becomepartner
end
end
private
def partner_params
# NOTE: Using `strong_parameters` gem
params.require(:user).permit(:name, :style, :current_password, :email)
end
and this is my view becomepartner.html
<div>
<%= form_for(#user, :url => { :action => "update_partner" } ) do |f| %>
<div class="field">
<%= f.label :style %>
<%= f.text_field :style %>
</div>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :email %>
<%= f.email_field :email %>
</div>
<div class="field">
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i>
<%= f.password_field :current_password, autocomplete: "off" %>
</div>
<% end %>
</div>
In form action you have mentioned action as partner_update but you don't have that action. Change it to update_partner.
You are using the collection route for another individual route, that is get 'users/becomepartner'. So this will generate the collection route with url like:
users/becomepartner/update_partner
You can confirm this by running rake routes.
But your forms action url will be different.
What you can do is create this collection route inside users resource route like:
resources :users do
collection do
patch 'update_partner'
end
end
Then in form_for url option, use update_partner_users_path
If you don't want the users resources routes, then just define a single route like:
get 'users/becomepartner' => 'users#becomepartner'
patch 'user/update_partner' => 'users#update_partner'
I have not ran any of this code, so if there is any syntax error then post it in comment.
In routes.rb,change
patch 'update_partner' to update 'update_partner' and remove collection as you are not operating on a collection.you have added it in a do block,instead add a one liner route path.
in the form,url must be update_partner and NOT partner_update .

Rails, Contact_us: Net::SMTPFatalError (550-Your FROM address

I'm using contact_us gem and it was working well until I added another mailer. The second mailer is working well but the contact_us form works just when the email field is my default from email in another mailer! Here are the files and settings:
contact_us.rb
# Use this hook to configure contact mailer.
ContactUs.setup do |config|
# ==> Mailer Configuration
# Configure the e-mail address which email notifications should be sent from. If emails must be sent from a verified email address you may set it here.
# Example:
# config.mailer_from = "contact#please-change-me.com"
config.mailer_from = nil
# Configure the e-mail address which should receive the contact form email notifications.
config.mailer_to = "hi#mysite.com"
# ==> Form Configuration
# Configure the form to ask for the users name.
config.require_name = false
# Configure the form to ask for a subject.
config.require_subject = false
# Configure the form gem to use.
# Example:
# config.form_gem = 'formtastic'
config.form_gem = nil
# Configure the redirect URL after a successful submission
config.success_redirect = '/'
end
application_mailer.rb
class ApplicationMailer < ActionMailer::Base
end
my_mailer.rb
class MyMailer < ApplicationMailer
default from: "\"mysite\" <hi#mysite.com>"
layout 'mailer'
#The email that should be sent to the Passenger after his successful payment
def payment_confirmation(user, trip, seats, code)
...
mail(to: #user.email, subject: "...")
end
end
and my contact_us form is like this:
<% #contact = ContactUs::Contact.new %>
<%= form_for #contact, :url => contacts_path, :id => "contact-form", :html => {:class => 'formtastic'} do |f| %>
<div class="input-group name-email">
<div class="input-field">
<%= f.text_field :name, :id => "name", :placeholder => "نام", :class => "form-control" %>
</div>
<div class="input-field">
<%= f.text_field :email, :id => "email", :placeholder => "ایمیل*", :class => "form-control" %>
<% if f.object.errors[:email].present? %>
<p class='inline-error'><%= f.object.errors[:email].join(' and ') %></p>
<% end %>
</div>
</div>
<div class="input-group">
<%= f.text_area :message, :id => "message", :placeholder => "پیغام*", :class => "form-control" %>
</div>
<div class="input-group">
<%= f.submit "ارسال پیغام", :id => "form-submit", :class => "pull-left" %>
</div>
<% end %>
So, the problem is that it works only when the user submits hi#mysite.com as his mail address in the contact_us form!!
Any idea and help would be appreciated ...

Name in Sendgrid Email with Rails

I'm using careerfoundry's tutorial on using Sendgrid to send emails with Heroku. I'm using their exact code for the user mailer and thank_you action in the pages controller. This code is working for the most part. The issue is that the subject line I receive in my inbox is this:
A new contact form message from #{name}
User_Mailer.rb
class UserMailer < ActionMailer::Base
default from: "from#example.com"
def contact_form(email, name, message)
#message = message
mail(:from => email,
:to => 'your-email#example.com',
:subject => "A new contact form message from #{name}")
end
end
Contact Form
<%= form_tag("/thank_you") do %>
<div class="row">
<div class="col-md-4">
<div class="input-group">
<%= text_field_tag :name, nil, class: 'form-control', placeholder: 'Name' %>
</div>
</div>
<div class="col-md-8">
<div class="input-group">
<span class="input-group-addon" id="basic-addon1">#</span>
<%= text_field_tag :email, nil, class: 'form-control', placeholder: 'Email' %>
</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: 'Message' %>
</div>
</div>
</div>
<br>
<%= submit_tag 'Send Message', class: 'btn btn-success' %>
<% end %>
Pages Controller
def thank_you
#name = params[:name]
#email = params[:email]
#message = params[:message] || "Hello!"
# Only try to send this email on a POST
# if request.post?
# or make a feedback form controller and send in the create action
# ActionMailer::Base.mail( FOR TEST PURPOSES
# :from => #email,
# :to => 'erikvdw#comcast.net',
# :subject => "A new contact form message from #{#name}",
# :body => #message).deliver
UserMailer.contact_form(#email, #name, #message).deliver
end
A quick fix would be to just split the string into two parts as such
class UserMailer < ActionMailer::Base
default from: "from#example.com"
def contact_form(email, name, message)
#message = message
mail(:from => email,
:to => 'your-email#example.com',
:subject => "A new contact form message from " + name) <----
end
end
This way the notation is clearer and it will avoid the manual concatenation problem.
After looking up a quick thing, it seems like this might also work. The single quotes are needed internally apparently according to a couple sources I found. I don't use that notation so let me know if it helped!
:subject => "A new contact form message from '#{name}'")

Rails routing, NoMethodError

I'm using Rails 3.2 and Ruby 4. When I browse to http://localhost:3000/account/new I get an error:
NoMethodError in Accounts#new
Showing D:/row/dev/basic/app/views/accounts/_form_account.html.erb where line #1 raised:
undefined method `accounts_path' for #<#<Class:0x42c8040>:0x6daa960>
Extracted source (around line #1):
1: <%= form_for(#account) do |f| %>
2:
3: <div>
4: <%= f.label :username %><br>
I created Account views using rails generate controller Controllernames index show new edit delete. I also ran rails generate model account.
According to the online Rails course I'm following this should create in routes.rb:
Edit: I used rails generate model accounts, so with the s at the end.
resources :accounts
get 'accounts/:id/delete' => 'accounts#delete', :as => :accounts_delete
However, this was not created in routes.rb. My routes.rb after some editing is:
Basismysql::Application.routes.draw do
# Public pages
get '/page1' => 'pages#page1'
get '/page2' => 'pages#page2'
get '/page3' => 'pages#page3'
get "/account/index" => 'accounts#index'
get "/account/show" => 'accounts#show'
get "/account/new" => 'accounts#new'
get "/account/edit" => 'accounts#edit'
get "/account/delete" => 'accounts#delete'
get 'account/:id/delete' => 'accounts#delete', :as => :accounts_delete
devise_for :users
root :to => 'pages#index'
end
New.html.erb is:
<div class="container">
<h1>Accounts#new</h1>
<p>Find me in app/views/accounts/new.html.erb</p>
</div>
<div class="container">
<%= render "form_account" %>
</div>
And _form_account.html.erb is:
<%= form_for(#account) do |f| %>
<div>
<%= f.label :username %><br>
<%= f.text_field :username %>
</div>
<div>
<%= f.label :firstname %><br>
<%= f.text_field :firstname %>
</div>
<div>
<%= f.label :lastname %><br>
<%= f.text_field :lastname %>
</div>
<div>
<%= f.label :organisation %>
<%= f.text_field :organisation %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Part of the account controller is:
def new
#account = Account.new
end
def create
#account = Account.new(account_params)
if #account.save
redirect_to(:action => 'index')
else
render('new')
end
end
private
def account_params
params.require(:account).permit(:username, :firstname, :lastname, :organisation)
end
get "/account/index" => 'accounts#index'
get "/account/show" => 'accounts#show'
get "/account/new" => 'accounts#new'
get "/account/edit" => 'accounts#edit'
get "/account/delete" => 'accounts#delete'
get 'account/:id/delete' => 'accounts#delete', :as => :accounts_delete
This isn't the way you should create routes, they are all unnamed(besides the last one), non-restful and all are get, replace this with
resources :accounts
And your error will gone
This works
rails generate controller accounts index show new edit destroy
Note: you must use accounts and not account while generating the controller
rails generate model account
Note: you must have account as singular
in routes.rb
map.resources :accounts /or
resources :accounts
depending upon the version of rails
In addition to:
resources :accounts
you probably need:
resource :account
You've started it by adding the routes piece-meal to the routes file, but some of those need to be PUTs or POSTs or DELETEs. resource :account is a simpler shortcut to do it (correctly).

receiving email to my gmail account using actionmailer

Please forgive the newbie question. I'm building a form that has a contact us page, in which a user should be able to fill out a form (user_full_name, user_email, subject, message), which when submitted should be sent as an email to my gmail address. I'm currently getting the following error when I try to access the view with the form on it.
undefined method `feedbacks_path' for #<#:0x007f8fefecd020>
below is my code, does anyone know what I'm doing wrong here? If possible I'd rather change the routes than add a url to the form. Also, want to use a 'match' in the routes to have the url path be 'localhost/contact' instead of 'localhost/feedback'. Does anyone have any ideas?
routes.rb
Sample::Application.routes.draw do
resources :feedback, only: [:new, :create]
root to: "home#index"
match '/about', to: 'static_pages#about', via: 'get'
match '/help', to: 'static_pages#help', via: 'get'
match '/privacy_policy', to: 'static_pages#privacy_policy', via: 'get'
match '/terms_and_conditions', to: 'static_pages#terms_and_conditions', via: 'get'
end
Feedback_Controller.rb
class FeedbackController < ApplicationController
def new
#feedback = Feedback.new
end
def create
#feedback = Feedback.new(params[:feedback])
if #feedback.valid?
FeedbackMailer.new_feedback(#feedback).deliver
flash[:success] = "We have receieved your message!"
redirect_to users_path
else
flash.now.alert = "Please fill in all fields."
render :new
end
end
end
Feedback.rb
class Feedback < ActiveRecord::Base
def self.columns() #columns ||= []; end
def self.column(name, sql_type = nil, default = nil, null = true)
columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
end
column :user_full_name, :string
column :user_email, :string
column :subject, :text
column :body, :text
belongs_to :user
end
view/feedback.new.html.erb
<div class="feedback">
<div class="container">
<%= form_for #feedback do |f| %>
<%= f.hidden_field :user_full_name %>
<%= f.hidden_field :user_email %>
<%= f.label :subject %>
<%= f.text_field :subject %>
<%= f.label :feedback %>
<%= f.text_area :body %>
<%= f.submit "Send", class: "btn btn-inverse" %>
<% end %>
</div>
</div>
feedback_mailer
<!DOCTYPE html>
<html>
<head>
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
</head>
<body>
Name: <%= #feedback.user_full_name %>
Email: <%= #feedback.user_email %>
Subject: <%= #feedback.subject %>
Comments/Question: <%= #feedback.body %>
</body>
</html>
feedback_mailer.rb
class FeedbackMailer < ActionMailer::Base
default to: "railstraining09#gmail.com"
def new_feedback(feedback)
#feedback = feedback
mail(from: #user.email, subject: 'feedback.subject')
end
end
If you are in developement you could add in app/config/environments/development.rb
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
# Gmail SMTP server setup
ActionMailer::Base.smtp_settings = {
:address => "smtp.gmail.com",
:enable_starttls_auto => true,
:port => 587,
:authentication => :plain,
:user_name => ENV['GMAIL_USERNAME'],
:password => ENV['GMAIL_PASSWORD']
}
and give it a try.
You can create instead a file mail.rb in config/environments/ or if you want to use a specific email account for each environment than you will need to write in each 'environments' file (production.rb; test.rb, development.rb) your ActionMailer::Base.smtp_settings { options .... }
P.S. I would suggest you to use mandrill/sendgrid etc instead video

Resources