views:

1230

answers:

3

Hi All,

I'm having severe issues with Rails, Javascript, and redirects. Basically I have the "simple" issue of redirecting to a different page if JS is disabled. If JS is enabled, then I add a new item inline immediately -- this works like a charm. However, if JS is disabled I want to redirect to the NEW page of a different controller. Basically the model setup is as such:

Site -> Buildings -> Controllers (not to be confused with Rails "controllers")

I have a "SiteManagerController" that uses JS to manage the whole thing. Basically I have a scenario where I'm trying to do the following:

1) if JS is enabled I want to add the item inline 2) if JS is disabled, I wish to render ":controller => buildings, :action => new"

My "link_to_remote" is straightforward. As I said, it works for JS. My rails controller code is as follows:

def add_building @building = Building.new @building.name = "Untitled" @building.site_id = params[:id] @building.save respond_to do |format| format.html {redirect_to :controller => "buildings", :action => "new"} format.js end end

This does not work. For what it's worth, when viewing page source there is no indication that anything is different when JS is enabled vs disabled. All links look the same -- i.e. Ajaxy.

I know it shouldn't be this complex an issue, but I'm rather stumped.

Best.

P.S. Please don't change the title of this post. ;)

A: 

I believe the solution lies in the "link_to_remote" and not any particular controller. The following seems to work:

     <div><%=link_to_remote "NEW BUILDING", {:url => {:action => "add_building", :id => site.id}},
   {:href => url_for(:controller => "buildings",:action => "new")}%></div>

If you guys have better suggestions, by all means post. Thanks again.

humble_coder
A: 

Have you tried writing the form so that it redirects to another page, then have some js fire off when the page loads that over-writes that with your ajax-y js? This way, if js is disabled, the page will be redirected as expected.

nilamo
I'm not sure that's approaching it from the right direction. Basically imagine a web "GUI" in which you can ADD and DELETE items. If JS is enabled I simply want to click the ADD link and have a new "blank" item appear. However, if JS is disabled, I want to be taken to the NEW page for the item. Where I go after the form is of no concern atm -- although I will want to redirect back to the original page eventually.
humble_coder
A: 

The link_to_remote solution mentioned would probably work, but if you're looking for an unobtrusive way to do it, you use some javascript (jQuery) like this:

in your .html.erb file:

<%=link_to "New Building", new_building_path, :id => 'new_building_link' %>

in a javascript file:

$(document).load(function() {
  $("#new_building_link").click(function() {
    $.ajax({
      type:     "POST",  # or whatever http method you need
      url:      "/buildings/add_building",
      dataType: "script"
    });
    return false;
  });
});

Then return some JS that will update the area of the page you want to change.

I'm sure there's a similar way to do it with Prototype, the default JS library for rails, but I don't know Prototype.

Also note that this uses restful routes (new_building_path rather than specifying the controller and the action). This is the preferred method now; you'd just need to add 'map.resources :buildings' to routes.rb. There are a couple of Railscasts about restful routes, and if you have $9 to drop, a Peepcode.

As one of the comments mentioned you could shrink your Building creation code by using: Building.create({:name => "Untitled", :site_id => params[:id]})

zgchurch
Yeah, basically I'm trying to be as verbose as possible (in the short term) while keeping it RAILScentric (e.g. using wrappers instead of explicit JS calls). But I do like your suggestion. It confirms that the solution lies in the link(s) and not the controller. Thanks.
humble_coder
if you want it to be as simple as possible and don't mind obtrusive JS, then using link_to_remote and specifying an href would probably be your best bet, as the first response suggests.
zgchurch