- XML Reference Guide
- Overview
- What Is XML?
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Table of Contents
- The Document Object Model
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- DOM and Java
- Informit Articles and Sample Chapters
- Books and e-Books
- Implementations
- DOM and JavaScript
- Using a Repeater
- Repeaters and XML
- Repeater Resources
- DOM and .NET
- Informit Articles and Sample Chapters
- Books and e-Books
- Documentation and Downloads
- DOM and C++
- DOM and C++ Resources
- DOM and Perl
- DOM and Perl Resources
- DOM and PHP
- DOM and PHP Resources
- DOM Level 3
- DOM Level 3 Core
- DOM Level 3 Load and Save
- DOM Level 3 XPath
- DOM Level 3 Validation
- Informit Articles and Sample Chapters
- Books and e-Books
- Documentation and Implementations
- The Simple API for XML (SAX)
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- SAX and Java
- Informit Articles and Sample Chapters
- Books and e-Books
- SAX and .NET
- Informit Articles and Sample Chapters
- SAX and Perl
- SAX and Perl Resources
- SAX and PHP
- SAX and PHP Resources
- Validation
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Document Type Definitions (DTDs)
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- XML Schemas
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- RELAX NG
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Schematron
- Official Documentation and Implementations
- Validation in Applications
- Informit Articles and Sample Chapters
- Books and e-Books
- XSL Transformations (XSLT)
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- XSLT in Java
- Java in XSLT Resources
- XSLT and RSS in .NET
- XSLT and RSS in .NET Resources
- XSL-FO
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- XPath
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- XML Base
- Informit Articles and Sample Chapters
- Official Documentation
- XHTML
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- XHTML 2.0
- Documentation
- Cascading Style Sheets
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- XUL
- XUL References
- XML Events
- XML Events Resources
- XML Data Binding
- Informit Articles and Sample Chapters
- Books and e-Books
- Specifications
- Implementations
- XML and Databases
- Informit Articles and Sample Chapters
- Books and e-Books
- Online Resources
- Official Documentation
- SQL Server and FOR XML
- Informit Articles and Sample Chapters
- Books and e-Books
- Documentation and Implementations
- Service Oriented Architecture
- Web Services
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Creating a Perl Web Service Client
- SOAP::Lite
- Amazon Web Services
- Creating the Movable Type Plug-in
- Perl, Amazon, and Movable Type Resources
- Apache Axis2
- REST
- REST Resources
- SOAP
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- SOAP and Java
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- WSDL
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- UDDI
- UDDI Resources
- XML-RPC
- XML-RPC in PHP
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Ajax
- Asynchronous Javascript
- Client-side XSLT
- SAJAX and PHP
- Ajax Resources
- JSON
- Ruby on Rails
- Creating Objects
- Ruby Basics: Arrays and Other Sundry Bits
- Ruby Basics: Iterators and Persistence
- Starting on the Rails
- Rails and Databases
- Rails: Ajax and Partials
- Rails Resources
- Web Services Security
- Web Services Security Resources
- SAML
- Informit Articles and Sample Chapters
- Books and e-Books
- Specification and Implementation
- XML Digital Signatures
- XML Digital Signatures Resources
- XML Key Management Services
- Resources for XML Key Management Services
- Internationalization
- Resources
- Grid Computing
- Grid Resources
- Web Services Resource Framework
- Web Services Resource Framework Resources
- WS-Addressing
- WS-Addressing Resources
- WS-Notifications
- New Languages: XML in Use
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Google Web Toolkit
- GWT Basic Interactivity
- Google Sitemaps
- Google Sitemaps Resources
- Accessibility
- Web Accessibility
- XML Accessibility
- Accessibility Resources
- The Semantic Web
- Defining a New Ontology
- OWL: Web Ontology Language
- Semantic Web Resources
- Google Base
- Microformats
- StructuredBlogging
- Live Clipboard
- WML
- XHTML-MP
- WML Resources
- Google Web Services
- Google Web Services API
- Google Web Services Resources
- The Yahoo! Web Services Interface
- Yahoo! Web Services and PHP
- Yahoo! Web Services Resources
- eBay REST API
- WordML
- WordML Part 2: Lists
- WordML Part 3: Tables
- WordML Resources
- DocBook
- Articles
- Books and e-Books
- Official Documentation and Implementations
- XML Query
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- XForms
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Resource Description Framework (RDF)
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Topic Maps
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation, Implementations, and Other Resources
- Rich Site Summary (RSS)
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Simple Sharing Extensions (SSE)
- Atom
- Podcasting
- Podcasting Resources
- Scalable Vector Graphics (SVG)
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- OPML
- OPML Resources
- Summary
- Projects
- JavaScript TimeTracker: JSON and PHP
- The Javascript Timetracker
- Refactoring to Javascript Objects
- Creating the Yahoo! Widget
- Web Mashup
- Google Maps
- Indeed Mashup
- Mashup Part 3: Putting It All Together
- Additional Resources
- Frequently Asked Questions About XML
- What's XML, and why should I use it?
- What's a well-formed document?
- What's the difference between XML and HTML?
- What's the difference between HTML and XHTML?
- Can I use XML in a browser?
- Should I use elements or attributes for my document?
- What's a namespace?
- Where can I get an XML parser?
- What's the difference between a well-formed document and a valid document?
- What's a validating parser?
- Should I use DOM or SAX for my application?
- How can I stop a SAX parser before it has parsed the entire document?
- 2005 Predictions
- 2006 Predictions
- Nick's Book Picks
At this point we've got the very basics of a working Rails application, and using the scaffolding we can make changes to the database. Now we're going to look at taking control of that process. We'll start by editing an existing question, and then we'll move on to adding and deleting questions.
When we last left our application, the "edit" action was being handled by the scaffolding. To change that, start by creating a template that references the specific question we want to edit:
<html> <head> <title>Questions, questions questions</title> </head> <body> <h2>Edit a question</h2> The existing question is "<%= @thisQuestion.questionText %>" </body> </html>
As before, if we access this page, we have a problem:
The problem lies in the fact that we haven't provided a specific object
from which we want the questionText
attribute.
To solve the problem, create the edit
action in the
Questions controller, question_controller.rb
:
class QuestionController < ApplicationController model :question scaffold :question def index end def list @questions = Question.find_all end def edit @thisQuestion = Question.find(@params["id"]) end end
As you may remember, the URL includes the id
of the
question we're working with. As such, we can extract it from the
params
array. (We'll look at this array in detail in the moment,
but for now just take it on faith that the id
value is in it.)
The find
method expects to receive the ID of the object you're looking for
in any model, whether it's the Question, Survey, or Answer. It's just the
way that Rails has been designed; models automatically have the
find
method, which takes the id of the particular object, goes to the database,
and populates an object with the data it finds for that row.
(To digress for a moment, you can also find a group of objects,
which are passed as an array, using the find_all
method.
With no arguments, this method finds all records. You also have the
option of providing a filter, such as "id > 25" or "status = 'finished'"
to limit the records you get back.)
Once we find it, we assign it to the thisQuestion
variable,
which gets passed to the template:
So now we have the correct question, so let's build an editing form around it in the "edit" template:
<html> <head> <title>Questions, questions questions</title> </head> <body> <h2>Edit a question</h2> <form method="post" action="/question/editExistingQuestion/<%= @thisQuestion.id %>"> Edit the question: <br /> <%= text_field("theExistingQuestion", "questionText", "value" => @thisQuestion.questionText) %> <br /> <input type="submit" value="Save Question"> </form> </body> </html>
OK, let's start at the top, with the form
element.
If you're familiar with HTML, you know that the action
attribute represents the URL to which the data will be sent. In Rails,
this means we want the URL that looks something like this:
http://localhost:3000/question/editExistingQuestion/12
In this case, the we're dealing with a question
object, for which we want to perform the editExistingQuestion
action, on the object with an id of 12
. To replicate that
in the action
attribute, we construct the tag dynamically,
asking Rails to add the id for the current object.
Next we have the text_field
method, which takes the following
arguments. First, the name of an array to which the data will belong.
This will make more sense in a moment, when we see the actual data.
Second, we have the name of the actual piece of data. This name should match
the attribute name for the object, so Rails knows what to do with it.
Finally, we have an optional HTML option that allows us to add an arbitrary
attribute and value. When you have Rails render the page, either by
entering the URL manually, or clicking on a "Change" link, it creates the
actual form for you:
<html> <head> <title>Questions, questions questions</title> </head> <body> <h2>Edit a question</h2> <form method="post" action="/question/editExistingQuestion/12"> Edit the question: <br /> <input id="theExistingQuestion_questionText" name="theExistingQuestion[questionText]" size="30" type="text" value="What is your name?" /> <br /> <input type="submit" value="Save Question"> </form> </body> </html>
Notice that Rails has taken care of housekeeping issues such as
creating the actual input
element and adding the appropriate
attributes. Notice also that the name
element hints that we are
actually dealing with an array. The page itself looks perfectly normal:
Okay, so let's see what happens if we submit the form. First we need to create an action in the controller:
... def edit @thisQuestion = Question.find(@params["id"]) end def editExistingQuestion render_text @params.inspect end end
In this case, we are simply telling Rails to print out a representation of the parameters that are being submitted with the request so that we can see them. If we then go ahead and submit the form, we should see something like this:
{"action"=>"editExistingQuestion", "theExistingQuestion"=>{"id"=>"12", "questionText"=>"What is your name?"}, "controller"=>"question"}
Notice that the parameters are actually an array that has as one of its members
(specifically, the theExistingQuestion
member) another array.
Now let's do something with that data:
... def editExistingQuestion thisQuestion = Question.find(@params["id"]) thisQuestion.attributes = @params["theExistingQuestion"] if thisQuestion.save render_text "Question saved. Thank you." else render_text "Sorry, no can do." end end end
First, as before, we're finding the specific object we want to work with.
Once we have it, we can specifically assign the theExistingQuesiton
array to the attributes
array for the object, and everything will
fall into place. That's why we made sure that the name of the field matched
the name of the attribute we wanted to set.
Once we've populated the data, all we have to do to save it to the database.
We can do that with the save
method, which returns true
if the operation is successful. Try it by making a change and submitting the
form:
To see if it worked, click the "back" button twice, and then reload the page if necessary:
Well, it worked, but it wasn't very convenient. Fortunately, we can tell Rails to send us back to the list of questions automatically:
... def editExistingQuestion thisQuestion = Question.find(@params["id"]) thisQuestion.attributes = @params["theExistingQuestion"] if thisQuestion.save redirect_to(:action => "list") else render_text "Sorry, no can do." end end end
You can redirect to any action, such as "new", or even a custom action that you've created.
Adding a new record is just as easy. Start by adding a form to the list template:
<html> <head> <title>Questions, questions questions</title> </head> <body> <h2>Existing questions</h2> <% @questions.each do |@thisQuestion| %> <%= @thisQuestion.questionText %> ( <%= link_to("Change", :action => "edit", :id => @thisQuestion.id) %> ) <br /> <% end %> <br /> <form method="post" action="addNewQuestion"> Add a new question: <%= text_field("newQuestion", "questionText") %> <input type="submit" value="Save Question"> </form> </body> </html>
The principle is the same as editing the record, but because
we don't have a specific object to deal with, we can be a bit more
general in our action
. We'll create the new action
in a moment. The form, meanwhile, is just a
typical form:
Now we just need to save the question when its submitted. Create
the new addNewQuestion
action:
... def editExistingQuestion thisQuestion = Question.find(@params["id"]) thisQuestion.attributes = @params["theExistingQuestion"] if thisQuestion.save redirect_to(:action => "list") else render_text "Sorry, no can do." end end def addNewQuestion thisQuestion = Question.new thisQuestion.attributes = @params["newQuestion"] if thisQuestion.save redirect_to(:action => "list") else render_text "Sorry, no can do." end end end
The process is virtually identical to editing an existing object,
except that instead of populating it by finding a record in the database,
we're using the Question
class to create a new object.
We can then populate it and save it, moving back to the list of existing
questions if all goes well.
So what about deleting existing records? It's also a fairly simple process. Start by creating a "delete" link on the list template:
<html> <head> <title>Questions, questions questions</title> </head> <body> <h2>Existing questions</h2> <% @questions.each do |@thisQuestion| %> <%= @thisQuestion.questionText %> ( <%= link_to("Change", :action => "edit", :id => @thisQuestion.id) %> ) ( <%= link_to("Delete", :action => "destroy", :id => @thisQuestion.id)%> ) <br /> <% end %> <br /> <form method="post" action="addNewQuestion"> Add a new question: <%= text_field("newQuestion", "questionText") %> <input type="submit" value="Save Question"> </form> </body> </html>
The only difference between this link and the previous one is the action to which it takes you. In Rails, to delete an object, you "destroy" it, so we'll keep with that as the action name.
Actually deleting it is a straightforward process:
... if thisQuestion.save redirect_to(:action => "list") else render_text "Sorry, no can do." end end def destroy thisQuestion = Question.find(@params["id"]) if thisQuestion.destroy redirect_to(:action => "list") else render_text "Sorry, no can do." end end end
As in the case of editing the object, we first find the appropriate
one in the database, but from there we use the destroy
method instead of save
.
So that takes care of creating, retrieving, editing, and deleting objects from the database, which is, let's face it, most of what you do in a dynamic web application. With a little tweaking for your own purposes, you should be ready to go.