I'm trying to use actionmailer to notify me when a new comment has been posted but I keep getting the error:
uninitialized constant CommentsController::CommentMailer
The comment is added to my database and can be viewed. I am also using devise and it's email functions are working fine.
My comment mailer:
class CommentMailer < ActionMailer::Base
def newcomment(comment)
mail(:to => "admin#example.com", :subject => "New Comment")
end
end
and my controller section:
def create
#comment = Comment.new(params[:comment])
#comment.user_id = current_user.id
respond_to do |format|
if #comment.save
CommentMailer.newcomment(#comment).deliver
format.html { redirect_to #comment, notice: 'Comment was successfully created!' }
format.json { render json: #comment, status: :created, location: #comment }
else
format.html { render action: "new" }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
This can also happen if you name your mailer file wrong. UserMailer.rb will break whereas user_mailer.rb is what is expected.
OK my bad, I had to restart my rails application after I added the mailer. It is working fine now
Related
I am using this 3rd party controller:
class LibController
def update
# 29 lines of code
respond_with resource
end
end
I want to do something other than the respond_with at the end. But I don't want to just copy/paste all 29 lines into MyController.update. Unfortunately I can't figure out a way to render or redirect anywhere else:
class MyController < LibController
def update
super
redirect_to somewhere_else
end
end
I get a DoubleRenderError: Render and/or redirect were called multiple times in this action. I assume this is because respond_with calls render immediately. Is there a way to block/prevent that?
Thanks!
I think you are doing a twice redirection.
Try to remove one redirection on your update method.
Check sample code below that shows equivalent response when using respond_with.
def create
#user = User.new(params[:user])
flash[:notice] = 'User was successfully created.' if #user.save
respond_with(#user)
end
Which is exactly the same as:
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
flash[:notice] = 'User was successfully created.'
format.html { redirect_to(#user) }
format.xml { render xml: #user, status: :created, location: #user }
else
format.html { render action: "new" }
format.xml { render xml: #user.errors, status: :unprocessable_entity }
end
end
end
(I've broken out the 2nd question that originally was part of this post into a separate post)
I am creating a product landing page with Rails in which users can enter their email address to be notified when the product launches. (Yes, there are services/gems etc that could do this for me, but I am new to programming and want to build it myself to learn rails.)
On submit of the form, if there are errors, the app currently redirects to '/invites' I would like to instead display error messages on the same page/URL as the original form? (In my case, the form is located at root while the error messages are displaying at '/invites')
I have read the Rails Guide on Routes and numerous stackoverflow posts on handling form errors nothing I've found seems to answer the question I have.
Update: Based on the reply from #rovermicrover I would like to clarify that, while I'm open to an Ajax solution, I'm fine with a page refresh that displays the error message. (I was not able to get the recommendation by #rovermicrover to function as desired - see my response to that solution below for more details.)
What I did:
Invite model:
class Invite < ActiveRecord::Base
attr_accessible :email
validates :email, :presence => {:message => "Please enter an email address."}
end
My routes file:
SuggestionBoxApp::Application.routes.draw do
root to: 'invites#new'
resources :invites
end
This is what I have in the Invites controller (I've only included the actions I'm referencing: new, create, show - it's basically the default of what Rails might generate):
class InvitesController < ApplicationController
def show
#invite = Invite.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #invite }
end
end
def new
#invite = Invite.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #invite }
end
end
def create
#invite = Invite.new(params[:invite])
respond_to do |format|
if #invite.save
format.html { redirect_to #invite }
format.json { render json: #invite, status: :created, location: #invite }
else
format.html { render action: "new" }
format.json { render json: #invite.errors, status: :unprocessable_entity }
end
end
end
end
Please let me know if there is any additional info I can provide in helping to answer this question. Thanks!
Make the form 'remote'
form_for #invite, :remote => true
....
Then in the controller
def create
#invite = Invite.new(params[:invite])
respond_to do |format|
if #invite.save
format.html { redirect_to #invite }
format.js { render :action => 'create_suc'}
else
format.html { render action: "new" }
format.js { render :action => 'create_fail' }
end
end
end
/invites/create_suc.js.erb
$('#errors').remove()
$('#new_invite').prepend("<div class='Thanks'>Thanks for signing up</div>")
$('#new_invite').hide("")
/invites/create_fail.js.erb
$('#new_invite').html('<%= escape_javascript render("form", :invite => #invite) %>');
Forms is a partial with your.... form in it, and also the handling of all errors on #invite.
There is a way to do this without resorting the making the form submit "remote", from a pure Ruby on Rails perspective. However, you can do this only if the browser has enabled cookies.
The idea is to save the form data in the session information in case of an error.
Just remember to delete the session data in case of success.
def new
#invite = Invite.new(session[:invite])
respond_to do |format|
format.html # new.html.erb
format.json { render json: #invite }
end
end
def create
#invite = Invite.new(params[:invite])
respond_to do |format|
if #invite.save
session.delete(:invite)
format.html { redirect_to #invite }
format.json { render json: #invite, status: :created, location: #invite }
else
session[:invite] = params[:invite]
format.html { render action: "new" }
format.json { render json: #invite.errors, status: :unprocessable_entity }
end
end
end
I am using the gem 'foreigner' and setup comment for my app and everything works. However, I would also like to notify my users whenever a comment is created. I've got two users, customers and developers. Customers can post comments and Developers can post comments.
How would I setup my comments_controller.rb file to figure out if its a customer or developer posting the comment and then send email with the right template.
So far I've tried the following with no work;
def create
#comment = Comment.new(params[:comment])
respond_to do |format|
if #comment.save
if current_user.is_developer?
Notifier.developer_notify(#developer).deliver
elsif current_user.is_customer?
Notifier.customer_notify(#customer).deliver
end
format.html { redirect_to :back, notice: 'Comment was successfully created.' }
# format.json { render json: #comment, status: :created, location: #comment }
else
format.html { render action: "new" }
# format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
"developer_notify" and "customer_notify" being the class defined in my Notifier mailer.
My "Notifier" mailer looks like this so far;
def developer_notify(joblisting)
#joblisting = joblisting
mail(:to => #joblisting.current_user.email, :subject => "There's a new comment.")
end
#Joblisting is the job that is referenced to as each Joblisting has its own comments from customers and developers.
Doing the above, gives me an error - undefined method 'current_user' for nil:NilClass
So I'm guessing it's not finding the Joblisting ID nor is it finding the customers email address, then if the customer posted a comment for that same job, it would send email to the developer with notification of a new comment posted.
Any suggestions?
you have passing joblisting from your controller:
def create
#comment = Comment.new(params[:comment])
#you have define here joblisting for example:
joblisting = JobListing.first #adapt the query to your needs
respond_to do |format|
if #comment.save
if current_user.is_developer?
#here add joblisting as argument after #developer
Notifier.developer_notify(#developer, joblisting).deliver
elsif current_user.is_customer?
#here add joblisting as argument after #developer
Notifier.customer_notify(#customerm, joblisting).deliver
end
format.html { redirect_to :back, notice: 'Comment was successfully created.' }
# format.json { render json: #comment, status: :created, location: #comment }
else
format.html { render action: "new" }
# format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
on notifier mailer
def developer_notify(#developer, joblisting)
#joblisting = joblisting
mail(:to => #joblisting.current_user.email, :subject => "There's a new comment.")
end
Regards!
I'm using Ryan Bates' Rails Cast on Wicked Wizard Forms to create a multi-step form. I don't have a current_user method defined (not using an authentication gem) - so, I'm trying to pass the user.id parameter during the redirect_to - unfortunately, I can't seem to get it to work. Any help is appreciated!
My user controller create method
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to controller: 'user_steps', id: 'user.id' }
#format.html { redirect_to #user, notice: 'User was successfully created.' }#
format.json { render json: #user, status: :created, location: #user }
else
format.html { render action: "new" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
The user_steps controller that to which I am redirecting:
class UserStepsController < ApplicationController
include Wicked::Wizard
steps :gender, :items, :brands, :final
def show
render_wizard
end
end
You should pass it through as a param, ideally, which the redirect_to method will do for you if you use a proper route path.
Example:
redirect_to(user_steps_path(#user))
In your case, if you don't have a named route, you might do this:
redirect_to(controller: 'user_steps', id: #user.to_param)
In URLs it's advisable to use the to_param method. id is used for database queries.
What you're passing in is literally 'user.id' as a parameter. It will not be evaluated.
What's the difference between respond_to and respond_with ?
What do they do?
Can anyone post example with the screenshot of output?
Thanks.
There is a pretty complete answer here. Essentially respond_with does the same thing as respond_to but makes your code a bit cleaner. It is only available in rails 3 I think
Both respond_to and respond_with does the same work, but respond_with tends to make code a bit simple,
Here in this example,
def create
#task = Task.new(task_params)
respond_to do |format|
if #task.save
format.html { redirect_to #task, notice: 'Task was successfully created.' }
format.json { render :show, status: :created, location: #task }
else
format.html { render :new }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
The same code using respond_with ,
def create
#task = Task.new(task_params)
flash[:notice] = "Task was successfully created." if #task.save
respond_with(#task)
end
also you need to mention the formats in your controller as:
respond_to :html,:json,:xml
When we pass #taskto respond_with, it will actually check if the object is valid? first. If the object is not valid, then it will call render :new when in a create or render :edit when in an update.
If the object is valid, it will automatically redirect to the show action for that object.
Maybe you would rather redirect to the index after successful creation. You can override the redirect by adding the :location option to respond_with:
def create
#task = Task.new(task_params)
flash[:notice] = #task.save ? "Your task was created." : "Task failed to save."
respond_with #task, location: task_path
end
For more information visit this Blog