Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Based on your answer to my comment I think handling deletion unobtrusively is a good place to start. I'll use Product with scaffolding as an example, but the code will be generic so it should be easy to use in your application.</p> <p>First add a new option to your route:</p> <pre><code>map.resources :products, :member =&gt; { :delete =&gt; :get } </code></pre> <p>And now add a delete view to your Product views:</p> <pre><code>&lt;% title "Delete Product" %&gt; &lt;% form_for @product, :html =&gt; { :method =&gt; :delete } do |f| %&gt; &lt;h2&gt;Are you sure you want to delete this Product?&lt;/h2&gt; &lt;p&gt; &lt;%= submit_tag "Delete" %&gt; or &lt;%= link_to "cancel", products_path %&gt; &lt;/p&gt; &lt;% end %&gt; </code></pre> <p>This view will only be seen by users with JavaScript disabled.</p> <p>In the Products controller you'll need to add the delete action.</p> <pre><code>def delete Product.find(params[:id]) end </code></pre> <p>Now go to your index view and change the Destroy link to this:</p> <pre><code>&lt;td&gt;&lt;%= link_to "Delete", delete_product_path(product), :class =&gt; 'delete' %&gt;&lt;/td&gt; </code></pre> <p>If you run the app at this point and view the list of products you'll be able to delete a product, but we can do better for JavaScript enabled users. The class added to the delete link will be used in our JavaScript.</p> <p>This will be a rather large chunk of JavaScript, but it's important to focus on the code that deals with making the ajax call - the code in the ajaxSend handler and the 'a.delete' click handler. </p> <pre><code>(function() { var originalRemoveMethod = jQuery.fn.remove; jQuery.fn.remove = function() { if(this.hasClass("infomenu") || this.hasClass("pop")) { $(".selected").removeClass("selected"); } originalRemoveMethod.apply(this, arguments); } })(); function isPost(requestType) { return requestType.toLowerCase() == 'post'; } $(document).ajaxSend(function(event, xhr, settings) { if (isPost(settings.type)) { settings.data = (settings.data ? settings.data + "&amp;" : "") + "authenticity_token=" + encodeURIComponent( AUTH_TOKEN ); } xhr.setRequestHeader("Accept", "text/javascript, application/javascript"); }); function closePop(fn) { var arglength = arguments.length; if($(".pop").length == 0) { return false; } $(".pop").slideFadeToggle(function() { if(arglength) { fn.call(); } $(this).remove(); }); return true; } $('a.delete').live('click', function(event) { if(event.button != 0) { return true; } var link = $(this); link.addClass("selected").parent().append("&lt;div class='pop delpop'&gt;&lt;p&gt;Are you sure?&lt;/p&gt;&lt;p&gt;&lt;input type='button' value='Yes' /&gt; or &lt;a href='#' class='close'&gt;Cancel&lt;/a&gt;&lt;/div&gt;"); $(".delpop").slideFadeToggle(); $(".delpop input").click(function() { $(".pop").slideFadeToggle(function() { $.post(link.attr('href').substring(0, link.attr('href').indexOf('/delete')), { _method: "delete" }, function(response) { link.parents("tr").fadeOut(function() { $(this).remove(); }); }); $(this).remove(); }); }); return false; }); $(".close").live('click', function() { return !closePop(); }); $.fn.slideFadeToggle = function(easing, callback) { return this.animate({opacity: 'toggle', height: 'toggle'}, "fast", easing, callback); }; </code></pre> <p>Here's the CSS you'll need too:</p> <pre><code>.pop { background-color:#FFFFFF; border:1px solid #999999; cursor:default; display: none; position:absolute; text-align:left; z-index:500; padding: 25px 25px 20px; margin: 0; -webkit-border-radius: 8px; -moz-border-radius: 8px; } a.selected { background-color:#1F75CC; color:white; z-index:100; } </code></pre> <p>We need to send along the auth token when we make POST, PUT or DELETE. Add this line under your existing JS tag (probably in your layout):</p> <pre><code>&lt;%= javascript_tag "var AUTH_TOKEN = #{form_authenticity_token.inspect};" if protect_against_forgery? -%&gt; </code></pre> <p>Almost done. Open up your Application controller and add these filters:</p> <pre><code>before_filter :correct_safari_and_ie_accept_headers after_filter :set_xhr_flash </code></pre> <p>And the corresponding methods:</p> <pre><code>protected def set_xhr_flash flash.discard if request.xhr? end def correct_safari_and_ie_accept_headers ajax_request_types = ['text/javascript', 'application/json', 'text/xml'] request.accepts.sort!{ |x, y| ajax_request_types.include?(y.to_s) ? 1 : -1 } if request.xhr? end </code></pre> <p>We need to discard flash messages if it's an ajax call - otherwise you'll see flash messages from the "past" on your next regular http request. The second filter is also required for webkit and IE browsers - I add these 2 filters to all of my Rails projects.</p> <p>All that's left is the destroy action:</p> <pre><code>def destroy @product.destroy flash[:notice] = "Successfully destroyed product." respond_to do |format| format.html { redirect_to redirect_to products_url } format.js { render :nothing =&gt; true } end end </code></pre> <p>And there you have it. Unobtrusive deleting with Rails. It seems like a lot of work all typed out, but it's really not that bad once you get going. You might be interested in this <a href="http://railscasts.com/episodes/136-jquery" rel="nofollow noreferrer">Railscast</a> too.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload