Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Agile Web Development With Rails, 1st Edition (2005).pdf
Скачиваний:
28
Добавлен:
17.08.2013
Размер:
7.99 Mб
Скачать

 

 

 

 

 

I TERATION D2: SHOW CAR T CONTENTS ON CHECKOUT

104

depot> mysql depot_development

 

 

 

 

 

Welcome to the MySQL monitor. Commands end with ; or \g.

 

 

 

mysql> select * from orders;

 

 

 

 

 

+

----+

-------------

+-----------------------

 

+

-------------

+----------

+

 

| id |

name

| email

 

| address

| pay_type |

 

+----

+-------------

 

+-----------------------

 

+-------------

 

+----------

+

 

|

3 |

Dave Thomas | customer@pragprog.com | 123 Main St | check

|

 

+----

+-------------

 

+-----------------------

 

+-------------

 

+----------

+

 

1

row in set (0.00 sec)

 

 

 

 

 

 

mysql> select * from line_items;

 

 

 

 

+----

+------------

 

+----------

+

----------+------------

+

 

 

 

| id |

product _ id | order_id | quantity | unit_price |

 

 

 

+----

+------------

 

+----------

+----------

+------------

+

 

 

 

|

4 |

 

4 |

3 |

1 |

29.95 |

 

 

 

+----

+------------

 

+----------

+----------

+------------

+

 

 

 

1

row in set (0.00 sec)

 

 

 

 

 

 

Ship it! Or, at least, let’s show it to our customer. She likes it. Except....

Do you suppose we could add a summary of the cart contents to the checkout page? Sounds like we need a new iteration.

 

9.2 Iteration D2: Show Cart Contents on Checkout

 

In this iteration we’re going to add a summary of the cart contents to the

 

checkout page. This is pretty easy. We already have a layout that shows

 

the items in a cart. All we have to do is cut and paste the code across

 

into the checkout view and...ummm...oh, yeah, you’re watching what I’m

 

doing.

 

OK, so cut-and-paste coding is out, because we don’t want to add dupli-

 

cation to our code. What else can we do? It turns out that we can use

 

Rails components to allow us to write the cart display code just once and

 

invoke it from two places. (This is actually a very simple use of the compo-

 

nent functionality; we’ll see it in more detail in Section 17.9, Layouts and

 

Components, on page 356.)

 

As a first pass, let’s edit the view code in checkout.rhtml to include a call to

 

render the cart at the top of the page, before the form.

File 38

<%= error_messages_for("order") %>

 

<%= render_component(:action => "display_cart") %>

 

<%= start_form_tag(:action => "save_order") %>

 

<table>

 

<tr>

 

<td>Name:</td>

 

The render_component( ) method invokes the given action and substitutes

 

the output it renders into the current view. What happens when we run

 

this code? Have a look at Figure 9.4, on page 106.

Prepared exclusively for Rida Al Barazi

Report erratum

ITERATION D2: SHOW CAR T CONTENTS ON CHECKOUT

105

Figure 9.3: Our First Checkout

Prepared exclusively for Rida Al Barazi

Report erratum

ITERATION D2: SHOW CAR T CONTENTS ON CHECKOUT

106

Figure 9.4: Methinks The Component Renders Too Much

 

Oops! Invoking the display_cart action has substituted in the entire ren-

 

dered page, including the layout. While this is interesting in a post-

 

modern, self-referential kind of way, it’s probably not what our buyers

 

were expecting to see.

 

We’ll need to tell the controller not to use our fancy layout when it’s ren-

 

dering the cart as a component. Fortunately, that’s not too difficult. We

 

can set parameters in the render_component( ) call that are accessible in

 

the action that’s invoked. We can use a parameter to tell our display_cart( )

 

action not to invoke the full layout when it’s being invoked as a compo-

 

nent. It can override Rails’ default rendering in that case. The first step is

 

to add a parameter to the render_component( ) call.

File 40

<%= render_component(:action => "display_cart",

 

:params => { :context => :checkout }) %>

 

We’ll alter the display_cart( ) method in the controller to call different render

 

methods depending on whether this parameter is set. Previously we didn’t

 

have to render our layout explicitly; if an action method exits without

 

calling a render method, Rails will call render( ) automatically. Now we

 

need to override this, calling render(:layout=>false) in a checkout context.

Prepared exclusively for Rida Al Barazi

Report erratum

ITERATION D2: SHOW CAR T CONTENTS ON CHECKOUT

107

File 39

def display_cart

 

@cart = find_cart

 

@items = @cart.items

 

if @items.empty?

 

redirect_to_index("Your cart is currently empty")

 

end

if params[:context] == :checkout render(:layout => false)

end end

When we hit Refresh in the browser, we see a much better result.

We call our customer over, and she’s delighted. One small request: can we remove the Empty cart and Checkout options from the menu at the right? At the risk of getting thrown out of the programmers union, we say, “That’s not a problem.” After all, we just have to add some conditional code to the display_cart.rhtml view.

File 42

<ul>

 

 

<li><%= link_to 'Continue shopping', :action => "index" %></li>

 

<% unless params[:context] == :checkout -%>

 

<li><%= link_to 'Empty cart',

:action => "empty_cart" %></li>

 

<li><%= link_to 'Checkout',

:action => "checkout" %></li>

 

<% end -%>

 

 

</ul>

 

 

While we’re at it, we’ll add a nice little heading just before the start of the

 

form in the template checkout.rhtml in app/views/store.

File 41

<%= error_messages_for("order") %>

 

<%= render_component(:action => "display_cart",

 

:params => { :context => :checkout }) %>

 

<h3>Please enter your details below</h3>

Prepared exclusively for Rida Al Barazi

Report erratum

ITERATION D2: SHOW CAR T CONTENTS ON CHECKOUT

108

A quick refresh in the browser, and we have a nice looking checkout page.

Our customer is happy, our code is neatly tucked into our repository, and it’s time to move on. Next we’ll be looking at adding shipping functionality to Depot.

What We Just Did

In a fairly short amount of time, we did the following.

Added an orders table (with corresponding model) and linked its rows to the line items we’d defined previously

Created a form to capture details for the order and linked it to the

Order model

Added validation and used helper methods to display errors back to the user

Used the component system to include the cart summary on the checkout page

Prepared exclusively for Rida Al Barazi

Report erratum