Practical 6
0. Finish Practical Sheet 5.
(Alternatively,
move your old depot application out of the way
and get a fresh copy
by first creating a fork of https://github.com/cs424/depot.git
on your github
page, and secondly cloning the fork into your
working directory.
Then cd depot
and run rake db:migrate
and rake db:seed
to set up the database.)
1. Partials. A partial is a named chunk of a view template in
its own file. With the render
method, it can be included into
views, layouts, or even other partials. And you can pass arguments to
a partial, … it really has a lot in common with a subroutine of a computer program.
The filename of a partial starts with an underscore (_
),
followed by the name of the partial and the extension
.html.erb
.
Let’s start by moving the formatting of line items in the shopping cart
into its own file. This is a sufficiently complex task too deserve
a place of its own. In the app/views/line_items
folder, create a
file _line_item.html.erb
. Note the leading _
and the use of singular
in the file name. This file now contains a partial with name line_item
(without leading _
). Copy the code that describes the table row
of a line item in a shopping cart from the cart view into this new file:
Then replace each occurence of item
by line_item
(3 times) so that it matches the name of
the partial.
2. Now replace the loop over all line items which contains that chunk in the cart view by the single line:
Reload the page and make sure it still works as desired.
(Note the =
sign in the opening ERB bracket <%=
.) If it works, the
render
method has correctly identified the thing to render as a list of line items, has found the instructions for rendering a single line item in the
line_item
partial in the line_items
view folder and has applied this
to each item in the list.
Note how a series of naming conventions makes it possible to remove
an entire level of complexity from the program.
3. Next, we are going to wrap up the shopping cart display into a partial, so that we can easily include it in the side bar of the catalog page.
Following the same naming conventions as before,
create a new file for a partial cart
(which name? which folder?).
Then copy the contents of the cart view
show.html.erb
into the new file
and replace each occurrence of @cart
by cart
so that it matches the name of
the partial. Also remove the
notice at the top of the file.
You can now replace everything except for that notice in the original cart view file by the single line:
Check whether it still works as desired.
3a. Actually, what do the tests report? If there are errors, what’s needed to fix them? If not, this might be a good time to commit the recent changes.
4. You are now in a position to display a cart wherever you want, with a single command. In order to have a cart to display on the store page, add the lines
before the index
method of the store controller (which file?).
This will take care of setting @cart
to the current cart
when the index
action is called, and make the variable available
in the view.
5. The partial can now be invoked by the text
inside the <nav>
element of the layout
(which file?). Try it out!
6. The class
attribute "carts"
of the <div>
element that contains the cart makes it pick up the style defined in the stylefile carts.scss
.
In order to make the cart more readable when it is displayed in the green sidebar (where it has the id
attribute cart
), add
to the nav
section of the application.scss
style file.
7. Now adding a line item should redisplay the store
and not the cart. Change the appropriate line in the create
method
of the line items controller to
8. Run the tests again and see what fails.
If all works fine, commit the changes to your local git
repository, and push them to the github
cloud.
git add .
git commit -m "include cart in store layout"
git push
9. Ajax.
If only the contents of the cart has changed then
only that portion of the page really needs to be updated,
rather than requesting, composing and sending a new version of the entire page.
Ajax refers to the ability of the browser to
change the internal (DOM) representation of a page, and to interact
with the server on that level. This usually involves
a few (small) changes to the existing programs.
First we instruct the "Add to Cart"
button to send an Ajax request
to the server (rather than requesting a new copy of the entire page.
This is done by adding the option remote: true
to the button (which file?):
10.
On the receiving end, we need to allow
the create
method of the line items
controller to respond to Ajax requests.
This is done
by adding one line
to the create
method of the line items
controller, after the line you changed in step 8.
11.
Finally, in the line items views folder, create a file create.js.erb
with the following two lines of code:
Executing this code will replace the content of the <div>
with
ID cart
by the result of rendering the cart partial.
rails
knows how to translate this into proper JavaScript; ruby
templates
are treated in the same was as they are in other .erb
files; and j
is short for
escape_javascript
, a helper method that converts from ruby
syntax into
JavaScript syntax.
Try it out: the page should refresh much quicker and smoother!
11a. If all works fine, commit the changes to your local git
repository, and push them to the github
cloud.
12. Highlights. CSS can do way more with your pages. We can use the animation feature to highlight the latest change to the cart. For this, add the following
to the stylesheet line_items.scss
.
13. In order to highlight the latest item in a cart, we need a way
to identify it. For that, replace format.js
in the line item
controller’s create
method by:
Then, in the line_item
partial, replace the opening <tr>
by:
I don’t particularly like this code. (Why? Because there must be a cleaner way to achieve this with the content_tag
helper. If you find one, there is a comment box below …) It marks (only) the latest
item with the "line_item_highlight"
class.
Now add a new item a watch Yellow Fade in action.
14. Empty Carts. If the cart is empty, there is no need to display it. One way to achieve this is by first defining a general helper method that conditionally renders objects. Add
to the ApplicationHelper
module in the app/helpers
folder.
Then replace the render
command in the <div>
with ID "cart"
in the application layout by
This will render @cart
only if it exists, and if it contains
at least one item.
15. Remove the message about currently empty carts (from where?). It is no longer needed, and it no longer works correctly.
16. Testing AJAX. To test the AJAX functionality, add the following test to the line items controller test.
Now run the tests.
16a. If all works fine, commit the changes to your local git
repository, and push them to the github
cloud.
17. Formulate a question about the new concepts in the comment box below.