1

In my Rails 3 app I am allowing users to add awards to their profiles. Using Rails UJS I get the create working with ajax. However, I can't for the life of me get destroy to work. Looking inside my server log, it looks like it's working, but the @award isn't removed unless I refresh my profile page.

The code I used is from a tutorial I was following in Beginning Rails 3. If anyone can help me figure out what's going on wrong in my code I'd appreciate it.

My awards_controller.rb:

def create
  @award = Award.new(params[:award])
  if @award.save!
    respond_to do |format|
      #format.html { redirect_to profile_path(@profile) }
      format.js { }
    end
  else
    respond_to do |format|
      #format.html { redirect_to profile_path(@profile)}
      format.js { render 'fail_create_award.js.erb' }
    end
  end
end

def destroy
  @award = Award.find(params[:id])
  @award.destroy
  respond_to do |format|
    #format.html { redirect_to profile_path(@profile) }
    format.js { render :nothing => true }
  end
end

My create.js.erb:

$('ul#awardInfo').append("<%= escape_javascript(render(@award)) %>");
$('#new_award')[0].reset();

My destroy.js.erb:

$("ul#awardInfo<%= (@award) %>").remove();

My form to delete the award, which appears as an "x" next to the award if the award belongs to/was created by the current_user:

<li>-&nbsp;<%= award.body %><% if @profile = current_user.profile %><span class="delete"><%= link_to 'x', award_path(award), :method => :delete, :remote => true, :confirm => "Are you sure you want to remove this award?", :class => "delete_award" %></span><% end %></li>

In my server log when I click "delete" (but before refreshing the page):

Started DELETE "/awards/8" for 127.0.0.1 at 2012-01-11 21:34:58 -0500
  Processing by AwardsController#destroy as JS
  Parameters: {"id"=>"8"}
  Award Load (1.0ms)  SELECT "awards".* FROM "awards" WHERE "awards"."id" = '8' LIMIT 1
  SQL (0.2ms)  BEGIN
  SQL (1.4ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
 FROM pg_attribute a LEFT JOIN pg_attrdef d
 ON a.attrelid = d.adrelid AND a.attnum = d.adnum
 WHERE a.attrelid = '"awards"'::regclass
 AND a.attnum > 0 AND NOT a.attisdropped
 ORDER BY a.attnum

  AREL (0.6ms)  DELETE FROM "awards" WHERE "awards"."id" = 8
  SQL (2.3ms)  COMMIT
Rendered text template (0.0ms)
Completed 200 OK in 31ms (Views: 1.3ms | ActiveRecord: 5.4ms)

UPDATE: If I remove render :nothing => true from my destroy action, it doesn't actually remove the award. My log shows the following:

Started DELETE "/awards/3" for 127.0.0.1 at 2012-02-03 07:54:34 -0500
  Processing by AwardsController#destroy as JS
  Parameters: {"id"=>"3"}
  Award Load (238.1ms)  SELECT "awards".* FROM "awards" WHERE "awards"."id" = '3' LIMIT 1
  SQL (0.4ms)  BEGIN
  SQL (1.6ms)   SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
 FROM pg_attribute a LEFT JOIN pg_attrdef d
 ON a.attrelid = d.adrelid AND a.attnum = d.adnum
 WHERE a.attrelid = '"awards"'::regclass
 AND a.attnum > 0 AND NOT a.attisdropped
 ORDER BY a.attnum
  AREL (97.3ms)  DELETE FROM "awards" WHERE "awards"."id" = 3
  SQL (45.8ms)  COMMIT
Rendered awards/destroy.js.erb (1.1ms)
Completed 200 OK in 954ms (Views: 531.9ms | ActiveRecord: 383.2ms)

UPDATE 2: So a weird thing happens if I go to check the HTML:

  • If I view source, I don't actually see any of the awards.
  • If I inspect the element, I see the following: <li>-&nbsp;test<span class="delete"><a href="/awards/4" class="delete_award" data-confirm="Are you sure you want to remove this award?" data-method="delete" data-remote="true" rel="nofollow">x</a></span></li>

The <li> is the actual award created. I have an award.rb model that belongs_to :profile. If the profile awards belong to my profile, I see a delete option, which is what the <span> is for.

1 Answer 1

4

Putting format.js { render :nothing => true } in your destroy action is presumably telling Rails to not render your destroy.js.erb.

Using the same format.js { } as used in the create action should direct Rails to render destroy.js.erb and subsequently execute the desired action.

Update:

From the code above, it looks like there's nothing in the actual award HTML that can be used to select on for the remove call.

I'd recommend making sure the li elements include ID attributes with the award ID in them. Something like:

<li id="award-<%= @award.id %>">

Then, to remove the award, select its li element and remove as follows:

$('li#award-<%= @award.id %>').remove();

It looks to me like the only remaining issue is that the jQuery call isn't selecting the right element, or any element at all, to call remove on. Giving the li a unique ID and then selecting that ID for removal should make the destroy action render properly.

Sign up to request clarification or add additional context in comments.

5 Comments

Unfortunately taking out render :nothing => true didn't do the trick.
Did doing so alter the Rendered text template line in your log? When you do a render :nothing => true, Rails renders an empty text template. Just doing format.js should have changed what Rails is rendering, and if so, I can probably provide more help if I see what's being rendered now.
I've updated my question with what the log shows. Now at least my destroy.js.erb is being rendered. So it must be what's in that file?
It looks to me like you're trying to remove a ul element, when really you want to be removing an li element. Since element IDs are supposed to be unique across an entire document, you really shouldn't even need a specific tag selector. You can just fetch the element you want to remove by its ID, like: $("awardInfo<%= (@award) %>").remove(). I'm actually not sure what's contained in @award. Is it a model, or just an ID? What does the actual HTML of your awards look like after create has run?
Edited further above to answer your questions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.