Rails - Form_for error for undefined local variable? - ruby-on-rails

I've been trying to setup a contact form but I keep getting errors and I just can't figure out what I'm doing wrong. The latest error I'm getting is:
NameError in Contacts#new
Showing .../app/views/contacts/new.html.erb where line #2 raised:
undefined local variable or method `contact' for #<#<Class:0x007fa2933ca1f8>:0x007fa29a4df460>
Did you mean? #contact
concat
Extracted source (around line #2):
1
2
3
4
5
6
<h1>Contact us</h1>
<%= form_for(contact) do |f| %>
<div class="field entry_box">
<%= f.label :name %>
<%= f.text_field :name, class: "form-control entry_field" %>
</div>
My ContactsController
class ContactsController < ApplicationController
def new
#contact = Contact.new
end
def create
#contact = Contact.new(contact_params)
if #contact.save
redirect_to contacts_path, notice: "Thanks for contacting us!"
else
render :new
end
end
private
def contact_params
params.require(:contact).permit(:name, :email, :message)
end
end
Model
class Contact < ApplicationRecord
end
Routes (relevant parts)
resources :contacts, only: [:new, :create]
get "contact" =>'contacts#new'
post "contact" =>'contacts#create'
View (new.html.erb)
<h1>Contact us</h1>
<%= form_for(contact) do |f| %>
<div class="field entry_box">
<%= f.label :name %>
<%= f.text_field :name, class: "form-control entry_field" %>
</div>
<div class="field entry_box">
<%= f.label :email %>
<%= f.number_field :email, class: "form-control entry_field" %>
</div>
<div class="field entry_box">
<%= f.label :message %>
<%= f.text_field :message, class: "form-control entry_field" %>
</div>
<div class="actions center space_big">
<%= f.submit "Submit", class: "btn btn-lg btn-success" %>
</div>
<% end %>
Thanks for any assistance!

Your controller defines an instance variable, #contact, but your view uses contact. There's a difference - make sure your form_for call uses the #contact variable that your controller defines.
You have:
<%= form_for(contact) do |f| %>
which you should change to
<%= form_for(#contact) do |f| %>
because of this line in your controller
#contact = Contact.new
In most errors, Rails will give you the source code and line number that caused the exception, and will then give you a hint - in this case, it says "did you mean #contact?"

The variable contact is undefined in new.html.erb. See the suggestion made by rails to use #contact?
The line
<%= form_for(contact) do |f| %>
should be
<%= form_for(#contact) do |f| %>
The instance variable #contact is passed on to the view from the new action of ContactsController.

You have to write instance variable in new form just write
<%= form_for(#contact) do |f| %>
<% end %>

Related

Contact name not showing name in DB

I'm a rookie, and looking to create a contact form, but when I check my submitted forms, it doesn't show the name. It just says name "" I'm using Ruby on Rails.
My html looks like;
Contact Us
<div class="col-md-4 col-md-offset-4">
<%= flash[:notice] %>
<div class="well">
<%= form_for #contact do |f| %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.text_field :name, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :comments %>
<%= f.text_area :comments, class: 'form-control' %>
</div>
<%= f.submit 'Submit', class: 'btn btn-default' %>
<% end %>
</div>
</div>
My controller code looks like;
class ContactsController < ApplicationController
def new
#contact = Contact.new
end
def create
#contact = Contact.new(contact_params)
if #contact.save
redirect_to new_contact_path, notice: "Message Sent."
else
redirect_to new_contact_path, notice: "Error Occured"
end
end
private
def contact_params
params.require(:contact).permit(:name, :email, :comments)
end
end
Probably your second text field is the problem, it's called :name twice...
change the second input and try it again
<%= f.text_field :name, class: 'form-control' %>
to
<%= f.text_field :email, class: 'form-control' %>

How can I redirect with submit button in rails?

I have this HTML:
<% provide(:contact, "active") %>
<% provide(:title, "Contacto | Recotiendame") %>
<div align="center">
<h1 id_"page_title">Contactanos!</h1>
<div class="skinny_wrapper wrapper_padding"
<%= form_for contact_path, url: #done do |f| %>
<%= f.label :Nombre %><br>
<%= f.text_field :Nombre, required: true %>
<br>
<%= f.label :Email %><br>
<%= f.email_field :Email, required: true %>
<br>
<%= f.label :Mensaje %><br>
<%= f.text_area :Mensaje, as: :text %>
<div class= "hidden">
<%= f.label :nickname %><br>
<%= f.text_field :nickname, hint: 'dejalo en blanco' %>
</div>
<br>
<%= f.submit 'Enviar Mensaje', class: "button" %>
</div>
<% end %>
</div>
with this controller:
class ContactController < ApplicationController
def new
#contact = Contact.new
end
def create
#contact = Contact.new(params[:contact])
#contact.request = request
if #contact.deliver
flash.now[:notice] = 'Gracias por su mensaje. Lo contactaremos luego!'
else
flash.now[:error] = 'No se pudo enviar el mensaje.'
render :new
end
end
end
The problem is that the submit button does nothing. How can I make it work to redirect me to create? I have seen lots of answers to this question but none works for me.
EDIT 1
When I did #done, it was only to try things.
If I had to guess, I think you've got your form_for fields wrong. Normally you'd have something like: form_for #contact and it'd Just Work, but if you wanted to override the default url, you'd pass a different url eg
form_for #contact, url: contacts_path`
(note the plural is important).
I don't know what #done is meant to be... but it probably shouldn't be there... and putting the contact_path has two incorrect things about it:
1) you shouldn't have a url at that point, but an object (in this case the object is the contact)
2) contact_path is for showing a single contact that has already been saved, for creating a new contact, you need contacts_path (the idea is that you're posting a new contact to the set of contacts).

How do i make one form for two related models?

I want to write data for 2 different models that are related to each other like this:
class Post < ActiveRecord::Base
has_many :roads
accepts_nested_attributes_for :roads, :allow_destroy => true
end
class Road < ActiveRecord::Base
belongs_to :post
end
Of course de roads table has a "post_id column". My form_for in the post view looks like this
<%= form_for #post do |f| %>
<div class="form-group">
<%= f.label :Tu_Nombre %>
<%= f.text_field :creador, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :año %> (Cuando fue tu experiencia?)
<%= f.text_field :año, class: "form-control" %>
</div>
<div class="form-group">
<%= fields_for :roads do |r| %>
<%= r.label :principio %> (desde?)
<%= r.text_field :principio, class: "form-control" %>
<%= r.label :final %> (hasta?)
<%= r.text_field :final, class: "form-control" %>
<% end %>
</div>
<div class="form-group">
<%= f.label :historia %> (Cuentanos la historia de tu viaje!)
<%= f.text_area :historia, class: "form-control", size: "50x15" %>
</div>
<div>
<%= f.submit class: "btn btn-success" %>
</div>
<% end %>
Finally my posts_controller create method
def create
#post = Post.new(post_params)
if #post.save
redirect_to #post, notice: 'Post was successfully created.'
else
render :new
end
end
with the private
def post_params
params.require(:post).permit(:historia, roads_attributes: [:pricipio, :final, :post_id])
end
The post is submitted and if i check the console all the atributes for post has been saved but the ones for road, has not. How can i use just one form two make records for these two models and that the post_id gets registered so i can relate the tables?
Thanks a lot!!
Update your posts_controller new method to include .build
def new
#post = Post.new
#post.roads.build
end
Please read the Nested Forms in Form Helpers chapter of Rails Guide. You could use fields_for to build the nested attributes form for your roads and permit nested attributes like the example. Below is an example from rails guide, you could try and figure it out yourself.
_form.html.erb
<%= form_for #person do |f| %>
Addresses:
<ul>
<%= f.fields_for :addresses do |addresses_form| %>
<li>
<%= addresses_form.label :kind %>
<%= addresses_form.text_field :kind %>
<%= addresses_form.label :street %>
<%= addresses_form.text_field :street %>
...
</li>
<% end %>
</ul>
<% end %>
permit nested attributes in people_controller.rb
def person_params
params.require(:person).permit(:name, addresses_attributes: [:id, :kind, :street])
end
Attach your fields_for to the parent form builder like so:
<%= f.fields_for :roads do |r| %>

Nested model doesn't update

I have two models: PointPage and PointPageClass, which belongs_to :point_page. When user create PointPage rails creates several (now there're 6 of them) PointPageClasses in database. I need to edit all of them on PointPage edit page. So, I'm using nested attributes in controller and fields_for in view.
point_page_form
<%= form_for #point_page, role: 'form' do |f| %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
</div>
... # some other PointPage fields
<% #point_page.point_page_classes.each do |class| %>
<%= f.fields_for :point_page_classes do |builder| %>
<div class="row">
<div class="col-lg-6">
<%= builder.text_field :distance_price, class: 'form-control' %>
</div>
<div class="col-lg-6">
<%= builder.text_field :show_price, class: 'form-control' %>
</div>
</div>
<% end %>
<% end %>
<%= f.submit 'Save', class: 'btn btn-default' %>
<% end %>
point_page_controller
def update
#point_page = PointPage.find(params[:id])
if #point_page.update_attributes(point_page_params)
respond_to do |format|
format.html { redirect_to new_point_path }
format.js
end
end
end
private
def point_page_params
params.require(:point_page).permit(:name, :url, :article,
point_page_classes_attributes: [:distance_price, :show_price])
end
So, I've added in point_page_controller PointPageClass attributes, but when I save the changes, it only saves changes for PointPage, but not for PointPageClass (distance_price and show_price).
Thanks for any help!
One of the problem could be not permitting the :id in the point_page_params.For the update to take place you need to permit the :id.
Try changing your point_page_params to like this
def point_page_params
params.require(:point_page).permit(:id,:name, :url, :article,point_page_classes_attributes: [:id,:distance_price, :show_price])
end

No method error in contact form for Rails 3

I'm putting a contact form together using the following tutorial: http://matharvard.ca/posts/2011/aug/22/contact-form-in-rails-3/
I've followed all the instructions, but for some reason I keep getting this error when I try to access the Contact page in my app:
NoMethodError in Contact#new
undefined method `[]' for nil:NilClass
Extracted source (around line #1):
1: <%= form_for #message, :url => contact_path do |form| %>
2: <fieldset class="fields">
3: <div class="field">
4: <%= form.label :name %>
What am I missing here?
new.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 %>
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
notifications_mailer.rb
class NotificationsMailer < ActionMailer::Base
default :from => "myemail#gmail.com"
default :to => "myemail#gmail.com"
def new_message(message)
#message = message
mail(:subject => "[myemail#gmail.com] #{message.subject}")
end
end
I had a similar problem with this tutorial. It was because I forgot to remove < ActiveRecord::Base from the Message class. I also forgot to change attr_accessible to attr_accessor. You may want to double check those two points.

Resources