• No se han encontrado resultados

5.4. ANÁLISIS DAFO DE LA PARENTALIDAD POSITIVA EN LOS PROCESOS

5.4.1. Debilidades

Dave speaking: I can’t help it—I just have to write aHello, World! program to try out a new system. The equivalent in Rails would be an application that sends our cheery greeting to a browser.

As we discussed in Chapter 2, The Architecture of Rails Applications, on

page9, Rails is a Model-View-Controller framework. Rails accepts incom-

ing requests from a browser, decodes the request to find a controller, and calls an action method in that controller. The controller then invokes a particular view to display the results back to the user. The good news is that Rails takes care of most of the internal plumbing that links all these

things together. To write our simple Hello, World! application, we need

code for a controller and a view. We don’t need code for a model, as we’re not dealing with any data. Let’s start with the controller.

Report erratum

HELLO, RAILS! 28

In the same way that we used the rails command to create a new Rails

application, we can also use a generator script to create a new controller

for our project. This command is calledgenerate, and it lives in the script

subdirectory of the demo project we created. So, to create a controller

called say, we make sure we’re in thedemo directory and run the script,

passing in the name of the controller we want to create.3

demo> ruby script/generate controller Say

exists app/controllers/ exists app/helpers/ create app/views/say exists test/functional/ create app/controllers/say_controller.rb create test/functional/say_controller_test.rb create app/helpers/say_helper.rb

The script logs the files and directories it examines, noting when it adds new Ruby scripts or directories to your application. For now, we’re inter- ested in one of these scripts and (in a minute) the new directory.

The source file we’ll be looking at is the controller. You’ll find it in the file

app/controllers/say_controller.rb. Let’s have a look at it. defining classes

page471

File 209 class SayController < ApplicationController

end

Pretty minimal, eh? SayControlleris an empty class that inherits fromAppli-

cationController, so it automatically gets all the default controller behavior. Let’s spice it up. We need to add some code to have our controller handle the incoming request. What does this code have to do? For now, it’ll do nothing—we simply need an empty action method. So the next question is, what should this method be called? And to answer this question, we need to look at the way Rails handles requests.

Rails and Request URLs

Like any other web application, a Rails application appears to its users to be associated with a URL. When you point your browser at that URL, you are talking to the application code, which generates a response back to you.

However, the real situation is somewhat more complicated than that. Let’s

imagine that your application is available at the URL http://pragprog.com/

online/demo. The web server that is hosting your application is fairly smart

3The concept of the “name of the controller” is actually more complex than you might

think, and we’ll explain it in detail in Section13.4,Naming Conventions, on page180. For now, let’s just assume the controller is calledSay.

Report erratum

HELLO, RAILS! 29

http://pragprog.com/online/demo/say/hello

1. First part of URL identifies the application

2. Next part selects a controller (say)

3. Last part identifies the action to invoke

Figure 4.2: URLs Are Mapped to Controllers and Actions

about paths. It knows that once it sees theonline/demopart of the path,

it must be talking to the application. Anything past this in the incoming URL will not change that—the same application will still be invoked. Any additional path information is passed to the application, which can use it for its own internal purposes.

Rails uses the path to determine the name of the controller to use and

the name of the action to invoke on that controller.4 This is illustrated in

Figure4.2. The first part of the path following the application is the name

of the controller, and the second part is the name of the action. This is

shown in Figure4.3, on the following page.

Our First Action

Let’s add an action calledhello to our saycontroller. From the discussion

in the previous section, we know that adding ahelloaction means creating

a method calledhelloin the classSayController. But what should it do? For

now, it doesn’t have to do anything. Remember that a controller’s job is to set up things so that the view knows what to display. In our first appli-

cation, there’s nothing to set up, so an empty action will work fine. Use methods

page469

your favorite editor to change the filesay_controller.rb in the app/controllers

directory, adding thehello( ) method as shown.

File 210 class SayController < ApplicationController

def hello

end end

4Rails is fairly flexible when it comes to parsing incoming URLs. In this chapter, we

describe the default mechanism. We’ll show how to override this in Section16.3, Routing Requests, on page280.

Report erratum

HELLO, RAILS! 30 http://pragprog.com/online/demo/say/hello class CustomerController < ... def hello # actions... end end class OrderController < ... def hello # actions... end end class UpdateController < ... def hello # actions... end end class SayController < ... def hello # actions... end end class LoginController < ... def hello # actions... end end class SayController < ... def hello

# code for hello action... end end Then invoke its hello() method Create an instance of class SayController

Figure 4.3: Rails Routes to Controllers and Actions

Now let’s try calling it. Find a browser window, and navigate to the URL

http://localhost:3000/say/hello. (Note that in this test environment we don’t have any application string at the front of the path—we route directly to the controller.) You’ll see something that looks like the following.

It might be annoying, but the error is perfectly reasonable (apart from the weird path). We created the controller class and the action method, but we haven’t told Rails what to display. And that’s where the views come in. Remember when we ran the script to create the new controller? The command added three files and a new directory to our application. That directory contains the template files for the controller’s views. In our case,

we created a controller named say, so the views will be in the directory

app/views/say.

To complete our Hello, World! application, let’s create a template. By

default, Rails looks for templates in a file with the same name as the

Report erratum

HELLO, RAILS! 31

action it’s handling. In our case, that means we need to create a file called app/views/say/hello.rhtml. (Why .rhtml? We’ll explain in a minute.) For now, let’s just put some basic HTML in there.

File 211 <html>

<head>

<title>Hello, Rails!</title>

</head>

<body>

<h1>Hello from Rails!</h1>

</body>

</html>

Save the filehello.rhtml, and refresh your browser window. You should see

it display our friendly greeting. Notice that we didn’t have to restart the application to see the update. During development, Rails automatically integrates changes into the running application as you save files.

So far, we’ve added code to two files in our Rails application tree. We added an action to the controller, and we created a template to display a page in the browser. These files live in standard locations in the Rails hier-

archy: controllers go into app/controllers, and views go into subdirectories

ofapp/views. This is shown in Figure4.4, on the next page.

Making It Dynamic

So far, our Rails application is pretty boring—it just displays a static page. To make it more dynamic, let’s have it show the current time each time it displays the page.

To do this, we need to make a change to the template file in the view—it now needs to include the time as a string. That raises two questions. First, how do we add dynamic content to a template? Second, where do we get the time from?

Dynamic Content

There are two ways of creating dynamic templates in Rails. One uses a

technology called Builder, which we discuss in Section 17.2, Builder tem-

plates, on page 329. The second way, which we’ll use here, is to embed

Report erratum

HELLO, RAILS! 32 demo/ app/ controllers/ views/ models/ hello.rhtml say_controller.rb say/

class SayController < ApplicationController def hello end end <html> <head> <title>Hello, Rails!</title> </head> <body>

<h1>Hello from Rails!</h1> </body>

</html>

Figure 4.4: Standard Locations for Controllers and Views

Ruby code in the template itself. That’s why we named our template file hello.rhtml: the .rhtmlsuffix tells Rails to expand the content in the file using a system called ERb (for Embedded Ruby).

ERb is a filter that takes an .rhtmlfile and outputs a transformed version.

The output file is often HTML in Rails, but it can be anything. Normal con- tent is passed through without being changed. However, content between

<%=and%> is interpreted as Ruby code and executed. The result of that

execution is converted into a string, and that value is substituted into the

file in place of the <%=...%> sequence. For example, change hello.rhtml to

contain the following.

File 136 <ul>

<li>Addition: <%= 1+2 %> </li>

<li>Concatenation: <%= "cow" + "boy" %> </li> 1.hour.from_now page185

<li>Time in one hour: <%= 1.hour.from_now %> </li>

</ul>

When you refresh your browser, the template will generate the following HTML.

<ul>

<li>Addition: 3 </li>

<li>Concatenation: cowboy </li>

<li>Time in one hour: Sat Feb 26 18:33:15 CST 2005 </li> </ul>

Report erratum

HELLO, RAILS! 33

Making Development Easier

You might have noticed something about the development we’ve been doing so far. As we’ve been adding code to our application, we haven’t had to touch the running application. It’s been happily chugging away in the background. And yet each change we make is available whenever we access the application through a browser. What gives?

It turns out that the WEBrick-based Rails dispatcher is pretty clever. In development mode (as opposed to testing or production), it automati- cally reloads application source files when a new request comes along. That way, when we edit our application, the dispatcher makes sure it’s running the most recent changes. This is great for development.

However, this flexibility comes at a cost—it causes a short pause after you enter a URL before the application responds. That’s caused by the dis- patcher reloading stuff. For development it’s a price worth paying, but in production it would be unacceptable. Because of this, this feature is disabled for production deployment (see Chapter22,Deployment and

Scaling, on page440).

In the browser window, you’ll see something like the following. • Addition: 3

• Concatenation: cowboy

• Time in one hour: Sat Feb 26 18:33:15 CST 2005

In addition, stuff in rhtml between <% and %> (without an equals sign) is

interpreted as Ruby code that is executed with no substitution back into the output. The interesting thing about this kind of processing, though, is that it can be intermixed with non-Ruby code. For example, we could

make a festive version ofhello.rhtml.

3.times page477 <% 3.times do %> Ho!<br /> <% end %> Merry Christmas!

Refresh again, and you’ll be listening for sleigh bells.

Ho! Ho! Ho!

Merry Christmas!

Note how the text in the file within the Ruby loop is sent to the output stream once for each iteration of the loop.

Report erratum

HELLO, RAILS! 34

We can mix the two forms. In this example, the loop sets a variable that is interpolated into the text each time the loop executes.

File 138 <% 3.downto(1) do |count| %>

<%= count %>...<br /> <% end %>

Lift off!

That will send the following to the browser.

3...<br /> 2...<br /> 1...<br /> Lift off!

There’s one last thing with ERb. Quite often the values that you ask it

to substitute using <%=...%>contain less-than and ampersand characters

that are significant to HTML. To prevent these messing up your page (and,

as we’ll see in Chapter21,Securing Your Rails Application, on page427, to

avoid potential security problems), you’ll want to escape these characters.

Rails has a helper method, h( ), that does this. Most of the time, you’re

going to want to use it when substituting values into HTML pages.

File 139 Email: <%= h("Ann & Bill <[email protected]>") %>

In this example, the h( ) method prevents the special characters in the

e-mail address from garbling the browser display—they’ll be escaped as

HTML entities. The browser sees Email: Ann & Bill <[email protected]>—the

special characters are displayed appropriately.

Adding the Time

Our original problem was to display the time to users of our application. We now know how to make our application display dynamic data. The second issue we have to address is working out where to get the time from.

One approach would be to embed a call to Ruby’sTime.now( ) method in our

say.rhtmltemplate. <html>

<head>

<title>Hello, Rails!</title>

</head>

<body>

<h1>Hello from Rails!</h1>

<p>

The time is <%= Time.now %>

</p>

</body>

</html>

Report erratum

HELLO, RAILS! 35

This works. Each time we access this page, the user will see the current time substituted into the body of the response. And for our trivial applica- tion, that might be good enough. In general, though, we probably want to do something slightly different. We’ll move the determination of the time to be displayed into the controller and leave the view the simple job of dis- playing it. We’ll change our action method in the controller to set the time

value into an instance variable called@time. instance variable

page472

File 212 class SayController < ApplicationController

def hello

@time = Time.now

end end

In the .rhtmltemplate we’ll use this instance variable to substitute the time

into the output.

File 213 <html>

<head>

<title>Hello, Rails!</title>

</head>

<body>

<h1>Hello from Rails!</h1>

<p>

It is now <%= @time %>.

</p>

</body>

</html>

When we refresh our browser window, we see the time displayed, as shown

in Figure 4.5. Notice that if you hit Refresh in your browser, the time

updates each time the page is displayed. Looks as if we’re really generating dynamic content.

Why did we go to the extra trouble of setting the time to be displayed in the controller and then using it in the view? Good question. In this appli-

Figure 4.5: Hello, World!with a Time Display

Report erratum

HELLO, RAILS! 36

Joe Asks. . .

How Does the View Get the Time?

In the description of views and controllers, we showed the controller set- ting the time to be displayed into an instance variable. The .rhtmlfile used that instance variable to substitute in the current time. But the instance data of the controller object is private to that object. How does ERb get hold of this private data to use in the template?

The answer is both simple and subtle. Rails does some Ruby magic so that the instance variables of the controller object are injected into the template object. As a consequence, the view template can access any instance variables set in the controller as if they were its own.

cation, you could just embed the call toTime.now( ) in the template, but by

putting it in the controller instead, you buy yourself some benefits. For example, we may want to extend our application in the future to support users in many countries. In that case we’d want to localize the display of the time, choosing both the format appropriate to the user’s locale and a time appropriate to their time zone. That would be a fair amount of application-level code, and it would probably not be appropriate to embed it at the view level. By setting the time to display in the controller, we make our application more flexible—we can change the display format and time zone in the controller without having to update any view that uses that time object.

The Story So Far

Let’s briefly review how our current application works.

1. The user navigates to our application. In our case, we do that using

a local URL such ashttp://localhost:3000/say/hello.

2. Rails analyzes the URL. Thesaypart is taken to be the name of a con-

troller, so Rails creates a new instance of the Ruby classSayController

(which it finds inapp/controllers/say_controller.rb).

3. The next part of the URL path, hello, identifies an action. Rails

invokes a method of that name in the controller. This action method

Report erratum

Documento similar