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
Related
I am using devise, and scaffolded Textbook.
I like to implement my strategy.
When buyer clicks an #textbook.title -> Buyer can send an email to the #textbook's seller.
I have every model has column for 'user_email'
So, Whenever a seller create a #textbook, automatically current_user.email is saved into #textbook.user_email.
I just don't know how to grab the seller's user_email and send email.
I have following
Textbook model:
class Textbook < ActiveRecord::Base
belongs_to :user
validates :title, :presence => true
validates :subject, :presence => true
validates :price, :presence => true
validates :offer, :presence => false
validates :created_at, :presence => false
validates :user_email, :presence => true
validates :description, :presence => true
end
I am not sure this model syntax is right for subject and current_user.email
Contact model:
class Contact < MailForm::Base
attribute :name, :validate => true
attribute :current_user.email, :validate => /\A([\w\.%\+\-]+)#([\w\-]+\.)+([\w]{2,})\z/i
attribute :message, :validate => true
def headers
{
:subject => "I like to buy #{#textbook.id.title}",
:to => "#textbook.id.user_email",
:from => %(<#{email}>)
}
end
end
My detail question is this:
If a user clicks 'contact' when buyer was inside of a specific textbook ant it links the user to textbook#show. Below is the form when the user clicked 'contact'.
How can I make sure this below view access the correct textbook.id or textbook.title?
<h1> Contact to the Seller </h1>
<div>
<%=form_for #contact do |f|%>
<h3>Send email for: <%=#textbook.id.title%> </h3>
<%= f.label :message %><br>
<%= f.text_area :message, as: :text %><br>
<%=f.submit 'Send message', class: 'button' %>
<%end%>
</div>
Specially, I don't know how to handle grab attributes that is from different model inside different views.
Thank you in advance!
-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!
Update 1:
I have contact controller like this:
class ContactsController < ApplicationController
def new
#contact = Contact.new
end
def create
#contact = Contact.new(params[:contact])
##contact.request = request
if #contact.deliver
flash[:success] = "Email sent."
else
flash[:alert] = "Cannot send an email."
render :new
end
end
end
I just edited my 'class Contact < MailForm::Base'
class Contact < MailForm::Base
attribute :name, :validate => true
attribute :email, :validate => /\A([\w\.%\+\-]+)#([\w\-]+\.)+([\w]{2,})\z/i
attribute :message, :validate => true
def headers
{
:subject => "I like to buy #{textbook.title}",
:to => "#textbook.user_email",
:from => %(<#{current_user.email}>)
}
end
end
But I got error:
NameError in ContactsController#create
undefined local variable or method `textbook' for #<Contact:0x007fbac641be40>
Extracted source (around line #8):
def headers
{
:subject => "I like to buy #{textbook.title}",
:to => "#textbook.user_email",
:from => %(<#{current_user.email}>)
}
#zeiv I fixed textbook.title -> #textbook.title
I get error an another error.
NoMethodError in ContactsController#create
undefined method `title' for nil:NilClass
def headers
{
:subject => "I like to buy #{#textbook.title}",
:to => "#textbook.user_email",
:from => %(<#{current_user.email}>)
}
I have views/textbooks.html.erb:
<div class="container">
<p>
<h3><strong>Title:</strong>
<%= #textbook.title %></h3>
</p>
<p>
<strong>Subject:</strong>
<%= #textbook.subject %>
</p>
<p>
<strong>Price:</strong>
$<%= #textbook.price %>
</p>
<p>
<strong>Accept Offer:</strong>
<%if #textbook.offer == true%>
<%='Yes'%>
<%else%>
<%='No'%>
<%end%>
</p>
<p>
<strong>Description:</strong>
<pre><%= #textbook.description %></pre>
</p>
<p>
<strong>Image:</strong>
<pre><%= image_tag #textbook.thumbnail.url(:medium) %></pre>
</p>
<p>
<strong>Created on:</strong>
<%= #textbook.created_at.strftime("%d %b. %Y") %>
</p>
<p>
<%= link_to 'Contact', new_contact_path %>
</p>
<%if #textbook.user_email == current_user.email %>
<%= link_to 'Edit', edit_textbook_path(#textbook) %> |
<%= link_to 'Back to list', textbooks_path %>
<%else %>
<%= link_to 'Back to list', textbooks_path %>
<%end%>
And I have textbooks_controller:
class TextbooksController < ApplicationController
before_action :set_textbook, only: [:show, :edit, :update, :destroy]
#before_action :set_textbook, only: [:show]
#before_action :authorize_resource!, except: [:new, :index, :show]
# GET /textbooks
# GET /textbooks.json
def index
##textbooks = Textbook.all
#textbooks = Textbook.all.order(created_at: :desc).paginate(page: params[:page], per_page: 10)
##textbooks = Textbook.paginate(:page => params[:page], :per_page => 10)
end
# GET /textbooks/1
# GET /textbooks/1.json
def show
end
I have config/routes:
resources :textbooks
resources :contacts, only: [:new, :create]
devise_for :users
When I rake routes at this moment 4/17 5:05pm
new_textbook GET /textbooks/new(.:format) textbooks#new
edit_textbook GET /textbooks/:id/edit(.:format) textbooks#edit
textbook GET /textbooks/:id(.:format) textbooks#show
PATCH /textbooks/:id(.:format) textbooks#update
PUT /textbooks/:id(.:format) textbooks#update
DELETE /textbooks/:id(.:format) textbooks#destroy
contacts POST /contacts(.:format) contacts#create
new_contact GET /contacts/new(.:format) contacts#new
UPDATE 2 -!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!#-!
below is after 04/17/2016 11:00pm
#zeiv I did what you told me.
But still I get error when I click 'contact' button in views/textbooks/show.html.erb
#views/textbooks/show.html.erb
<p>
<%= link_to 'Contact', new_contact_textbook_path %>
</p>
my routes.rb has now:
Rails.application.routes.draw do
resources :textbooks do
member do
get 'contact', to: 'textbooks#new_contact', as: 'new_contact'
post 'contact', to: 'textbooks#send_contact', as: 'send_contact'
end
end
rake routes has now:
Prefix Verb URI Pattern Controller#Action
new_contact_textbook GET /textbooks/:id/contact(.:format) textbooks#new_contact
send_contact_textbook POST /textbooks/:id/contact(.:format) textbooks#send_contact
textbooks GET /textbooks(.:format) textbooks#index
POST /textbooks(.:format) textbooks#create
new_textbook GET /textbooks/new(.:format) textbooks#new
edit_textbook GET /textbooks/:id/edit(.:format) textbooks#edit
textbook GET /textbooks/:id(.:format) textbooks#show
PATCH /textbooks/:id(.:format) textbooks#update
PUT /textbooks/:id(.:format) textbooks#update
DELETE /textbooks/:id(.:format) textbooks#destroy
The error I get is this:
NoMethodError in Textbooks#new_contact
undefined method `id' for nil:NilClass
Extracted source (around line #4):
<div>
Texbook id is: <%= #textbook.id %>
</div>
I am running heroku local the error shows:
10:56:13 PM web.1 | Rendered textbooks/new_contact.html.erb within layouts/application (2.0ms)
10:56:13 PM web.1 | Completed 500 Internal Server Error in 7ms (ActiveRecord: 0.1ms)
10:56:13 PM web.1 | ActionView::Template::Error (undefined method `id' for nil:NilClass):
10:56:13 PM web.1 | 1: <h1> contact seller! - working? </h1>
10:56:13 PM web.1 | 2:
10:56:13 PM web.1 | 3: <div>
10:56:13 PM web.1 | 4: Texbook id is: <%= #textbook.id %>
10:56:13 PM web.1 | 5: </div>
Basically what you need to do is to write your mailers and controllers in such a way that all the information you want is passed to the mailer. So if you want an instance of your Textbook model to be passed to the mailer, you will need to do so from the controller in which you send your email. You might event want to nest your contact controller routes within your textbook routes to help you. Alternatively, rather than having an entire controller for Contact, just have a contact action within your textbook controller.
# route.rb
...
resources :textbooks do
member do
get "contact", to: "textbooks#new_contact", as: "new_contact"
post "contact", to: "textbooks#send_contact", as: "send_contact"
end
end
That will give you routes like /textbook/24/contact. member do means that the routes are for individual instances of your model rather than the whole collection, so you will need to specify which textbook you are referring to when calling their helpers: new_contact_textbook_path(#textbook.id).
So in your Textbook controller, you would do this:
# textbooks_controller.rb
before_action :set_textbook, only: [:show, :edit, :update, :destroy, :new_contact, :send_contact]
...
def new_contact
# We are NOT doing Contact.new here
# Only put logic here that you need to display the form
end
def send_contact
message = params[:message]
if Contact.send_contact(#textbook, current_user, message).deliver
flash[:success] = "Email sent."
redirect_to #textbook
else
flash[:alert] = "There was a problem sending the email."
render :new_contact
end
end
Then put your new_contact.html.erb file in with your other Textbook views.
<h1> Contact to the Seller </h1>
<div>
<%= form_tag send_contact_textbook_path(#textbook.id) do %>
<h3>Send email for: <%=#textbook.title%> </h3>
<%= label_tag :message, "Type your message:" %><br>
<%= text_area_tag :message %><br>
<%= submit_tag 'Send message', class: 'button' %>
<%end%>
</div>
Notice that I'm using form_tag instead of form_for because we don't have a Contact object to pass it. (That is, Contact isn't a model. It's a mailer.)
Your mailer would then look something like this:
class Contact < ApplicationMailer
def send_contact(textbook, current_user, message)
#textbook = textbook
#current_user = current_user
#message = message
mail(
from: "#{#current_user.name} <#{#current_user.email}>",
to: #textbook.user.email,
subject: "I would like to buy #{#textbook.title}",
reply_to: #current_user.email,
)
end
end
And finally, put the template/view for you mailer in /app/views/contact/send_contact.html.erb:
<!DOCTYPE html>
<html>
<head>
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
</head>
<body>
<h1><%= #current_user.name %> is wondering about <%= #textbook.title %>:</h1>
<p><%= #message %></p>
</body>
</html>
And that should do it! Although you may have to adjust some things to suit your needs. Also see these links for more examples:
Contact Form Mailer in Rails 4
https://sendgrid.com/docs/Integrate/Frameworks/rubyonrails.html
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'!
I'm trying to build a mailer into my rails app, which allows visitors to submit feedback through a form which is sent to a third party email address. This object is defined as a 'comment'.
As part of the app, a user must be authenticated in order to access this form and send me a 'comment', and as such I'm trying to pass the attributes from the User model to the comment form and mailer.
I'm getting the following error, code to follow:
undefined method `user_full_name' for nil:NilClass
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
</head>
<body>
Name: <%= #comment.user_full_name %>
Email: <%= #comment.user_email %>
routes.rb
Sampleapp::Application.routes.draw do
devise_for :users, :controllers => { :registrations => "registrations" }
devise_scope :user do
get 'register', to: 'devise/registrations#new'
get 'login', to: 'devise/sessions#new', as: :login
get 'logout', to: 'devise/sessions#destroy', as: :logout
end
resources :users do
member do
get 'edit_profile'
end
resources :messages, only: [:new, :create]
end
resources :messages do
get :sent, action: "outbox", type: "sent", on: :collection
end
resources :comments, 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
CommentsController.rb
class CommentsController < ApplicationController
def new
#comment = Comment.new
end
def create
#comment = Comment.new comment_params
if #comment.valid?
CommentsMailer.new_comment(#user).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
private
def comment_params
params.require(:comment).permit(:subject, :feedback)
end
end
comment.rb
class Comment < ActiveRecord::Base
belongs_to :user, inverse_of: :comments
attr_accessible :subject, :feedback
validates :subject, presence: true
validates :feedback, presence: true
end
new.html.erb
<div class="comment">
<div class="container">
<%= form_for #comment do |f| %>
<%= f.hidden_field :user_full_name, value: current_user.full_name %>
<%= f.hidden_field :user_email, value: current_user.email %>
<%= f.label :subject %>
<%= f.text_field :subject %>
<%= f.label :feedback %>
<%= f.text_area :feedback %>
<%= f.submit "Send", class: "btn btn-inverse" %>
<% end %>
</div>
</div>
comments.mailer.rb
class CommentsMailer < ActionMailer::Base
default to: "myemail#gmail.com"
default from: "#comment.user.email"
def new_comment(user)
#user = user
mail(subject: '#comment.subject')
end
end
new_comment.html.erb
<!DOCTYPE html>
<html>
<head>
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
</head>
<body>
Name: <%= #comment.user.full_name %>
Email: <%= #comment.user.email %>
Subject: <%= #comment.subject %>
Feedback: <%= #comment.body %>
</body>
</html>
You are not passing #comment object to CommentsMailer and trying to access it there.
Instead of passing User object (#user) to CommentsMailer in create action CommentsMailer.new_comment(#user).deliver. Try pass #comment object.
Try make following changes in your create action :
def create
#comment = Comment.new comment_params
if #comment.valid?
CommentsMailer.new_comment(#comment).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
comments.mailer.rb
class CommentsMailer < ActionMailer::Base
default to: "myemail#gmail.com"
default from: "#comment.user.email"
def new_comment(comment)
#comment = comment
#user = #comment.user
mail(subject: '#comment.subject')
end
end
i want to save a input "email" from static pages to the database. Right now, i have a emails model with a :address field, but i can't save the value when click the submit input.
Layout with form
# layout/website.html.erb
<div>
<%= form_for #email, :url => newsletter_path, :method => :post do |email| %>
<%= email.text_field :address %>
<%= email.submit "Go" %>
<% end %>
</div>
Pages Controller
# controllers/pages_controller.rb
def home
newsletter
end
def newsletter
#email = Email.new(params[:address])
if #email.valid?
redirect_to(request.referer, :notice => "The suscription has been sent successfully.")
else
redirect_to(request.referer, :alert => "Please add an valid email address.")
end
end
Routes
# routes.rb from static pages
get "/home" => 'pages#home', :as => :home
get "/pricing" => 'pages#pricing', :as => :pricing
get "/logo-gallery" => 'pages#logo_gallery', :as => :logo_gallery
get "/blog" => 'pages#blog', :as => :blog
get "/blog/:id" => 'pages#post', :as => :post
get "/contact" => 'pages#contact', :as => :contact
match '/contact' => 'pages#create', :as => :contact, :via => :post
get "/faqs-and-terms" => 'pages#faqs_and_terms', :as => :faqs_and_terms
match "/newsletter" => 'pages#newsletter', :as => :newsletter, :via => :post
Model
# models/email.rb
class Email < ActiveRecord::Base
attr_accessible :address
validates :address, :format => { :with => %r{.+#.+\..+} }, :allow_blank => true
end
With this code, when visit /home right now i'm received:
ActionController::ActionControllerError in PagesController#home
Cannot redirect to nil!
I hope you can help me, what can i do to fix this and get a better code. Thank you.
You should use Email.create(params[:email]) instead of Email.new(params[:address]) to persist records in DB. Also, in your view you code add hidden_field
<%= email.text_field :address %>
<%= hidden_field_tag :referer, :value => request.path %>
<%= email.submit "Go" %>
And then in controller:
redirect_to params[:referer]
UPD
Also, please notice that you should use params[:email] in your controller, not params[:address]. You can invoke raise params.inspect in your controller to inspect params sent by form.
In newsletter action email record is only initialized but not saved. And you have no need to call newsletter method inside home action every time. Just update your code like this.
Pages Controller
# controllers/pages_controller.rb
.....
# no need to call newsletter action here
def home
end
def newsletter
#email = Email.new(params[:email])
if #email.save
redirect_to((request.referer || '/'), :notice => "The suscription has been sent successfully.")
else
redirect_to((request.referer || '/'), :alert => "Please add an valid email address.")
end
end
Layout with form
As #email is not defined in controller, so you should initialize an Email object in form.
# layout/website.html.erb
<div>
<%= form_for Email.new, :url => newsletter_path, :method => :post do |email| %>
<%= email.text_field :address %>
<%= email.submit "Go" %>
<% end %>
</div>
I hope that it should work.
Right now I'm building a project management app in rails, here is some background info:
Right now i have 2 models, one is User and the other one is Client. Clients and Users have a one-to-one relationship (client -> has_one and user -> belongs_to which means that the foreign key it's in the users table)
So what I'm trying to do it's once you add a client you can actually add credentials (add an user) to that client, in order to do so all the clients are being displayed with a link next to that client's name meaning that you can actually create credentials for that client.
So in order to do that I'm using a helper the link to helper like this.
<%= link_to "Credentials",
{:controller => 'user', :action => 'new', :client_id => client.id} %>
Meaning that he url will be constructed like this:
http://localhost:3000/clients/2/user/new
By creating the user for the client with he ID of 2.
And then capturing the info into the controller like this:
#user = User.new(:client_id => params[:client_id])
EDIT: This is what i currently have in my View/Controller and Routes
I keep getting this error: No route matches "/clients//user" with {:method=>:post}
Routes
ActionController::Routing::Routes.draw do |map|
map.resources :users
map.resources :clients, :has_one => :user
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end
Controller
class UsersController < ApplicationController
before_filter :load_client
def new
#user = User.new
#client = Client.new
end
def load_client
#client = Client.find(params[:client_id])
end
def create
#user = User.new(params[:user])
#user.client_id = #client.id
if #user.save
flash[:notice] = "Credentials created"
render :new
else
flash[:error] = "Credentials created failed"
render :new
end
end
View
<% form_for #user, :url => client_user_url(#client) do |f| %>
<p>
<%= f.label :login, "Username" %>
<%= f.text_field :login %>
</p>
<p>
<%= f.label :password, "Password" %>
<%= f.password_field :password %>
</p>
<p>
<%= f.label :password_confirmation, "Password Confirmation" %>
<%= f.password_field :password_confirmation %>
</p>
<%= f.submit "Create", :disable_with => 'Please Wait...' %>
<% end %>
Your form tag is wrong, you are posting to /users without the :client_id.
Try this:
<% form_for #user, :url => {:controller => 'users', :action => 'new', :client_id => #client.id} do |f| >
Alternatively, you could use nested resources:
config/routes.rb
map.resources :clients do |clients|
clients.resources :users
end
Controller
class UsersController < ApplicationController
before_filter :load_client
def load_client
#client = Client.find(params[:client_id])
end
# Your stuff here
end
View
<% form_for [#client, #user] do |f| %>
I solved this by using nested attributes, by including the user model, when creating the client. And it works flawlessly.
In case any of you guys need more info here's the two screencasts that helped me come up with as solution:
http://railscasts.com/episodes/196-nested-model-form-part-1
http://railscasts.com/episodes/196-nested-model-form-part-2