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.
Related
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
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 watched the railscast for building your own user authentication. I'm getting this undefined method error. Where should this method be defined, the controller, model, or neither?
Showing /opt/csdashboard/app/views/dashboard_users/new.html.erb where line #3 raised:
undefined method `dashboard_users_index_path' for #<#<Class:0x007f8480988fa8>:0x007f84809880f8>
Extracted source (around line #3):
1: <h1>Sing Up</h1>
2:
3: <%= form_for #dashboard_user do |f|%>
4: <% if #dashboard_user.errors.any? %>
5: <div class="alert-error">
6: <h2>Form is invalid</h2>
Here is my dashboard_user/new.html.erb file
<h1>Sing Up</h1>
<%= form_for #dashboard_user do |f|%>
<% if #dashboard_user.errors.any? %>
<div class="alert-error">
<h2>Form is invalid</h2>
<ul>
<% for message in #dashboard_user.full_message %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :email %><br />
<%= f.text_field :email %>
</p>
<p>
<%= f.label :password %><br />
<%= f.password_filed :password %>
</p>
<p>
<%= f.label :password_confirmation %><br />
<%= f.password_filed :password_confirmation %>
</p>
<p class='ui-button'><%= f.submit %></p>
<% end %>
Here is the model:
class DashboardUsers < ActiveRecord::Base
attr_accessible :email, :password, :password_hash, :password_salt
attr_accessor :password
before_save :encrypt_password
validates_confirmation_of :password
validates_presence_of :password, :on => :create
validates_presence_of :email
validates_uniqueness_of :email
def self.authenticate(email, password)
dashboard_user = find_by_email(email)
if dashboard_user && dashboard_user.password_hash == BCrypt::Engine.hash_secret(password, dashboard_user.password_salt)
dashboard_user
else
nil?
end
end
def encrypt_password
if password.present?
self.password_salt = BCrypt::Engine.generate_salt
self.password_hash =BCrypt::Engine.hash_secret(password, password_salt)
end
end
end
Here is the controller:
class DashboardUsersController < ApplicationController
def new
#dashboard_user = DashboardUsers.new
end
def create
#dashboard_user = DashboardUsers.new(params[:user])
if #dashboard_user.save
redirect_to index, :notice => 'Signed up!'
else
render 'new'
end
end
end
Update with routes.rb
Speaking of routes, what should I do with get '/' => 'csdashboard#index'. This was the first route before I added user auth.
Csdashboard::Application.routes.draw do
resources :dashboard_users
resources :sessions
resources :csdashboard
get '/log_out' => 'sessions#destroy', :as => 'log_out'
get '/log_in' => 'sessions#new', :as => 'log_in'
get '/sign_up' => 'dashboard_users#new', :as => 'sign_up'
root :to => 'dashboard_users#new'
get '/' => 'csdashboard#index'
get '/img/:name.:ext', :to => redirect('/assets/%{name}.%{ext}')
match '/404' => 'errors#not_found'
match '/422' => 'errors#server_error'
match '/500' => 'errors#server_error'
end
You need the route with name dashboard_users_index and method post to be defined in routes.rb.
Can you show us your routes.rb file?
This is a pretty basic question, but I'm having difficulty incorporating it in to my application. I've looked at other similar questions on SO, but they all are using the contact page as a separate page.
I have a front-end of a Rails app that is just a small public facing site using stellar.js for parallax scrolling.
At the last part of the page, I would like to have a "Contact Us" form, but I'm getting a
NoMethodError in Welcome#index undefined method `model_name' for NilClass:Class
Here are the related files:
routes.rb
TestApp::Application.routes.draw do
get "welcome/index"
root :to => 'welcome#index'
match 'contact' => 'contact#new', :as => 'contact', :via => :get
match 'contact' => 'contact#create', :as => 'contact', :via => :post
app/views/welcome/index.html.erb
<%= render "contact" %>
The partial for the contact section of the page app/views/welcome/_contact.html.erb
<%= form_for #message, :url => contact_path do |form| %>
<fieldset class="fields">
<div class="field">
<%= form.label :name %>
<%= form.text_field :name %>
</div>
<div class="field">
<%= form.label :email %>
<%= form.text_field :email %>
</div>
<div class="field">
<%= form.label :subject %>
<%= form.text_field :subject %>
</div>
<div class="field">
<%= form.label :body %>
<%= form.text_area :body %>
</div>
</fieldset>
<fieldset class="actions">
<%= form.submit "Send" %>
</fieldset>
<% end %>
app/controllers/contact_controller.rb
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
message.rb
class Message
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
The question is what do I need to do to make this form to function correctly in the welcome#index view?
You need to have #message = Message.new defined in every action that needs #message to be present.
So that means you need this in WelcomeController:
def index
#message = Message.new
end
A shortcut is to just add it to the top of the partial in case it's not set:
<% #message ||= Message.new %>
(But you need to decide if mixing in calls to the model within your views is your style. Some devs don't have a problem with this, and some do.)
You can change following things:
In routes:
Remove:
match 'contact' => 'contact#new', :as => 'contact', :via => :get
match 'contact' => 'contact#create', :as => 'contact', :via => :post
Add:
resources :contact # It will add 7 default REST routes and standard practice model name should be plural if you created your model with singular then keep it singular
In _contact.html.erb partial form path needs to be new_contact_path
<%= form_for Message.new, :url => contact_path do |form| %>
class Message should inherit ActiveRecord::Base
class Message < ActiveRecord::Base
end
In create action else part should be:
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 :template => "welcome/index"
end
I have a User model and a Company model linked like this:
class User < ActiveRecord::Base
belongs_to :company
accepts_nested_attributes_for :company
end
class Company < ActiveRecord::Base
has_many :users
end
On the sign in page, I want the user to set up both his info (mail, password) and his company info (several fields). So my form looks like this:
<%= simple_form_for #user, :html => { :class => 'form-horizontal' } do |f| %>
<%= f.input :email, :required => true, :placeholder => "user#domain.com" %>
<%= f.input :password, :required => true %>
<%= f.input :password_confirmation, :required => true %>
<h2>Company info</h2>
<%= simple_fields_for :company, :html => { :class => 'form-horizontal' } do |fa| %>
<%= fa.input :name %>
<%= fa.input :url %>
<%= fa.input :description, :as => :text, :input_html => { :cols => 60, :rows => 3 } %>
<%= fa.input :logo %>
<%= fa.input :industry %>
<%= fa.input :headquarters %>
<% end %>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
root_url, :class => 'btn' %>
</div>
<% end %>
My user model has a company_id:integer field. So logically, when I sign in the user, the first thing to do is to create the Company before the User and then give to the user creation model the appropriate company_id. So I wrote this:
class UsersController < ApplicationController
before_create :create_company
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to root_url, :notice => "Registration successful."
else
render :action => 'new'
end
end
private
def create_company
#company = Company.new(params[:company])
if #company.save
self.company_id = #company.id
else
render :action => 'new'
end
end
end
Problem is: when accessing /users/new I get this error:
undefined method `before_create' for UsersController:Class
What's going wrong? I checked, before_create has not been deprecated, I'm in Rails 3.2.8. This is probably something stupid with my create_company method but I can't figure why...
Thanks a lot for helping!
before_create is a hook method belonging to ActiveRecord
before_filter is a hook method belonging to Controller.
so I suggest you to re-build your code after you make clear which is which. ^_^