Rails: Redirect within XHR
I have a 开发者_如何学JAVAParent
model which has Children
. If all the Children
of a certain Parent
are deleted, I'd like to automatically delete the Parent
as well.
In a non-AJAX scenario, in the ChildrenController
I would do:
@parent = @child.parent
@child.destroy
if @parent.children.empty?
redirect_to :action => :destroy,
:controller => :parents,
:id => @parent.id
end
But this is impossible when the request is XHR. The redirect causes a GET request.
The only way I can think of to do this with AJAX is add logic to the response RJS, causing it to create a link_to_remote
element, "click" it, and then remove it. It seems ugly. Is there a better way?
Clarification
When I use the term redirect, I do not mean an HTTP redirect. What I mean is that instead of returning the RJS associated with destroying Child
, I want to perform destroy
on Parent
and return the RJS associated with destroying Parent.
I would listen to what nathanvda says, but you can do it via ruby syntax (and you don't need erb scriptlets in rjs):
if @parent.children.empty?
page.redirect_to(url_for :action => :destroy,
:controller => :parents,
:id => @parent.id)
else
.. do your normall stuff here ..
end
A better approach to destroying the parent through a redirect is doing it in an after_hook. Not only you don't have to tell your user's browser to make another request, you also don't need to keep track of everywhere in the code where you delete children so you don't end up with hanging parents.
class Parent < ActiveRecord::Base
# also worth getting the dependent destroy, so you don't have hanging children
has_many :chilren, :dependent => :destroy
end
class Child < ActiveRecord::Base
after_destroy { parent.destroy if parent.children.empty? }
end
Then you can just handle however you prefer what to show the user when that happens, like redirecting the user to '/parents'.
I would guess you could set the window.location.href
in your rjs, something like
<% if @parent.children.empty? %>
window.location.href='<%= url_for :action => :destroy,
:controller => :parents,
:id => @parent.id %>'
<% else %>
.. do your normall stuff here ..
<% end %>
assuming you render javascript. Not sure if it is completely correct, but hope you get the idea.
[EDIT: added controller code]
TO make it clearer, your controller would look as follows
@parent = @child.parent
@child.destroy
if @parent.children.empty?
render :redirect
end
精彩评论