Politecnico di Milano – Sede di Como a.a 2005/2006
AJAX – Asynchronous Javascript And XML The Rails way
Final report for “Advanced Prof. Piero FRATERNALI
Informatic Technologies for the Web” course
Author: Alessandro BAFFA 682075
Contents
1 Ruby On Rails framework 1.1 Introduction 1.2 Architecture: an overview 1.3 Directory structure 1.4 Naming convention 1.5 Active Record 1.6 Action controller 1.7 Action view 1.8 Rails vs Jakarta Struts 1.9 Benefits 1.10 Drawbacks
pag.3 pag.4 pag.5 pag.6 pag.8 pag.11 pag.12 pag.17 pag.21 pag.22
2 AJAX – Asynchronous Javascript and XML 2.1 Architecture 2.2 Benefits 2.3 Drawbacks
pag.24 pag.30 pag.31
3 AJAX: the Rails way 3.1 Ajax: the Rails way 3.2 Benefits
pag.32 pag.35
3
1 Ruby On Rails framework 1.1 Introduction To find a simple, one-sentence description of Rails, you need look no futher than the project's homepage: “Rails is a full-stack, open-source Web framework in Ruby for writing real-world applications with joy and less code than most frameworks spend doing XML sit-ups”. Ruby on Rails is a new Web applications framework built on the Ruby language, that makes it easier to develop and mantain web applications. It is a Model-View-Controller (MVC) framework as, for example, Jakarta Struts, but it introduces some differences that make Struts innovative. So, what are this innovation that make Struts different from the other frameworks MVC based? First of all Rails is written in Ruby code, a modern object-oriented scripting language. Ruby is concise without being unintelligible and this property makes the programs easy to write and to read. It makes easier to create, for example, methods that act almost like an extension to the sintax, and it also allows us to performs some operations that usually are done in external configuration files, inside the codebase instead. Secondly, and maybe this is the most important and interesting introduction of Rails, the concept of “convention over configuration”. It reflects the philosophy on which Rails is based, that's the decrease of effort for developers to write Web application without spend a lot of time on the several configuration files (for example Struts), but using some conventions that allow them to concentrate on the solution of the problem. This means that a Web application based on Ruby On Rails framework will have less code of a tipical Java application. It's important to say that the convention used by Rails can be always override, if it's needed. I also can mention other innovations embedded in Ruby on Rails, as reception of incoming e-mails, a full unit testing framework, the generator code, that creates itself the scaffold of the application that allows you to fill in the application's logic, starting with half of the application already in place, and the support for web services, but this report will focalize the attention on the support for AJAX, that's one of the most innovative Web technology (or to be more exact, a set of technologies) that belongs to the so called Web 2.0.
1.2 Architecture: an overview Ruby on Rails is an MVC framework. Rails enforce a structure for your applications where you develop models, view and controllers as separate chunks of functionalities and it knits all togheter as your program execute. The innovation of this framework is that this knitting process is based on an intelligent use of default conventions, that allow developers to spare a lot of time writing configuration files to make it all work. In a Rails application the request are send to a router which works out where in the application the request should be send and how the request itself should be parsed. Ultimately this phase identifies a particoular method (called actions) somewhere in the controller code. The action might look at data in the request it self, it might interact with the model, and it might cause other actions to be invoked. Eventually the action prepares information for the view, which renders something to the user.
The figure above shows how the framework handles an incoming request. As it can be seen the URL structure of the request is quite different from a typical Java application's request, but this stucture allows the developers to follow the concept of “convention over configuration�, in fact all the single part of the URL is related with a specific controller and one of its method. Examining this URL we can split it into 4 parts:
1. my.url: is the name of the application 2. store: is the name of controller 3. add_to_cart: is the name of controller's action 4. 123: is the id of a particoular item which we want to work with and is by convention extacted into an internal parameter called id
The routing component receives the URL from the client and picks it apart. Then it works out all the single part of this incoming request and it knows that has to invoke the method called add_to_cart() of the StoreController (this names are built by Rails conventions and i'll explain this more over in this report).
The add_to_cart() method receives the user request. In this case it finds the current user’s shopping cart (which is an object managed by the model) It also asks the model to find the information for product 123. It then tells the shopping cart to add that product to itself. Now that the shopping carts includes also this product, it needs to let the user see the result in his browser. The controller arranges things so that the view has access to the cart object from the model, and invokes the view code. In Rails, this invocation is often implicit; again conventions help link a particular view with a given action. By following some conventions, Rails permits to build, maintain and extend an application easier, handling all of the low-level housekeepeng and allowing you to focalize on the core operations rather than spending a lot of time writing a lot of configuration files.
1.3 Directory structure As I already said in introduction, Rails framework build itself the scaffold of the application, that's the developers can start with half of the work already in place. The figure below shows the general directory structure build as the framework starting:
And the figure below shows this structure referring to the previous example of the
shopping cart:
Most of the work takes place in the app and test directory. In the first lives the main code of the application, so in here we have to fill the code of controllers, models and views. But Rails makes the life easier also in this phase, in fact inside the app directory it creates also some sub-directories (which names speack for themselves) and inside these Rails creates the objects of controllers, models and views for you. In this way the developers can find the scaffold and the most important code already done and they only have to add the methods inside the objects. As you can see the names of objects are created following the default conventions of Rails (i'll explain it more in detail in the next paragraph)
1.4 Naming convention The most innovation of Rails, that somtimes puzzles newcomers (included myself), is the way by which the framework names automatically the objects and how it can recognize what is the table of database referred to a specific object. This method is by default in Rails, but you can override it whenever you want with your personal rules.
The figure shows how this operation happens. The conviention used in Rails is based to have variable names with letters all in lowercase and words separated by underscore. The case of classes and modules are managed in different way from the case of variables, in fact these are named with words without undescores, but each of them starts by capitol letter. So, for example, Rails leads to variable names such as store_controller and class names such as LineItem. Another important assumption of Rails is that the database table names are plural and have underscore between the words (for example, line_items). This naming conventions are important for Rails which uses this one for generate component names automatically. For example, if you create a model class using the Rails convention, naming it as LineItem, Rails automatically deduce the following: ✔
that the corrisponding database table will be called line_items. As you can see, this name is generated by deleting underscore and convert the capitol letters in lowercase
✔
that the class definition is in a file called line_item.rb, positioned in app/models directory
However this naming convention for the database tables have some trouble. In fact this algorithm for names works properly in the majority of common cases, but if you have a class called Sheep, Rails try to find a table called sheeps .. Other problems can appear with the legacy systems with which this algorithm can have some troubles, and could force you to use strange name for classes. Rails controllers, at last, have some additional conventions. If your application has a store controller, then Rails assumes that: ✔
there's a class called StoreController in app/controllers directory, that contains its definition in a file called store_controller
✔
there's a helper module named StoreHelper in the file store_helper.rb in app/helpers directory
✔
there's a view of this controller that Rails try to find in the app/views/store
✔
the output of this view is wraps in a layout template contained in store.rhtml ore store.rxml in app/view/layouts directory
1.5 Active Record Active Record is the object-relational mapping (ORM) layer supplied with Rails. This support follows the standard ORM model: tables map to classes, rows to objects, and columns to object attributes. It differs from most other ORM library in the way is configured. Following the “convention over configurations” axiom, the configuration files are minimized by using a set of defaults. When you create a subclass of ActiveRecord::Base, you're are creating something that wraps a database table. As I have just say before, this is allowed by the naming convention used for the database table names, so if I create a class called Order as class Order < ActiveRecord::Base end Rails wraps automatically the table called order and we can interrogate it from the class. In parallel of those advantages that come from the ORM standard model, ActiveRecord introduce some owner conventions. The most important are the generation of primary keys and Ids and the CRUD (Create, Read, Update, Delete) support that make developers' life easier, offering a help to manage the model layer of an application. The first one is so referred to the default insert of an integer column called id in the database tables. This convention is made by Rails automatically. The framework takes care of creating new primary key values for recors that you create and add to the database (the values will be ascending integers). The flexibility if Rails is reflected also in this operation, in fact you can decide to use another attribute (maybe already existing in database table) as your primary key, just overriding the default name of key itself. You can see an example of code by which you can use this property: class Book < ActiveRecord::Base set_primary_key “isbn” end However, if you decide to use your own primary key, you also have to take on the responsability of setting a unique primary key in your new row in the table, before save it. The second feature i mentioned before, is the CRUD layer. This one supports Rails developers to implement the four basic operations on database table (create, read, update, delete), offering a set of already methods to manage the attributes of tables that in the majority of cases are the only operations in an application. Insted of implement everytime the same operations in SQL language, ActiveRecord allow the
developers to not “invent the wheel” on every applications, everytime.
Create In the object-relational mapping, in which a table is represented by a class and its rows by objects, it seems reasonable that when you want to create a new row and add it in the table, you want to create a new object of a class. ActiveRecord allow you to create a new object by calling Order.new() (in case we have a table called order and the related class called Order) and save it into the database by calling the method save(). Without calling this method, the object is saved also in your local memory. To convert the object in a row into the database, ActiveRecord constructor accept a hash of values when each of them corresponds to an attribute of the table. This algorithm is useful when the values came from an HTML form. With the save() method, ActiveRecord give you the create() method by which you can create and save automatically the object into database.
Read ActiveRecord, obviously allow you to read rows from the database. This operation is made possible by the find() method overall, that allows you to find a specific row taking its primary key. This method, return finally an object containing data for the corresponding row. Often, though, you need to read the rows by some more elaborate criteria, other than the primary key. For this reason ActiveRecord implements some other option for performing this kind of query, for example you can introduce some symbols as :all or :first as the first parameter, that allow you to read, respectively, all the rows in the table and only the first row that respect your conditions. Extending the find() method you can see how it is structured: find(:all, :condition =>). Other options provided by ActionRecord that can be useful are: ●
:order, which specifies the criteria that in SQL language is known as order by
●
:limit, that limits the number or rows returned by find()
●
:joins, that works in the same way of the classical SQL join, and using the convention in generatig primary key, this method becomes very interesting and faster because developers can avoid reading which is the correct foreign key, using the Rails convention
But the find() method is not the only method you have to find some rows into the database. ActionRecord provides some methods that are based on attribute that are stored into a table, for creating dynamic finders. So, for example, if you have the table user with name and email attributes, ActionRecord allows you some dynamic methods like Order.find_by_name(), and find_by_email(). Another powerful method is called find_by_sql(), which allows the developers to create a query in the classical way. It takes a single parameter containing an SQL select statement and returns an array of model objects from the result set. You can determine the attributes available in a model object using the attributes(), attribute_name() and attribute_present?() methods.
Update To update a row into a database you can use the same method for save an object, that's the save() method. ActionRecord, finally match it with an existing row (if it doesn't exists a new row is created) and update this one. A column will be updated in the database even if its value has not changed. In addition, ActionRecord allows developers to update rows in a single call, using useful method, that's: ●
update_attribute(), allows developers to update a specific attribute. The object that contains this attribute must be find before. For example: order = Order.find(123) order.update_attribute(:name, “ale”)
●
update(), takes an id parameter and a set of attributes. It matches the object related by this id and updates its attributes. For example: order = Order.update(1, :name =>”ale”, :email =>”alessandro.baffa@gmail.com”)
●
update_all(), allow you to specify the value of an attribute and the classical where clause. For example: result = Product.update_all(“price = 1000”, “title like '%java%'”)
A very interesting process provided by ActionRecord is related to the management of multiple access to the same database. It is called “Optimistic locking”. Basically, to avoid that a single row can be updated in the same moment, and the first person who updated this value lose his change, in a case of a simultaneous changing, Rails provide each single row with a version number. Whenever this row is updated, this number is incremented and when you want to change its value, Rails checks your model version number with the number of the table row. If the two numbers don't match, the update is aborted.
Delete ActiveRecord supports four methods for deleting rows into a table. Two methods operate at the database level and are called delete() and delete_all(), that respectively allow you to delete the rows given a particoular id, an array of ids or a given condition. They return tipically the number of rows affected. The other two methods operate at the class level. These are called destroy() and destroy_all(), which delete from the database the row corresponding to a particoular model object given a particoular id or a condition. Neither method return anything. An important feature we can take into account is that ActionRecord is possible to be used as part of a non-Web application. So, in conclusion, the developers have an instrument which make their life easier also in the phase of database management. ActionRecord allows you to have an ORM
technology embeded into the framework, that gives you the possibility to manage data in an object oriented way without any configuration file and without forcing you to change the programming language, giving you a set of methods already embeded into your model objects.
1.6 Action Controller The controller is the real heart of this framework. The ActionController provides support for the management of incoming requests from the client. It's important to underline that these three parts of Ruby on Rails are knit togheter by the Rails system, which gives you an environment for a coherent and easy use of the framework. A have already explained the architecture of Rails in the first paragraph and the flow of an incoming request, but now is time to observe more in detail this operation. Rails encodes the incoming URL and uses a subsystem called routing for determine what have be done with the request parameters. This operation is split in four parts, that can be summarized by the following: â&#x153;&#x201D;
once the controller is identified, a new istance of this object is created by its process() method
â&#x153;&#x201D;
the controller than call the method with the same name of the URL parameter
â&#x153;&#x201D;
if the action method returns a note for render the view to the client, this one is processed by the controller, if not the controller force a template named after action.
The request process is interesting in Rails. When you create a scaffold for your application (with the command rails), the system generates a set of configuration files automatically. The most important among them is the config/routes.rb which contains the rules for routing the incoming request ActionController::Routing::Routes.draw do |map| map.connect ':controller/service.wsdl', :action => 'wsdl' map.connct ':controller/:action/:id' end The code above shows the object that manage this routing process. The Routing component draws a map for connect the incoming URL with the internal addresses, and if you remember the classical URL pattern of Rails (for the example in the first paragraph I used http://my.url/store/add_to_cart/123) you can observe that the second map.connect is exactly the general pattern of it. Obviously, the framework gives you the possibility to insert your own rules and, for example, if you have a blog and you want to reach a post just insert the data in the URL, you can create a pattern like this:
map.connect “blog/:year/:month/:day”, :controller => “blog”, :action => “show_post”, :requirements => { :year => /(19|20)\d\d/, :month => /[01]?|d/, :day => /[0-3]?\d/ } This routing process is not the only support that Rails provides for manage incoming requests. Another method is called url_for( ) that allows application to create URLs that refer back to itself, in case, for example, of a page that contains a form that needs to link back to a controller and action. The problem which this method want to solve is that the application doesn't know the format of the URL that encode this information, in fact what it sees are the parameters it receives once routing has done its work. The url_for() maps the parameters into a request that is compatible with own rules (in map.connect, in case you made your personal one) and it generates automatically a valid URL which is referred to the right controller and action. The controller has also the task to give a response to the user. It can return a template to the browser, a string directly or some other data (for example a pdf document..). The method used for this operation is the render() method and the controller checks if it is called just before it finishes handling a request. The most common way to render a template is look into the app/views directory in which, automatically, Rails insert the template files named as the action of a controller. So, for example, if we have a controller like this class RecipeController < ApplicationController scaffold :recipe def list @recipes = Recipe.find_all end def edit @recipe = Recipe.find(@params["id"]) @categories = Category.find_all end end Rails insert into the app/views/recipe (the name of controller in lowercase) two files named list.rhtml and edit.rhtml.
1.7 Action View The third part of an MVC framework is the view. Likely the other frameworks, this part is called from the controller, it can render the data contained in the model objects and it has the responsability to render the final report to the client. But Rails has a different way to manage this operation than the other frameworks do. As I already said before in this report, also the view uses the power of “conventions
over configuratios”. The render() method, that I already mentioned, try to find templates in the app/views directory by default, and these templates are named like actions methods of controllers. As you saw in the previous paragraph, if there are method called list and edit into the RecipeController code, Rails automatically try to find templates also called list.rhtml and edit.rhtml. Template are a mixture of code and text, and the former is used to add dynamic contents in the template. The view environment allows templates to access to the information set up by controller and in this way the view and controller can communicate. So the objects as headers, params, request and response are available into the templates by a lot of methods that are implemented by the helper classes (I'll explain this argument next), but not only, in fact the templates can also call the method of current controllers just access to them by the attribute named controller.
Rails support two types of template: ●
rxml, to construct XML response
●
and rhtml, to generate HTML pages with some pieces of Ruby code.
The former is allowed by a freestanding library that let you generate XML. The code below shows and example of a template that uses this library: xml.div(:class => ”productlist”) do xml.timestamp(Time.now) @products.each do |product| xml.product do xml.productname(product.title) xml.price(product.price, :currency => “euro”) end end end and this is the result generated: <div class = “productlist”> <timestamp>28 maggio 2006</timestamp> <product> <productname>Il Codice da Vinci</productname> <price currency=”euro”>12,50</price> </product> </div> The library has taken the name of methods and it converted them to XML tags.
The RHTML templates is a regular HTML file, instead. It can contains some pieces of Ruby language code, but even not. In the latter case, the template is simply sent as it is to the client. But the first one is the most interesting. Templates provide you to add some Ruby code inside by put it into <%= %>, like the most ot us are used to do, but it is powered by the helper classes. An helper is a simple module that contains methods that help developers to write the view code. By default each application uses its own helpers, so if you have a controller named StoreController, Rails automatically assumes that there is a helper module called StoreHelper in the store_helper.rb (that Rails puts in the app/helpers directory). Helper modules provide a set of method that can be useful for designing the output render, and they cover several functionalities for the formatting of data as, for example dates, numbers and text. The methods that, personally, i think are the most interesting among them are those for linkng other pages and resources, the form helpers and the validation helpers. The ActionView::Helpers::AssetTagHelper and ActionView::Helpers:UrlHelper modules contains a number of methods that let you reference resources external to the current template.
Linking other pages and resources The first method is link_to(), which creates an hyperlink to another action in your application: <%= link_to “Add comment”, :action => “add_comment”%>, which first parameter is the text displayed for the link, and the second one is the action of the current controller. You can also insert a third parameter for confirm the click (:confirm) or link to an absolute URL, instead of action. The result is http://my.app/current_controller_name/add_comment. Another one is button_to() method that works the same as link_to(), but generates a button in a self contained form, and image_tag(), for creating <img> tags. This one is interesting because Rails assumes that the image linked in the method lives under the /images directory, and its extension is .png, by default.
Form helpers The form helpers is interesting because demonstrate how components interoperate to support creating and editing information in the database. The figure below shows this operation:
The attributes in the model pass through the controller to the view, on the HTML page, and back again into the model. The model object has attributes such as name, country and password. The template uses helper methods to construct an HTML form to let the user edit the data in the model. Note how the form fields are named. The country attribute, for example, is mapped to an HTML input field with the name user[country]. When the user submits the form, the raw POST data is sent back to our application. Rails extracts the fields from the form and constructs the params hash. Simple values (such as the id field, extracted by routing from the form action) are stored as scalars in the hash. But, if a parameter name has brackets in it, Rails assumes that it is part of more structured data and constructs a hash to hold the
values. Inside this hash, the string inside the brackets is used as the key. This process can repeat if a parameter name has multiple sets of brackets in it. Helpers provide also some methods that can help the developers to write the code of the form, which later will be parsed for generating the HTML code, as form_tag() and end_form_tag().
Validation helpers The helper object we've seen all know about Active Record models. They can extract data from they need from the attributes of model object, and they name their parameter in such a way that models can extract them from the request parameters. But the helper objects can interact with model in another interesting way, in fact they also are aware to the validation of the attributes. When constructing the HTML form for each field on the model, the helpers methods invoke that model's error.on(field) method. If any errors are returned, the generated HTML will be wrapped in <div> tag with class=”fieldWithErrors”, and if you want to display the text of error messages ActionView provides the error_message_on() method that returns the error text associated with a particoular field.
There are three types of templates in Ruby on Rails. The main idea behind this choice is that a web site may has lots of duplication: ●
many pages share the same tops, tails and sidebars
●
multiple pages may contain the same snippets of rendered HTML
●
the same functionality may appear in multiple places. Many sites have a standard search component or a polling component, that appears in most of the sites' sidebar
Rails has layouts, partials and components that reduce the need for duplication in these three situations. Layouts allow you to render pages that are nested inside other rendered pages. This feature is used to put the content of an action into the content of a page frame. Starting from a controller named StoreController, Rails try to find a layout called store_layout.rhtml in the app/views/layouts directory and it inserts the action specific output into the HTML produced by this layout into the template. The partial page templates eliminate the duplication of snippets of code between the different template pages. For example a shopping cart might display an order line item on the shopping cart page and again on the order summary page. Instead of repeat the same code for rendering this information in both the page templates, the partial templates solve this problem. A partial page template is a one that you can invoke one or more times from another template, passing it the object you want to render. Then it return the control to the calling template. The convention used by Rails is that the partial templates are named starting with underscore and are positioned in the app/views directory. Not only the view templates can use the partial page template, but also the controller and this feature is very important in the use of AJAX support to update just part of a page from the controller.
Components let us call actions from within a view or another action. The logic of the action will be execute, and its results rendered. These results can be inserted into the output of the current action. This allow us to share both the view and part of the logic behind that view.
1.8 Rails vs Jakarta Struts So far, I have only described the main features of Ruby on Rails framework. I said that it's MVC based and it has some innovations that make this framework more flexible than the others MVC based too. But why a developer should choose this framework rather than another one? For having a more complete overview of this new technology, it can be useful to have a comparison between this one and the most famouse framework, that's Struts, the J2EE framework. In the introduction of this report I wrote â&#x20AC;&#x153;Rails is a full-stack, open-source Web framework in Ruby for writing real-world applications with joy and less code than most frameworks spend doing XML sit-upsâ&#x20AC;?. The first part of the sentence, that can be found on the homepage of Rails project, declares Ruby on Rails as a stack, and it's really so.
As you can see, are both structured basically in the same way: there's a container in which the code will execute, an MVC layer that separates the application in model, controller and view and a mechanism to persist data.
Front controller One difference is between the front controllers, but these are different only in the mechanism for determine which action execute for a specific request. Both the front controllers are responsable to receive the incoming requests and manage them, parsing the URLs for taking the util parameters and than execute the correct action (that in Struts extend the Action class and in Rails extend ActionController). With Struts however, you have to declare the action class in an external configuration file (struts-config.xml) and then the container, once started, load the instance of ActionServlet class, parse this file and wait incoming requests. By convention the request that end in .do are referred to the ActionServlet that mapping the request to the configuration file to find the correct action.
Rails instead, hasn't any kind of configuration files for dispatch the appropriate action. It parse directly the structure of URL that indicates which of the controller load and which of its method use (the explanation of this process has been treated before in this report).
The action and the model In both Rails and Struts, the action acts as a bridge between the front controller and the model. The developer provides an implementation of an action in order to provide application-specific processing of a request. The front controller is responsible for accepting the request and passing it off to a specific action.
An action with Struts forces developers to extend Action class and override the execute() method, passing in it a number of useful objects as HttpServletRequest, HttpServletResponse, ActionMapping and ActionForm. Generally an action provides a unit of work, and the image shows three operations that have to be treated by three different actions. Then the execute() return an ActionForward object that the ActionServlet uses to find which are the other components of the application that continue to manage the request (generally this is a JSP page, but it can be another action). An important thing to keep in mind when a developer is writing code of an action with Struts is that the framework create only one istance of the class. So he has to takes care the case of multithread that invoke execute() method. In this way, Struts allows to manage faster the request process, but developers have to take into account some attentions for security because the variable are visible to multiple
threads. Rails does in different way. You have to extend the ActionController::Base class, but It doesn't create only one instance of this, it creates a new instance for each request. This has negative impact on the performance, but it solves the problem of multithread and you can have all the parameters like session, request and header accessible as instance member of ActionController. This class is also the logical place for the logic as delete(), list() and save() (as you can see in the figure below). Rails then, differently form Struts, doesn't use an object to redirect the process to the view component or another action (ActionMapping), but uses the redirect_to() method to invoke another action (I exposed how before in this report).
The persistence framework Both Hibernate and ActiveRecord are classified as object-relational mapping tools.
The imagine above show the structures of frameworks. Hibernate is based on the Data Mapper pattern, where a specific mapper class, the Session, is responsible for persisting and retrieving data to and from the database. Hibernate can persist any Java object as long as it conforms to JavaBean specifications. XML mapping files describe how a class maps to a particular table in the database, along with any relationships that the class has with other classes. The code below shows an example of an Hibernate mapping file. The class tag maps the Order object to the ORDERS table and has a number of sub tags that describe its properties, the ID and the order name, and a one-to-many relationship to models.Item. <hibernate-mapping> <class name="models.Order" table="ORDERS" dynamic-update="true" dynamic-insert="false" discriminator-value="null"> <id name="id" column="id" type="java.lang.Long" unsaved-value="null">
<generator class="identity"/> </id> <set name="items" lazy="false" inverse="false" cascade="none" sort="unsorted"> <key column="id"/> <one-to-many class="models.Item"/> </set> <property name="name" type="java.lang.String" update="true" insert="true" access="property" column="name"/> </class> </hibernate-mapping> Rails' ORM (Active Record) doesn't require a mapping file, as Hibernate does; in fact, a developer working with Active Record doesn't need to code getters or setters, or even the properties of the class, in fact it provides the so called CRUD operations automatically (Create – Read – Update – Delete). Through some nifty lexical analysis, Active Record is able to determine that the Order class will map to the ORDERS table in the database. The columns of the table become properties of the object. Accessors and mutators are also added. The code belows shows an example of an object using ActiveRecord: class Order < ActiveRecord::Base has_many :items end the second line is referred to the relationship that Rails makes automatically between ORDERS table and ITEMS table. It is possible with another of naming convention of ActiveRecords that uses :item as parameter and then uses it to discover the Item object that is referred to the ITEMS table into the database.
1.9 Benefits My personal opinions about Ruby on Rails start from the definition that Wikipedia gives about what is a framework: “(...)a framework is a defined support structure in which another software project can be organized and developed. A framework may include support programs, code libraries, a scripting language, or other software to help develop and glue together the different components of a software project. Frameworks are designed with the intent of facilitating software development, by allowing designers and programmers to spend more time on meeting software requirements rather than dealing with the more tedious low level details of providing a working system.(...)”. Analysing this definition I can certainly say that Ruby on Rails is a really good framework, in all the possible sense. It includes programs (Rails system), code libraries (XML rendering, Javascript library, etc..) and scripting language that really help to develop and organize a project, allowing the developers to focus on the solutions of the problem instead of spend a lot of time with low level technical problems. The most innovation of this framework is undoubtedly the use of conventions, that creates a very efficient environment in which an application can be considered as a whole. The naming convention of variables, but overall of the database tables and objects (which are related to) is the most useful trick that I saw in RoR; it facilitates the output design of the view, it makes more intuitive the information flow and the writing of logic code in the objects, but overall it lets developers to not consider the configuration files that are the most tedious thing that a developer have to do with a framework. The naming convention is the real glue of this framework and it is powered with the huge number of instruments that Ruby on Rail gives available. ✔
The scaffold, automatically generated in a very intelligent way, provides to developers a structured and more intuitive environment
✔
The Ruby language, by which the framework is written, is very easy to learn and it seems agile
✔
The Action Record, the object-relational mapping (ORM) included in Rails, is very efficient and the power of naming convention makes very easy to create complex queries and manage a huge quantity of data stored into the database. The CRUD support and the integration with the Ruby language (for calling these methods) is very useful
✔
The helper modules add a set of methods that integrates the Ruby language with all the possible support embeded into the framework, like CRUD, Javascript, HTML and XML. It is useful because the developers will not have to switch the language for some operations, but they can use Ruby in all the work.
Another interesting and useful thing is at the action level. As we have saw in the previuos paragraph, in which I compared Struts and Rails, the ActionClass in Struts
can process one operation only, while in Rails an ActionController can process more operations allowing the developers to include their code inside the controller, instead of write another ActionClass extending Action. The flexibility at last, gives you the possibility to implement your own rules in all level of the scaffold, allowing you to not be forced to follow the conventions implemented by Rails.
1.10 Drawbacks In spite of the large number of benefits, that are very interesting at the conceptual level, Ruby on Rails shows some technical drawbacks which induce some people to think that this framework isn't so a due instrument for big applications yet. I could say that the first criticism is that the Ruby language is still a niche product, but I also think that the easiness with which it can be learned is a point that has to be taken in account. I want to focus on some techniques that can generate some problems, instead. Comparing Struts with Ruby on Rails I realized that the feature of the latter to be flexible can be considerated more a disvantage. Struts is quite tedious to implement and set up, but it can provides a scaffold that is standard and, in case of subsequent maintenance, the developers may have some facilities. On my point of view this possibility allowed to the developers, that let them to decide if follow the Rails' rules or not, demonstrates that the concept of â&#x20AC;&#x153;convention over configurationâ&#x20AC;? isn't really a due technique which can be applied to big projects. The risk behind this choice is that the quantity of logic and objects in the application, that could become very huge with the growing of the requirement analysis and time, without the support of a very structured environment can causes a lot of risks, first of all the failure of the project. The possibility of using some naming conventions could be very useful in writing the code, and it is the most fascinating feature in Ruby on Rails, but it can be the reason of the failure itself, and it is certainly the main reason because this framework can't be used in some big project, as for example the legacy system in which you can't use this conventions of names in the table of database. Again, the naming convention hasn't also a structured way to work: there are some changes between naming of variables that are so thin that, on my point of view, will be very hard to scan during the development and are very hard to remind (I'm thinking to the view layout which name have to start with an underscore before the action name) . The convention of plural names of the tables into the database and the subsequent names of objects model is too tricky. Another point that is important to underline is the scalability. The feature to create so many instances as the number of request for the ActionController is a very negative feature. The official justification is that it was most important to solve the problem of management the simultaneous incoming request, and in this way this problem is really solved, in fact multiple simultaneous requests can't access to the local variable of another client, anyway. But they have forgot the problem of scalability: it can be reasonable to create so many instances for each incoming request, it can costs too many resources. In my point of view is more reasonable to have some configuration files to solve the problem of security or multithread.
There arent' a lot of problem, as you can see. In general Ruby on Rails introduces some innovations that should be used also in the other frameworks, because it embodies a real framework that helps developers to build projects in a very confortable way.
2.AJAX: Asynchronous Javascript and XML 1.11 Architecture We are all familiar with web pages which operate in the following way: 2 you enter a URL, click “GO” and wait for the page load 3 submit data in a form fields, click “Submit” button and wait for the page refresh This way to do is the classical model that has been since the early days of Internet: a client submits some data to a server, it computes these incoming data with its methods and sends back to the client the page reloaded with the new informations. We are familiar with this model and we also know that between the event of sending data to the server and the page reloading, we can't do anything. We just have to wait. But not only. In the most common cases, this reload is very slow and involves truly little data meaning that the server is forced to send more data than is necessary. The figure below shows a tipical web application: AJAX (Asynchronous Javascript and XML) allows you to navigate web pages while the page itself sends data to the server, without waiting for a new page or a page refresh. The figure below shows the difference between a classical web application and another using Ajax:
Ajax isn't a technology, but instead a collection of technologies as Javascript, CSS (Cascading Style Sheet), XMLHTTPRequest and DOM (Document Object Model), but Javascript is really the glue that knitts all these component togheter, defining the user workflow and the business logic of the application. The user interface is manipulated by Javascript that continually refreshes the informations into the web page manipulating the Document Object Model, the Cascading Style Sheet offer the correct look and feel for this manipulation and the XmlHttpRequest object sends request to the server asynchronously while the user works.
As you can see in the figure above, Ajax is a sort of layer that is positioned between the Web browser of client and the Web server. When the client send data from the web page, these are not send directly to the server, but to the Ajax engine that can decide if to send this requests to the server or manage them by itself, in fact Ajax will have forseen the user's requirements and will already have the information requested. Basically, the principles on which Ajax is based are the following: 5. the browser hosts an application, not content. When the user logs in or initializes a session, several server-side objects are created, representing, for example, the shopping cart and the customer credentials if this is an ecommerce site. At the same time, the home page is dished up to the browser, in a stream of HTML markup that mixes together standard presentation and user-specific data and content such as a list of recently viewed items. Every time the user interacts with the site, another document is sent to the browser, containing the same mixture of presentation and data. The browser throws the old document away and displays the new one. When the user hits the logout link or closes the browser, the application exits and the session is destroyed. Any information that the user needs to see the next time he logs on will have been handed to the persistence tier by now. An Ajax application moves some of the application logic to the browser. When the user logs in, a more complex document is delivered to the browser, a large proportion of which is JavaScript code. This document will stay with the user throughout the session, although it
will probably alter its appearance consid-erably while the user is interacting with it. It knows how to respond to user input and is able to decide whether to handle the user input itself or to pass a request on to the web server (which has access to the system database and other resources), or to do a combination of both. Because the document persists over the entire user session, it can store state. A shopping basketâ&#x20AC;&#x2122;s contents may be stored in the browser, for example, rather than in the server session. The figure below shows a lifecycle of a classic web application:
While the following shows an Ajax based web application:
6. The server delivers data, not content. So, the classic web app serves up the same mixture of presentation, content, and data at every step. When the user adds an item to a shopping case, all that he really needs to know is the updated price of the basket or whether anything went wrong. With Ajax, the presentation, the navigation lists, and other features of the page layout are all there already, so the server needs to send back only the relevant data and it might do this in a number of ways, such as returning a fragment of JavaScript, a stream of plain text, or a small XML document. In an Ajax application, the traffic is heavily front-loaded, with a large and complex client being delivered in a single burst when the user logs in. Subsequent communications with the server are far more efficient, however. For a transient application, the cumulative traffic may be less for a conventional web page application, but as the average length of interaction time increases, the bandwidth cost of the Ajax application becomes less than that of its classic counterpart. The figures below shows this statistics.
The figure A shows the quantity of data that are needed for all the interaction with a classical web application. As you can see, every step requires a lot of data, brand and content.
The figure B shows the quantity of data that are needed for all the interaction with an Ajax based web application, instead. It's impressive the data quantity conservation for every step of navigation, unlikly the classical counterpart.
The figure C shows the increase of cumulative data between a classical web application and another Ajax based. As you can see, both have an increase, but Ajax
permits to have a lower dynamic, and this is important for the server loading.
7. User interaction with the application can be fluid and continuous. A web browser provides two input mechanisms out of the box: hyperlinks and HTML forms, and both point to server side URLs. While the page is submitting, the user is effectively in limbo. The old page may still be visible for a while, and the browser may even allow the user to click on any visible links, but doing so will produce unpredictable results and trouble with the server session. With a hypothetical Ajax shopping cart, which sends data asynchronously, users can drop things into it as fast as they can click. If the cartâ&#x20AC;&#x2122;s client-side code is robust, it will handle this load easily, and the users can get on with what theyâ&#x20AC;&#x2122;re doing. Waiting for a page refresh maybe prohibitive for some other domain and Ajax can help in this manner.
XMLHTTPRequest The main component of Ajax, whose that glues all the component togheter (such as CSS, DOM manipulation and interaction with the server) is the XMLHTTPRequest object. The XMLHTTPRequest object is Javascript's device for communicating with the server in the background, and that's without the necessity of a page load or refresh. It is a nonstandard extension originated as Microsoft-specific ActiveX component that was available as Javascript object in the Internet Explorer browser. Subsequently also the other browsers have implemented this object in similar funcionalities and API calls. The figure below shows a sample of code for creation of a XMLHTTPRequest object:
Well, as you can see the code try to check if the browser supports the native XMLHTTPRequest object or ActiveX. If not, it returns null and the variable state remains so. Otherwise it returns an object that we can use for communicate with the server. But how? It's very straightforward and the code below shows how it is possibile:
All we have to pass in it is the URL of the page that have to compute the data and the parameters. The Http method, as GET or POST, is not mandatory and by default is fixed to POST. There are four properties that are indispensable for creating an Ajax application: ✔
OnReadyStateChange: readyState property
defines
an
handler
that
calling
continually
the
✔
ReadyState: can take four integer values: 0 = uninitialized, 1 = loading, 2 = loaded, 3 = interactive, 4 = complete.
✔
ResponseText, responseXML: are referred to the information returned from the server, in text and XML format respectively.
2.2 Benefits The most benefits that come from Ajax are the reduction of costs and the improvement of user interface. The former includes costs in terms of time spent completing a task, waiting for loading of data and consume of bandwidth. The latter is referred to the familiarity of the interface that allows the users to do operations with more intuitiveness and satisfaction, that from the point of view of usability is very important. The reduce of costs has been studied and a lot of interesting results are now available. The first that I want to point out is the measure of bytes transferred in a classical web application and another Ajax based instead. The figure below shows the result of a case study that was built in USA:
The first row is due to the few amount of data that are sent to the server, in fact it is
called only for the needed data instead of entire page. The second result is referred to the time saved for complete a specific task in a classical web application and another Ajax based. While the third is the time saved for trasmitting data from the East coast to the West coast with a simple 56K modem. But also to business, Ajax gives impressive results and it has calculated taking in account the labor rate, the number of transactions and the time saving for transactions. The results are expressed in dollars and cents, given certain assumption and using basic math. Ajax Cost Savings = Hourly Labor Rate x (Seconds Saved per Transaction x Number of Transactions per year) / 3600 Looking at a conservative potential time savings of 36 seconds per transaction, if a business performs 50,000 of these transactions per year, and a labor cost of $20/hour, we see a total labor savings of $10,000 per year, or 500 man hours, on this transaction type alone. Given predicted time savings of 199.01 seconds per transaction for a remotely hosted application, you see a more aggressive cost reduction of approximately $55,281 per year for this transaction type, or 2,764 man hours. So, as you can see Ajax has a lot of benefits that are really quantifiable in terms of time spending, reduction of cost of bandwidth and money.
2.3 Drawbacks Some drawbacks come from the way in which Ajax fetches data from the server and it is related with the number of requests that Ajax makes to it. In fact every request has fixed overhead and each fetch from the database has fixed costs. RPCs that request small amounts of data generate the highest overhead in these terms. If they were combined to fetch larger blocks of data with fewer requests then the overhead is lower. In this terms some developers think that Ajax is a great tool that works well under low load, but as this load increase, the server may slow down unacceptably due to the extra overhead that are several and for few contents. Another problem comes from the back button of the browser that becomes quite unusable because the changes are only in some parts of the web pages and they are generated automatically, as we have seen, and in invisible manner.
3.AJAX: the Rails Way In the previous chapters of this report I have shown you an overview of Ruby on Rails framework and the AJAX technique, and I explained what are the benefits of both and how they work. These technologies are regarded to be two of the most innovative supports for web applications and their use is getting more and more frequent. Ajax is very useful, as you have seen before, but from the developers point of view its implementation could become quite tiring because of Javascript language, that forces to add some pieces of Java code in the view pages and sometimes it can't be very pleasant to do. So you have to learn another language and add external libraries that make Ajax work properly. Rails simplify your life. It has built-in support for Ajax calls, including some interesting components as a Javascript helper that allow you to avoid learning other languages knitting togheter the Rails' functions with Ajax's. First of all, Ruby on Rails includes the prototype, effects, dragdrop and controls Javascript libraries built-in, which are included automatically when you create your application runnng the rails command. These libraries allow you to use all the useful function of Ajax for DOM manipulation and server requests. The second thing is JavaScriptHelper, a module that wraps the javascript access in Ruby code, allowing you to use the same language when you want to add Ajax functions in your applications.
JavaScriptHelper The JavaScriptHelper modules provide a lot of functionalities that can be grouped in: 4 AJAX calls 5 Document Object Model (DOM) manipulation 6 Visual effects All of them are made possible thanks to the JavaScriptGenerator that is built-in Rails and provide to generate instructions on how to modify an already rendered page. This makes it easy to modify multiple elements on your page in one declarative Ajax response. JavaScriptGenerator generates blocks of Javascript code that allow you to modify the content and presentation of one of multiple DOM elements. There are many helpers in Rails, but the most important are PrototypeHelper and ScriptaculousHelper that provide methods for controlling the change of contents, manipulation of DOM element and and visual effects. The former helper provides a set of helpers for calling prototype javascript functions, including the calling to remote methods using Ajax. The functions provided by this helper is focused on the reloading of some pieces into the web page and so manipulate the DOM element which are referred to. The methods included in this helper are numerous, and I want to suggest only some of them. An interesting feature of prototype library is the presence of some constant that you can add into the methods used in your view templates. This constant are
divided into two groups: CALLBACKS and AJAX_OPTIONS. But above all the callbacks are more interesting. These automatically have access to a Javascript variable called request, which contains the corresponding XMLHTTPRequest object. These callbacks have access to the four states of ReadyState property included in XMLHTTPRequest object, that we have seen in the previous chapter about AJAX: 4 :uninitialized(), is the counterpart in Rails of the state 0 in XMLHTTPRequest object. 5 :loading(), is the counterpart in Rails of the state 1 in XMLHTTPRequest object and it is invoked when the XMLHTTPRequest starts sending data to the server. 6 :loaded(), is the counterpart in Rails of the state 2 in XMLHTTPRequest object and it is invoked when all the data has been sent to the server, and then XMLHTTPRequest waits for the server response 7 :interactive(), is the counterpart in Rails of the state 3 in XMLHTTPRequest object this event is triggered when data start to come back from the server 8 :complete(), is the counterpart in Rails of the state 4 in XMLHTTPRequest and it is invoked when all data from the server are received. 9 :failure() 10 :success() The methods shown above are the most important during Ajax operations, and for this reason the PrototypeHelper is the most important and it has to be included always when you want to use Ajax, and also the other helpers have to extend this one. Prototype allows to send request for the server from a view page, calling some javascript functions from the HTML code, in most of common cases from the tag <href> or a button submit in a form. The helper lets you make a basic Ajax call simplier, as this code shows you: <%= link_to_remote(“Do the AJAX things”, :update = > 'mydiv' :url => { :action => :say_hello })%>
<div id=”mydiv”>This text will be changed</div> The link_to_remote() method takes three parameters: ✔
the text for the link
✔
the id of the element in your page that will be changed
✔
the URL of the action to call
The code above is added into the .rhtml template, and it sends a request to the action in the server. The code of the action is very simple and is shown below: def say_hello render(:layout => false) end
As we have seen in the first chapter of this report, Rails assumes that for every action there's a layout named in the same way, and so if we create a layout called say_hello.rhtml with this line of code <em>Hello from AJAX!!</em>
the text in the “mydiv” element in our view page, will be changed with this element. Basically, what happens during this operation is that link_to_remote() method
generates the subsequent HTML code: <a href=”#” onclick=“new Ajax.Updater('mydiv', {asynchronous:true}); return false;”> Do the AJAX thing </a>
'/example/say_hello',
This method generates an HTML tag which generates a new instance of Ajax.Updater, a function declared in the Prototype library. This instance calls XMLHTTPRequest internally, which generates a request to the action given in the second parameter. By default these remote requests are processed asynchronous during which various Javascript callbacks can be triggered (for progress indicator, for example). To access the server response, you can use request.responseText, and to find out the HTTP status you can use request.status. You can customize your Javascript code by adding some optional parameters, as: ✔
:confirm, add confirmation dialog
✔
:condition, perform the condition when request should not be initiated
and so on. The observe_field(field_id, options = {}) method observes the field with the DOM id specified by field_id and makes an Ajax call when its content have changed. The option required by this method are: ✔
:url, the url of action to call when the content change
✔
:function, instead of making a remote call to a Url, you can call a javascript function
Additional option can be: ✔
:frequency, (in second) at which changes to this field will be detected.
✔
:update, specifies the DOM id of the element whose innerHTML should be updated with the XMLHTTPRequest response text.
Another important support gave not only by Prototype, but also Scriptaculous is related to the Document Object Model (DOM) manipulation. They deliver handly shortcut for a number of often used operations, which are intended to be invoked from within the pages delivered to the browser. The former helper provide methods as: ✔
Element.show(id), shows hidden DOM element with the given id
✔
Element.remove(id), removes the DOM elements with the given id from the page
✔
Element.hide(id), hides the visible DOM element with the given id
and so on. While Scriptaculous helper gives more sofisticated effects, as: ✔
sortable_element(element_id, option = {}), makes the element with the given id sortable by drag-and-drop and make an Ajax call whenever any sort order is changed.
✔
draggable_element(element_id, options = {}), makes the DOM element draggable
The last important support is for the visual effect, that are the most fascinating thing of Ajax, maybe. Because of Ajax works in the background, the browser doesn't even indicate that a page is loading, and the user are driven to click over and over the button. We need to let the user know visually that something is happening, and this is tipically a two step process. First we can use various DOM manipulation techniques to do things into the browser that reflected what is happened to the server, but for second we should to provide feedback that the change has been made and let the user to undestand that his action really took place. The JavaScriptGenerator let to call also the other Javascript libraries for the visual effect as, for example, effects.js, another own Javascript library already built-in Ruby on Rails, that provides two types of effects: one shot effects and repeatedly callable effects. The former are used to convey a clear message to the user. All these effects take one parameter, that's the element on the page. Some examples can be Effect.Appear(element) that changes the opacity of the given element smoothly from 0% to 100%, or Effect.Puff(element) that creates the illusion that the element disappeares in a gently expanding cloud of smoke, and so on. The latter are referred to resizing the elements on the page, and functions as Effect.Scale(element, percent) that smoothly scales the given element, Element.setContentZoom(element, percent) that provides a nonanimated way to set the scale of text and other element that use em units, can be exhaustives. So, basically the Ajax calls are all managed by Rails in this manner. The Javascript Helper gives a lot of functions that wrap access to Ajax into the Ruby code, and every functions have a lot of callbacks and options that can manage the properties of XMLHTTPRequest object. The developers, using the Ruby language, are allowed to use these functions on the server side, and automatically a Javascript code is generated client side because of the JavascriptGenerator functionalities, which decodes the Ruby code in Javascript. When the user clicks on the link generated, as the previous example code, he's actually using the Javascript objects contained in the Prototype , Scriptaculous or the other libraries.
Benefits This kind of management of Ajax calls is very interesting and intelligent, from my point of view. The developers are not so forced to write a lot of cumbersome lines of Javascript code, but they can use always the same language, and in an easy way. Rails adds the libraries automatically by the creation of the application and the JavascriptHelper gives a huge number of functions that can be wraps simply and automatically to access Javascript and the XMLHTTPRequest object properties, which in this way, maybe, is not managed directly from the developers, but from the framework. All the functions contained in the Javascript libraries, as Prototype or effects, can be modified by the developers and there arent' any kind of mandatories.