Look at this error:
AnswersControllerTest#test_should_destroy_answer [/Users/pitosalas/mydev/questionanswer/test/controllers/answers_controller_test.rb:47]:
Expected response to be a redirect to <http://www.example.com/questions/525858932> but was a redirect to <http://www.example.com/questions.525858932>.
Expected "http://www.example.com/questions/525858932" to be === "http://www.example.com/questions.525858932".
Notice the URL
In the error message from the test the url has a . in an incorrect place. This is telling me something but I am not sure what.
http://www.example.com/questions.525858932
Here is the test:
test "should destroy answer" do
assert_no_difference("Question.count") do
delete question_answer_url(#question, #answer)
end
assert_redirected_to question_url(#question)
end
And the controller:
def destroy
#question = Question.find(params[:question_id])
#answer = Answer.find(params[:id])
respond_to do |format|
format.html do
if !#answer.comments.empty?
redirect_to questions_url(#question), notice: "First delete all the comments"
elsif #answer.destroy
redirect_to questions_url(#question), notice: "Answer was successfully destroyed."
else
redirect_to questions_url(#question), notice: "Answer could not be destroyed."
end
end
format.json { head :no_content }
end
end
Question
What does the dot in the url mean? I know there's a bug but,,,
Related
If I am the server and someone sends me a JSON request to destroy a model/record but the destroy request failed, what response should Igive them. I assume just send them back a no content will be bad because they will assume that the destroy is a success.
So my question is: What should I return? And why?
Also, is my code below following good convention? I don't know if it is okay to do a conditional statement in a destroy action, I also customised the error messages which seems to be not following convention:
def destroy
#book = Book.find(params[:id])
respond_to do |format|
if #book.destroy
format.html { redirect_to books_url, notice: "Book was successfully deleted." }
else
format.html do
error_messages = #book.errors.try(:messages)
error_messages = error_messages[:base].join('. ') + '.' if error_messages.present?
flash[:error] = "Book deletion failed. #{ error_messages }"
redirect_to books_url
end
end
format.json { head :no_content } # what should this be?
end
end
If I were you, I'd use :unprocessable_entity like this:
if #book.destroy
# ...
format.json { head :no_content }
else
# ...
format.json { head :unprocessable_entity }
end
I found this flow chart to be enlightening: i.stack.imgur.com/whhD1.png
My controller is
def destroy
#image.destroy
respond_to do |format|
format.html
format.json { render json: 'success' }
end
end
I want that request from html then it redirect to :back like
flash[:notice] = "Image Successfully deleted"
redirect_to :back
it works fine when I can't deal with json. I want to combine both of them so they send response accordingly to html or ajax request
You can just put it inside the respond_to block for the html format
def destroy
#image.destroy
respond_to do |format|
format.html do
flash[:notice] = "Image Successfully deleted"
redirect_to :back
end
format.json do
render json: 'success'
end
end
end
You can put multiple lines into a block.
respond_to do |format|
format.html do
flash[:notice] = "Image Successfully deleted"
redirect_to :back
end
format.json { render json: 'success' }
end
The idea of this test is to handle the event a record is not found. There for a destroy action should not take place and yet it is. I've chopped and changed it around, nut essentially the test reads right, so there must be a problem in my code.
RSpec.describe Admin::EntriesController, :type => :controller do
setup_factories
let(:model){ Photo }
let(:instance){photo}
let(:no_instances){no_photos}
let(:some_instances){some_photos}
let(:params_full_instance){params_full_photo}
let(:params_new_instance){params_new_photo}
describe "delete destroy" do
context "where the record is found" do
before do
allow(model).to receive(:where).and_return(some_instances)
allow(some_instances).to receive(:first).and_return(instance)
end
context "where the record is destroyed" do
before do
allow(instance).to receive(:destroy).and_return(true)
delete :destroy, params_id
end
sets_flash(:notice)
redirects_to('/admin/entries/rejected')
end
context "where the record is not destroyed" do
before do
allow(instance).to receive(:destroy).and_return(false)
delete :destroy, params_id
end
sets_flash(:error)
redirects_to('/admin/entries/rejected')
end
end
context "where the record is not found" do
before do
allow(model).to receive(:where).and_return(no_instances)
delete :destroy, params_id
end
sets_flash(:error)
redirects_to('/admin/entries/rejected')
end
CONTROLLER
before_action :get_entry_id, only: [:destroy, :toggle_approve_field, :toggle_reject_field]
def destroy
if #entry.nil?
flash[:error] = "object is not not found"
end
if #entry.destroy
flash[:notice] = 'blah'
respond_to do |format|
format.html { redirect_to rejected_admin_entries_path }
format.json { head :no_content }
format.js
end
else
flash[:error] = 'There was a problem fetching the record'
redirect_to rejected_admin_entries_path
end
end
def get_entry_id
if #entry.nil?
flash[:error] = "object is not not found"
end
#entry = Photo.where(id: params[:id]).first
end
I probably need a fresh pair of eyes on it. And a nice explanation as to what I am getting wrong ;)
UPDATE: expected behaviour, is, when a destroy action is made, and the record is not found, i expect to see a flash error and to be redirected.
UPDATE 2: Implemented guys code below, still receiving error
1) Admin::EntriesController for authenticated users delete destroy where the record is not found should set flash error
Failure/Error: expect(flash[method]).to_not be_nil
expected: not nil
got: nil
# -e:1:in `<main>'
2) Admin::EntriesController for authenticated users delete destroy where the record is not found should redirect to /admin/entries/rejected
Failure/Error: expect(response).to redirect_to(path)
Expected response to be a <redirect>, but was <200>
Thanks
Rico
Your problem is you are still trying #entry.destroy even if it is still nil.
def destroy
if #entry.nil?
flash[:error] = "object is not not found"
elsif #entry.destroy
flash[:notice] = 'blah'
respond_to do |format|
format.html { redirect_to rejected_admin_entries_path }
format.json { head :no_content }
format.js
end
else
flash[:error] = 'There was a problem fetching the record'
redirect_to rejected_admin_entries_path
end
end
The problem is in the destroy method. You are not calling return. This should work:
def destroy
if #entry.nil?
flash[:error] = "object is not not found"
return
end
if #entry.destroy
flash[:notice] = 'blah'
respond_to do |format|
format.html { redirect_to rejected_admin_entries_path }
format.json { head :no_content }
format.js
end
else
flash[:error] = 'There was a problem fetching the record'
redirect_to rejected_admin_entries_path
end
end
Anyway this code is sub-optimal. You should find the #entry in a before_filter aspect and return a 404 if is not found.
E.g.,
before_filter :find_entry
...
def find_entry
#entry = Entry.find(params[:id])
end
I have this simple action (originally generated by scaffold):
def destroy
#item = Item.find(params[:id])
#item.destroy
respond_to do |format|
format.html { redirect_to :back, :success => 'Post was successfully removed.' }
format.json { head :no_content }
end
end
The page is redirected back, but the alert message is not shown. (snippet for displaying flash messages works well in the whole application, but not here)
What's the problem here?
Thanks
Try this:
format.html { redirect_to :back, :flash => {:success => 'Post was successfully removed.' }}
The flash key is either :notice or :alert. There is no :success key.
I have the following code:
def edit
#post = Post.find(params[:id])
if !current_user.posts.include?(#post)
permission_denied
end
respond_to do |format|
format.html # edit.html.erb
format.json { render :json => #post }
end
end
def permission_denied
flash[:notice] = 'Sorry, you are not authorized to access that page.'
redirect_to root_url
end
How could adapt this code, so it doesn't show me the "Render and/or redirect were called multiple times in this action" . I have tried adding "and return" to redirect_to root_url and return, but I keep getting the same error.
You should return from the edit action:
def edit
#post = Post.find(params[:id])
return permission_denied if !current_user.posts.include?(#post)
respond_to do |format|
format.html # edit.html.erb
format.json { render :json => #post }
end
end