views:

50

answers:

1

I have a destroy action defined for a particular resource. On completion, it uses an rjs file with a visual effect to remove the resource from the page that it is being called from.

My problem is that the destroy action can be called from 2 different templates. And so the visual effect needs to be different, depending on which template it is being called from... Is there a way to do so...?

1: I figure that one way I could do this, is to have a destroy action, and a destroy-variant action, with one template calling the destroy-variant action, and the other calling the normal one... However, I'm pretty sure that that is against the idea of DRY. And to be honest, I'm not entirely sure how to do so either... Will using :method => :delete, :action => :destroy-variant in the URL options work?

2: The other way that seems like a possibility to me, is to find out which page is calling the action, and then pushing out different rjs files as appropriate. But I've got absolutely no idea how to differentiate which page is doing the action calling.

3: The final way is just for me to redo the templates/RJS so that the same visual effect can be applied to both templates.

I'd appreciate the advice! :)

+2  A: 

Firstly, please increase your acceptance rate. Its too low.

Secondly, You do not mention the javascript library that you are using. This solution is jquery based. Its quite easy to do what you want using just one action destroy. But i would suggest a different technique to go about it. I find rjs pretty constraining. Go for the jquery taconite plugin. Its all markup rather than... a bunch of javascript mixed with erb which is less appealing to the eyes!

So now instead of your destroy.rjs you will have a destroy.xml.erb. Before i go into what you need to put in it, lets see what modifications you need to make for your destroy action.

BEFORE:

   def destroy
        @model = Model.find(params[:id])
        @model.destroy

          respond_to do |format|
            format.html { redirect_to :action => :index }
            format.xml
          end
    end

AFTER:

   def destroy
        @model = Model.find(params[:id])
        @model.destroy
        @template = params[:template]
          respond_to do |format|
            format.html { redirect_to :action => :index }
            format.xml
          end
    end

Add a named route in your routes.rb to simplify things:

map.destroy_using_template 'destroy/:id/:template', :controller => "controller", :action => "destroy"

In your views:

Add the jquery taconite plugin to the header in your <layout>.html.erb,

<%= javascript_include_tag "jquery.js", "jquery.taconite.js" %>

In the view for template 1:

Assuming you use a link to delete.

   <%= link_to "Delete", destroy_using_template_path(:id => "1", :template => "temp1"), :method => :delete, :confirm => "Are you sure you want to delete the record?" %>

and the same for template 2:

Assuming you use a link to delete.

   <%= link_to "Delete", destroy_using_template_path(:id => "1", :template => "temp2"), :method => :delete, :confirm => "Are you sure you want to delete the record?" %>

Now in your destroy.xml.erb

<taconite>
    <% if @template=="temp1" %>
      <remove select="#template1" />
    <% elsif @template=="temp2" %>
      <remove select="#template2" />
    <% end %>

    <eval>
        //OPTIONAL: Execute some javascript here if you want. You can do most of the DOM modifications using taconite itself.
        alert("HEY!!!");
    </eval>
</taconite>

Is it not easy now? :)

Remember, while using taconite you have to make sure the code in destroy.xml.erb is XML compliant. Make sure you close any open tags. Read up more on taconite here: http://malsup.com/jquery/taconite/

Taconite implements all the regular jquery DOM modifiers in markup and a few extra of its own. If you want to switch to javascript you can easily do so by just including that javascript in the eval tag as shown above.

Shripad K
Jty.tan
The problem with built-in helpers is that it is obtrusive and prevent(rather make it difficult) to doing exactly what you are trying to achieve. If you have used jquery and if you are comfortable with it then i suggest that you move away from using built-in helpers soon. Jquery simplifies a lot of things for you. If you want a tutorial to setup the basic ajax required check this answer of mine.. i have provided all the steps to get started: http://stackoverflow.com/questions/3004371/rails-need-a-helping-hand-to-finish-this-jquery-ajax-problem/3007897#3007897
Shripad K
Another drawback of using obtrusive javascript is that it cannot be cached properly leading to severe performance hits. The advantage of unobtrusive javascript on the other hand is that the entire code can be grouped in just one file and minified(compressed) using a compiler. You can think of javascript to the likes of images. It gets downloaded and executed client side everytime a page is requested. If its stored in one file it can be cached by the browser so that it need not be downloaded everytime. That will speed up your site tremendously.
Shripad K
Wow. Your answer in the other post is so far beyond my comfort/experience level it's not funny... I'll go work through those steps and try to understand what's happening, and what for. You've given a lot of detail, which is awesome. I just need the time now to figure it out. Thanks heaps! :) PS: No, I haven't used jquery before. :(
Jty.tan
Regarding the `params[:template]` bit... This was one issue I had, how do I actually find out which template is being called from within the code? It doesn't seem to be added to the `params` hash automatically, and I can't figure out a way to pass that as a parameter.
Jty.tan
I have given that in the answer too. If you observe the route `map.destroy_using_template 'destroy/:id/:template', :controller => "controller", :action => "destroy"` you can see that you are passing the template as a parameter. Now how will you actually pass it from the view? You do this: ` <%= link_to "Delete", destroy_using_template_path(:id => "1", :template => "temp1"), :method => :delete, :confirm => "Are you sure you want to delete the record?" %>`
Shripad K
You can do the same for 'n' templates, `<%= link_to "Delete", destroy_using_template_path(:id => "1", :template => "tempn"), :method => :delete, :confirm => "Are you sure you want to delete the record?" %>`
Shripad K
Also add the route to the top of all other routes in the routes.rb file. It should have a higher priority compared to the other routes.
Shripad K
As far as the other post is concerned its actually pretty simple to understand. I suggest you pick up a jquery book. Its extremely easy to understand and you should be extremely comfortable using jquery in a matter of hours. I suggest `JQuery in action` from manning, or `JQuery From novice to ninja`. Both are decent beginner books and you can pick up from there.
Shripad K
Oooohhhh... Ok, that makes heaps more sense now. Thanks! :D Actually, *everything* about your answer makes more sense now. lol. I'd gotten caught up in the taconite bit, and couldn't figure out where the magic was that got it the information. >.< I'll have a good look into jQuery. It's definitely something that I've seen mentioned in various places, so it'd be worth learning. :)
Jty.tan
Its definitely worth learning. If you have any more follow up questions you can post here. :)
Shripad K