Rails%203%20In%20Action

Rails%203%20In%20Action Rails%203%20In%20Action

27.02.2013 Views

esources :tickets do resources :comments resources :tags do member do delete :remove end end end Deleting a tag By nesting the tags resource inside the ticket’s resource, you are given routing helpers such as ticket_tag_path. With the member block inside the resources :tags, you can define further actions that this nested resource responds to. You’ll define that you should accept a DELETE request to a route to a remove action for this resource, which you should now create. Before you add this action to the TagsController, you must first generate this controller by using rails g controller tags Now that you have a controller to define your action in, let’s open app/controllers/ tags_controller.rb and define the remove action in it like this: def remove @ticket = Ticket.find(params[:ticket_id]) if can?(:tag, @ticket.project) || current_user.admin? @tag = Tag.find(params[:id]) @ticket.tags -= [@tag] B Remove tag @ticket.save render :nothing => true end end In this action, you find the ticket based on the id passed through as params[:ticket], and then you do something new. On the left side of -= B you have @ticket.tags. On the right, is an array containing @tag. This combination will remove the tag from the ticket, but will not delete it from the database. On the second-to-last line of this action, you save the ticket minus one tag. On the final line you tell it to return nothing, which will return a 200 OK status to your browser, signaling that everything went according to plan. When you re-run your scenario it will now successfully click the link, but the tag is still there: When I follow "delete-this-tag-must-die" Then I should not see "this-tag-must-die" Failed assertion, no message given. (MiniTest::Assertion) Your tag is unassociated from the ticket but not removed from the page, and so your feature is still failing. The request is made to delete the ticket, but there’s no code currently that removes the tag from the page. There are two problems you must overcome to make this work. The first is that there’s no code. That part’s easy, and you’ll 301

302 CHAPTER 11 Tagging get there pretty soon. The second is that there’s no unique identifier for the element rendered by app/views/tags/_tag.html.erb, which makes removing it from the page exceptionally difficult with JavaScript. Let’s add a unique identifier now and remove the element. 11.4.3 Actually removing a tag You’re removing a tag’s association from a ticket, but you’re not yet showing people that it has happened on the page. You can fix the second of your aforementioned problems by changing the span tag at the top of this partial to be this: This will give the element a unique identifier, which you can use to locate the element and then remove it using JavaScript. Currently for the remove action, you’re rendering nothing. Let’s now remove the render :nothing => true line from this action, because you’re going to get it to render a template. If a request is made asynchronously, the format for that request will be js, rather than the standard html. For views, you’ve always used the html.erb extension, because HTML is all you’ve been serving. As of now, this changes. You’re going to be rendering a js.erb template, which will contain JavaScript code to remove your element. Let’s create the view for the remove action in a file called app/views/tags/remove.js.erb, and fill it with this content: $('#tag-').remove(); This code will be run when the request to the remove action is complete. It uses the jQuery library’s $ function to locate an element with the id attribute of tag-this-tagmust-die and then calls remove() 3 on it, which will remove this tag from the page. When you run your feature using bin/cucumber features/deleting_tags .feature, you see that it now passes: 1 scenario (1 passed) 11 steps (11 passed) Awesome! With this feature done, users with permission to tag on a project will now be able to remove tags too. Before you commit this feature, let’s run rake cucumber :ok spec to make sure everything is ok: 56 scenarios (55 passed) 619 steps (619 passed) # and 39 examples, 0 failures, 19 pending That’s awesome too! Commit and push this: git add . git commit -m "Added remove tag functionality" git push 3 http://api.jquery.com/remove/.

esources :tickets do<br />

resources :comments<br />

resources :tags do<br />

member do<br />

delete :remove<br />

end<br />

end<br />

end<br />

Deleting a tag<br />

By nesting the tags resource inside the ticket’s resource, you are given routing helpers<br />

such as ticket_tag_path. With the member block inside the resources :tags, you can<br />

define further actions that this nested resource responds to. You’ll define that you<br />

should accept a DELETE request to a route to a remove action for this resource, which<br />

you should now create.<br />

Before you add this action to the TagsController, you must first generate this controller<br />

by using<br />

rails g controller tags<br />

Now that you have a controller to define your action in, let’s open app/controllers/<br />

tags_controller.rb and define the remove action in it like this:<br />

def remove<br />

@ticket = Ticket.find(params[:ticket_id])<br />

if can?(:tag, @ticket.project) || current_user.admin?<br />

@tag = Tag.find(params[:id])<br />

@ticket.tags -= [@tag]<br />

B Remove tag<br />

@ticket.save<br />

render :nothing => true<br />

end<br />

end<br />

In this action, you find the ticket based on the id passed through as params[:ticket],<br />

and then you do something new. On the left side of -= B you have @ticket.tags. On<br />

the right, is an array containing @tag. This combination will remove the tag from the<br />

ticket, but will not delete it from the database.<br />

On the second-to-last line of this action, you save the ticket minus one tag. On the<br />

final line you tell it to return nothing, which will return a 200 OK status to your<br />

browser, signaling that everything went according to plan.<br />

When you re-run your scenario it will now successfully click the link, but the tag is<br />

still there:<br />

When I follow "delete-this-tag-must-die"<br />

Then I should not see "this-tag-must-die"<br />

Failed assertion, no message given. (MiniTest::Assertion)<br />

Your tag is unassociated from the ticket but not removed from the page, and so your<br />

feature is still failing. The request is made to delete the ticket, but there’s no code currently<br />

that removes the tag from the page. There are two problems you must overcome<br />

to make this work. The first is that there’s no code. That part’s easy, and you’ll<br />

301

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!