
- •Introduction
- •Rails Is Agile
- •Finding Your Way Around
- •Acknowledgments
- •Getting Started
- •Models, Views, and Controllers
- •Installing Rails
- •Installing on Windows
- •Installing on Mac OS X
- •Installing on Unix/Linux
- •Rails and Databases
- •Keeping Up-to-Date
- •Rails and ISPs
- •Creating a New Application
- •Hello, Rails!
- •Linking Pages Together
- •What We Just Did
- •Building an Application
- •The Depot Application
- •Incremental Development
- •What Depot Does
- •Task A: Product Maintenance
- •Iteration A1: Get Something Running
- •Iteration A2: Add a Missing Column
- •Iteration A4: Prettier Listings
- •Task B: Catalog Display
- •Iteration B1: Create the Catalog Listing
- •Iteration B2: Add Page Decorations
- •Task C: Cart Creation
- •Sessions
- •More Tables, More Models
- •Iteration C1: Creating a Cart
- •Iteration C3: Finishing the Cart
- •Task D: Checkout!
- •Iteration D2: Show Cart Contents on Checkout
- •Task E: Shipping
- •Iteration E1: Basic Shipping
- •Task F: Administrivia
- •Iteration F1: Adding Users
- •Iteration F2: Logging In
- •Iteration F3: Limiting Access
- •Finishing Up
- •More Icing on the Cake
- •Task T: Testing
- •Tests Baked Right In
- •Testing Models
- •Testing Controllers
- •Using Mock Objects
- •Test-Driven Development
- •Running Tests with Rake
- •Performance Testing
- •The Rails Framework
- •Rails in Depth
- •Directory Structure
- •Naming Conventions
- •Active Support
- •Logging in Rails
- •Debugging Hints
- •Active Record Basics
- •Tables and Classes
- •Primary Keys and IDs
- •Connecting to the Database
- •Relationships between Tables
- •Transactions
- •More Active Record
- •Acts As
- •Aggregation
- •Single Table Inheritance
- •Validation
- •Callbacks
- •Advanced Attributes
- •Miscellany
- •Action Controller and Rails
- •Context and Dependencies
- •The Basics
- •Routing Requests
- •Action Methods
- •Caching, Part One
- •The Problem with GET Requests
- •Action View
- •Templates
- •Builder templates
- •RHTML Templates
- •Helpers
- •Formatting Helpers
- •Linking to Other Pages and Resources
- •Pagination
- •Form Helpers
- •Layouts and Components
- •Adding New Templating Systems
- •Introducing AJAX
- •The Rails Way
- •Advanced Techniques
- •Action Mailer
- •Sending E-mail
- •Receiving E-mail
- •Testing E-mail
- •Web Services on Rails
- •Dispatching Modes
- •Using Alternate Dispatching
- •Method Invocation Interception
- •Testing Web Services
- •Protocol Clients
- •Securing Your Rails Application
- •SQL Injection
- •Cross-Site Scripting (CSS/XSS)
- •Avoid Session Fixation Attacks
- •Creating Records Directly from Form Parameters
- •Knowing That It Works
- •Deployment and Scaling
- •Picking a Production Platform
- •A Trinity of Environments
- •Iterating in the Wild
- •Maintenance
- •Finding and Dealing with Bottlenecks
- •Case Studies: Rails Running Daily
- •Appendices
- •Introduction to Ruby
- •Ruby Names
- •Regular Expressions
- •Source Code
- •Cross-Reference of Code Samples
- •Resources
- •Index

PROTOCOL CLIENTS |
425 |
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="Backend" xmlns:typens="urn:ActionWebService" . . .
<types>
<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" . . .
<xsd:complexType name="Product"> <xsd:all>
<xsd:element name="id" type="xsd:int"/> <xsd:element name="title" type="xsd:string"/>
<xsd:element name="description" type="xsd:string"/> <xsd:element name="image_url" type="xsd:string"/>
<xsd:element name="price" type="xsd:double"/>
<xsd:element name="date_available" type="xsd:dateTime"/>
</xsd:all>
</xsd:complexType>
<xsd:complexType name="IntegerArray"> <xsd:complexContent>
<xsd:restriction base="soapenc:Array">
<xsd:attribute wsdl:arrayType="xsd:int[]" ref="soapenc:arrayType"/> </xsd:restriction>
</xsd:complexContent> </xsd:complexType>
</xsd:schema>
</types>
<message name="FindAllProducts">
</message>
<message name="FindAllProductsResponse">
<part name="return" type="typens:IntegerArray"/>
</message>
<message name="FindProductById"> <part name="param0" type="xsd:int"/>
</message>
. . .
Figure 20.4: WSDL Generated by AWS
Having two different URLs for these different cases may seem arbitrary, but there is a reason. For delegated and layered dispatching, the information telling us which service object the invocation should be routed to is embedded in the request. For delegated dispatching we rely on the controller action name to determine which service it should go to.
Note that these URLs are used as both the SOAP and XML-RPC message endpoints; AWS is able to determine the type of message from the request.
20.7 Protocol Clients
Action Web Service includes some client classes for accessing remote web services. These classes understand Action Web Service API definitions, so if we have the API definition of a remote service, we can access that service
Prepared exclusively for Rida Al Barazi
Report erratum

PROTOCOL CLIENTS 426
with type conversion to and from the correct types occurring automatically for us.
However, these are not general-purpose clients. If our client application is not tightly coupled to the server, it may make more sense to use Ruby’s native SOAP and XML-RPC clients.
If we want to access a remote web service API from inside a controller with the AWS clients, use the web_client_api( ) helper function.
class MyController < ApplicationController
web_client_api :product, :soap,
"http://my.app.com/backend/api"
def list
@products = product.find_all_products.map do |id| product.find_product_by_id(id)
end end
end
The web_client_api declaration creates a protected method named product( ) in the controller. This uses the ProductApi class we created in the first example. Calling the product( ) method returns a client object with all the methods of ProductApi available for execution.
We can also invoke the web service API directly by creating an instance of the client for the relevant protocol (either ActionWebService::Client::Soap or ActionWebService::Client::XmlRpc). We’ll then be able to invoke API methods on this instance.
shop = ActionWebService::Client::Soap.new(ProductApi,
"http://my.app.com/backend/api") product = shop.find_product_by_id(5)
Prepared exclusively for Rida Al Barazi
Report erratum