Chapter 7. Strengthening Models with Validation

At this point, you have most of the ingredients needed to create simple web applications in Rails, provided you’re willing to stick to a single database table. There’s one large problem remaining: users (and programs connecting through web services) don’t always put in the data you want them to put in. Making your application work reliably requires checking information as it comes in and interacting with users so that they know how to get it right.

Warning

As you’ll see throughout this chapter, Rails expects all data validation to happen in the model layer and provides tools that make it easy to do there. If you find yourself putting data-checking code into the views or the controllers, pause for a moment—you’re quite likely doing something wrong.

The one probable exception is if you’re adding warnings for users working in your forms, avoiding a round trip to the server, but you should never rely on those to limit your data to the correct types. All that work should do is give users more information more rapidly.

Without Validation

You might think, since the examples in Chapter 6 defined data types, that Rails will be doing some basic content checking—ensuring that numeric data actually includes numbers, for example.

Nope. Rails and the Rails scaffolding give you places where you can add validation code, but absolutely none of it is built-in. The easiest way to see what happens is to try putting in bad data, as shown in Figure 7-1.

Entering bad data into a form

Figure 7-1. Entering bad data into a form

The text fields might not be the data you want, but at least they’re text. The boolean value and the dates are constrained to a few choices by the interface design already—you can’t choose bad data. However, “thousands,” “twenty-six,” and “not” aren’t numbers. But Rails doesn’t care—it accepts those strings and converts them to a number: 0 (zero), as shown in Figure 7-2.

Nonnumeric data converted to zeros in a “successful” creation

Figure 7-2. Nonnumeric data converted to zeros in a “successful” creation

You can see what happened by looking at the data that scrolled by in the script/server window (or in the logs in Heroku) when the request went in. You don’t need a detailed understanding of SQL to find the problem—looking at the data going in will show it. Example 7-1 lists the data going into the Rails app and then shows the SQL INSERT with the data moving out from the Rails app to the database.

Example 7-1. Behind the scenes for bad data flowing to the application

Processing PeopleController#create (for 127.0.0.1 at 2008-03-08 18:42:04) [POST]
  Session ID:
BAh7ByIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNo%0ASGFzaHsABjoKQHVzZWR7
ADoMY3NyZl9pZCIlNmMxZGE3NDdiMmY3NDQzZWIz%0AZWM1NmQzNDFkZjBhYjM%3D--
ca58de858eb31bb2b1c88e0f1939fe085641c576
  Parameters: {"commit"=>"Create",
"authenticity_token"=>"8a2e7ade080a91f5c872cd8c783d2282576d6117",
"action"=>"create", "controller"=>"people", "person"=>{"name"=>"Sploink",
"birthday(2i)"=>"3", "favorite_time(5i)"=>"54", "birthday(3i)"=>"8",
"favorite_time(6i)"=>"49", "price"=>"not", "country"=>"Canada",
"body_temperature"=>"twenty-six", "description"=>"sdfsdfdsfasdfd",
"graduation_year"=>"thousands", "favorite_time(1i)"=>"2008",
"favorite_time(2i)"=>"3", "secret"=>"", "can_send_email"=>"1",
"favorite_time(3i)"=>"8", "email"=>"sasdas", "birthday(1i)"=>"2008",
"favorite_time(4i)"=>"11"}}
Person Create (0.000524)   INSERT INTO people ("name", "updated_at", "price",
"country", "body_temperature", "description", "birthday", "graduation_year",
"can_send_email", "favorite_time", "secret", "created_at", "email")
VALUES('Sploink', '2008-03-08 18:42:04', 0.0, 'Canada', 0.0, 'sdfsdfdsfasdfd',
'2008-03-08', 0, 't', '2008-03-08 11:54:49', '', '2008-03-08 18:42:04', 'sasdas')
Redirected to http://localhost:3000/people/2
Completed in 0.01586 (63 reqs/sec) | DB: 0.00052 (3%) | 302 Found 
[http://localhost/people]

The parameters are complicated by the many pieces of incoming dates that use a naming convention to identify their parts, but it’s clear that “thousands,” “twenty-six,” and “not” went into the Rails application. In the SQL command going to the database, price and body_temperature went in as 0.0, while graduation_year went in as 0.

Between receiving the data and sending it to the database, Rails converted those values to numbers. The strings became zero (0.0), since they weren’t actually numeric. Fixing this problem will require spending some time in the model, developing barriers that check incoming data and stop it if they don’t match your application’s requirements.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset