- •Introduction
- •Rails Is Agile
- •Finding Your Way Around
- •Acknowledgments
- •Getting Started
- •Models, Views, and Controllers
- •Installing Rails
- •Installing on Windows
- •Installing on Mac OS X
- •Installing on Unix/Linux
- •Rails and Databases
- •Keeping Up-to-Date
- •Rails and ISPs
- •Creating a New Application
- •Hello, Rails!
- •Linking Pages Together
- •What We Just Did
- •Building an Application
- •The Depot Application
- •Incremental Development
- •What Depot Does
- •Task A: Product Maintenance
- •Iteration A1: Get Something Running
- •Iteration A2: Add a Missing Column
- •Iteration A4: Prettier Listings
- •Task B: Catalog Display
- •Iteration B1: Create the Catalog Listing
- •Iteration B2: Add Page Decorations
- •Task C: Cart Creation
- •Sessions
- •More Tables, More Models
- •Iteration C1: Creating a Cart
- •Iteration C3: Finishing the Cart
- •Task D: Checkout!
- •Iteration D2: Show Cart Contents on Checkout
- •Task E: Shipping
- •Iteration E1: Basic Shipping
- •Task F: Administrivia
- •Iteration F1: Adding Users
- •Iteration F2: Logging In
- •Iteration F3: Limiting Access
- •Finishing Up
- •More Icing on the Cake
- •Task T: Testing
- •Tests Baked Right In
- •Testing Models
- •Testing Controllers
- •Using Mock Objects
- •Test-Driven Development
- •Running Tests with Rake
- •Performance Testing
- •The Rails Framework
- •Rails in Depth
- •Directory Structure
- •Naming Conventions
- •Active Support
- •Logging in Rails
- •Debugging Hints
- •Active Record Basics
- •Tables and Classes
- •Primary Keys and IDs
- •Connecting to the Database
- •Relationships between Tables
- •Transactions
- •More Active Record
- •Acts As
- •Aggregation
- •Single Table Inheritance
- •Validation
- •Callbacks
- •Advanced Attributes
- •Miscellany
- •Action Controller and Rails
- •Context and Dependencies
- •The Basics
- •Routing Requests
- •Action Methods
- •Caching, Part One
- •The Problem with GET Requests
- •Action View
- •Templates
- •Builder templates
- •RHTML Templates
- •Helpers
- •Formatting Helpers
- •Linking to Other Pages and Resources
- •Pagination
- •Form Helpers
- •Layouts and Components
- •Adding New Templating Systems
- •Introducing AJAX
- •The Rails Way
- •Advanced Techniques
- •Action Mailer
- •Sending E-mail
- •Receiving E-mail
- •Testing E-mail
- •Web Services on Rails
- •Dispatching Modes
- •Using Alternate Dispatching
- •Method Invocation Interception
- •Testing Web Services
- •Protocol Clients
- •Securing Your Rails Application
- •SQL Injection
- •Cross-Site Scripting (CSS/XSS)
- •Avoid Session Fixation Attacks
- •Creating Records Directly from Form Parameters
- •Knowing That It Works
- •Deployment and Scaling
- •Picking a Production Platform
- •A Trinity of Environments
- •Iterating in the Wild
- •Maintenance
- •Finding and Dealing with Bottlenecks
- •Case Studies: Rails Running Daily
- •Appendices
- •Introduction to Ruby
- •Ruby Names
- •Regular Expressions
- •Source Code
- •Cross-Reference of Code Samples
- •Resources
- •Index
KEEPING UP-TO-DATE 24
this directory into the ADO directory in the Ruby tree that you created in step 1.
The SQL Server adapter will work only on Windows systems, as it relies on Win32OLE.
3.5 Keeping Up-to-Date
Assuming you installed Rails using RubyGems, keeping up-to-date is relatively easy. Issue the command
dave> gem update rails
and RubyGems will automatically update your Rails installation. The next time you restart your application it will pick up this latest version of Rails. (We have more to say about updating your application in production in the Deployment and Scaling chapter, starting on page 440.)
3.6 Rails and ISPs
If you’re looking to put a Rails application online in a shared hosting environment, you’ll need to find a Ruby-savvy ISP. Look for one that supports Ruby, has the Ruby database drivers you need, and offers FastCGI and/or lighttpd support. We’ll have more to say about deploying Rails applications in Chapter 22, Deployment and Scaling, on page 440.
Now that we have Rails installed, let’s use it. On to the next chapter.
Prepared exclusively for Rida Al Barazi
Report erratum
Chapter 4
Instant Gratification
Let’s write a trivial web application to verify we’ve got Rails snugly installed on our machines. Along the way, we’ll get a glimpse of the way Rails applications work.
4.1 Creating a New Application
When you install the Rails framework, you also get a new command-line tool, rails, which is used to construct each new Rails application that you write.
Why do we need a tool to do this—why can’t we just hack away in our favorite editor, creating the source for our application from scratch? Well, we could just hack. After all, a Rails application is just Ruby source code. But Rails also does a lot of magic behind the curtain to get our applications to work with a minimum of explicit configuration. To get this magic to work, Rails needs to find all the various components of your application. As we’ll see later (in Section 13.2, Directory Structure, on page 173), this means that we need to create a specific directory structure, slotting the code we write into the appropriate places. The rails command simply creates this directory structure for us and populates it with some standard Rails code.
To create your first Rails application, pop open a shell window and navigate to a place in your filesystem where you’ll want to create your application’s directory structure. In our example, we’ll be creating our projects in a directory called work. In that directory, use the rails command to create an application called demo. Be slightly careful here—if you have an existing directory called demo, you will be asked if you want to overwrite any existing files.
Prepared exclusively for Rida Al Barazi
CREATING A NEW APPLICATION |
26 |
dave> cd work work> rails demo create
create app/apis
create app/controllers create app/helpers
:: :
create log/development.log create log/test.log
work>
The command has created a directory named demo. Pop down into that directory, and list its contents (using ls on a Unix box or dir under Windows). You should see a bunch of files and subdirectories.
work> cd demo |
|
|
|
|
demo> ls -p |
|
|
|
|
CHANGELOG |
app/ |
db/ |
log/ |
test/ |
README |
components/ |
doc/ |
public/ |
vendor/ |
Rakefile |
config/ |
lib/ |
script/ |
|
All these directories (and the files they contain) can be intimidating to start with, but we can ignore most of them when we start out. For now, we need to use only one of them, the public directory.
As its name suggests, the public directory contains the files that we expose to our end users, the people using our application. The key files are
the dispatchers: dispatch.cgi, dispatch.fcgi, and dispatch.rb. The dispatch- dispatchers ers are responsible for accepting incoming requests from users sitting at
their browsers and directing those requests to the code in our application. They’re important files, but we won’t need to touch them for now.
You’ll also notice that there’s a script directory underneath demo. It contains some utility scripts that we’ll be using as we develop our applications. For now, we’ll use the script called server. It starts a stand-alone web server that can run our newly created Rails application under WEBrick.1 So, without further ado, let’s start the application you just wrote.
demo> ruby script/server
=> Rails application started on http://0.0.0.0:3000 [2005-02-26 09:16:43] INFO WEBrick 1.3.1
[2005-02-26 09:16:43] INFO ruby 1.8.2 (2004-08-24) [powerpc-darwin7.5.0] [2005-02-26 09:16:43] INFO WEBrick::HTTPServer-start: pid=2836 port=3000
As the last line of the start-up tracing indicates, we just started a web server on port 3000.2 We can access the application by pointing a browser at http://localhost:3000. The result is shown in Figure 4.1.
1WEBrick is a pure-Ruby web server that is distributed with Ruby 1.8.1 and later.
2The 0.0.0.0 part of the address means that WEBrick will accept connections on all interfaces. On Dave’s OS X system, that means both local interfaces (127.0.0.1 and ::1) and his LAN connection.
Prepared exclusively for Rida Al Barazi
Report erratum
HELLO, RAILS! 27
Figure 4.1: Newly Created Rails Application
We’re going to leave WEBrick running in this console window. Later on, as we write application code and run it via our browser, we’ll see this console window tracing the incoming requests. When you’re done using the application, you can press control-C to stop WEBrick.
At this point, we have a new application running, but it has none of our code in it. Let’s rectify this situation.
4.2 Hello, Rails!
Dave speaking: I can’t help it—I just have to write a Hello, 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 page 9, Rails is a Model-View-Controller framework. Rails accepts incoming 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.
Prepared exclusively for Rida Al Barazi
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 called generate, 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 the demo 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 interested 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 |
File 209 |
class SayController < ApplicationController |
→ page 471 |
|
||
|
end |
|
Pretty minimal, eh? SayController is an empty class that inherits from ApplicationController, 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 Section 13.4, Naming Conventions, on page 180. For now, let’s just assume the controller is called Say.
Prepared exclusively for Rida Al Barazi
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 the online/demo part 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 Figure 4.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 Figure 4.3, on the following page.
|
Our First Action |
|
Let’s add an action called hello to our say controller. From the discussion |
|
in the previous section, we know that adding a hello action means creating |
|
a method called hello in the class SayController. 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 |
|
your favorite editor to change the file say_controller.rb in the app/controllers |
|
directory, adding the hello( ) method as shown. |
File 210 |
class SayController < ApplicationController |
|
def hello |
|
end |
|
end |
methods
→ page 469
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 Section 16.3, Routing Requests, on page 280.
Prepared exclusively for Rida Al Barazi
Report erratum
HELLO, RAILS! 30
http://pragprog.com/online/demo/say/hello
class CustomerController < ...
|
|
def hello |
|
|
|
||||||||||
|
|
class OrderController < ... |
|
|
|
||||||||||
|
|
|
|
|
# actions... |
|
|
|
|||||||
|
|
|
|
|
def hello |
|
|
|
|||||||
|
|
|
|
endclass |
UpdateController < ... |
|
|
|
|||||||
end |
|
|
|
|
|
# actions... |
|
|
|
||||||
|
|
|
|
|
def hello |
|
|
|
|||||||
|
|
|
|
|
|
|
endclass SayController < ... |
|
|
|
|||||
|
|
end |
|
|
|
|
|
# actions... |
|
|
|
||||
|
|
|
|
|
|
|
def hello |
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
endclass LoginController < ... |
|
|
|
||
|
|
|
|
|
end |
|
|
|
# actions... |
|
|
|
|||
|
|
|
|
|
|
|
|
def hello |
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
end |
|
|
||
|
|
|
|
|
|
|
|
|
|
|
# actions... |
|
|||
|
|
|
|
|
|
|
|
end end |
|
||||||
|
|
|
|
|
|
|
|
|
|
|
end |
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Create an |
|
|
instance of class |
|
|
SayController |
|
Then |
|
|
invoke its |
|
|
|
|
|
hello() |
|
|
method |
class |
SayController < ... |
def |
hello |
# |
code for hello action... |
end |
|
end |
|
|
|
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
Prepared exclusively for Rida Al Barazi
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 file hello.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 hierarchy: controllers go into app/controllers, and views go into subdirectories of app/views. This is shown in Figure 4.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 templates, on page 329. The second way, which we’ll use here, is to embed
Prepared exclusively for Rida Al Barazi
Report erratum
HELLO, RAILS! 32
class SayController < ApplicationController
demo/ |
def hello |
||||||||||||
|
|
app/ |
end |
||||||||||
|
|
end |
|||||||||||
|
|
|
|
|
|
controllers/ |
|||||||
|
|
|
|
|
|
||||||||
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
say_controller.rb |
|
|
|||
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
<html> |
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
models/ |
|
<head> |
|||||
|
|
|
|
|
|
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
<title>Hello, Rails!</title> |
|
|
|
|
|
|
views/ |
|
</head> |
|||||
|
|||||||||||||
|
|
|
|
|
|
|
|
|
say/ |
|
<body> |
||
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
<h1>Hello from Rails!</h1> |
|||
|
|
|
|
|
|
|
|
|
|
|
hello.rhtml |
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
</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 .rhtml suffix tells Rails to expand the content in the file using |
|
a system called ERb (for Embedded Ruby). |
|
ERb is a filter that takes an .rhtml file 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> |
|
<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> |
1.hour.from_now
→ page 185
Prepared exclusively for Rida Al Barazi
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 automatically 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 dispatcher 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 Chapter 22, Deployment and Scaling, on page 440).
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 of hello.rhtml.
|
3.times |
<% 3.times do %> |
→ page 477 |
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.
Prepared exclusively for Rida Al Barazi
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 Chapter 21, Securing Your Rails Application, on page 427, 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 <frazers@isp.email>") %> |
|
|
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 <frazers@isp.email>—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’s Time.now( ) method in our say.rhtml template.
<html> <head>
<title>Hello, Rails!</title>
</head> <body>
<h1>Hello from Rails!</h1>
<p>
The time is <%= Time.now %>
</p> </body>
</html>
Prepared exclusively for Rida Al Barazi
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 |
|
File 212 |
class SayController < ApplicationController |
→ page 472 |
|
|
|
||
|
def hello |
|
|
|
@time = Time.now |
|
|
|
end |
|
|
|
end |
|
|
|
In the .rhtml template 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
Prepared exclusively for Rida Al Barazi
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 setting the time to be displayed into an instance variable. The .rhtml file 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 to Time.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 as http://localhost:3000/say/hello.
2.Rails analyzes the URL. The say part is taken to be the name of a controller, so Rails creates a new instance of the Ruby class SayController
(which it finds in app/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
Prepared exclusively for Rida Al Barazi
Report erratum