With our route properly handling requests to the action
/hello_world, let's change our action to render some HTML instead:
class ApplicationController < ActionController::Base def hello_world render inline: '<em>Hello, World!</em>' end end
Here we use
inline: instead of
plain: to pass the response body string to
render, which sets the content type of the response to HTML. Here is what our response will look like:
HTTP/1.1 200 OK Cache-Control: max-age=0, private, must-revalidate Connection: Keep-Alive Content-Length: 22 Content-Type: text/html; charset=utf-8 Date: Tue, 23 Feb 2016 02:44:36 GMT Etag: W/"1e401bc81108cb3e3dba191111bf9059" Server: WEBrick/1.3.1 (Ruby/2.3.0/2015-12-25) X-Content-Type-Options: nosniff X-Frame-Options: SAMEORIGIN X-Request-Id: a2eac900-60da-460d-9757-94d8c41c4624 X-Runtime: 0.252767 X-Xss-Protection: 1; mode=block <em>Hello, World!</em>
Most of the above is very similar to our last HTTP response for the hello world
action. Notice, that there are a few differences, and one of those differences is
that the response body now has
em tags wrapped around it.
Let's inspect our
response object within Rails as well:
# assuming we're inside the hello_world action above... render inline: '<em>Hello, World!</em>' binding.pry ### inside Pry ### response.body # => "<em>Hello, World!</em>" response.content_type # => "text/html" response.status # => 200
Here we see the content type set appropriately to
text/html, thanks to using
inline: instead of
plain:. The status code here also defaults to
OK), which is fine, but if we wanted to change it, we could do so in a
render call simply by passing e.g.
status: 404 along as well.
Now if you refresh the page, you'll see our
Hello, World! message displayed in italics in your browser, thanks to the
text/html content type and the
<em> tags in the HTML response body string.
We've got requests being processed by an action now, but there's something amiss: there's content in our action.
The problem here is that a controller's job is not to hold content, it's to… well, control things. A cleanly written controller action won't do much of anything itself, other than orchestrate the calling of other parts of the application and, when needed, put those results together.
A controller action is merely the director of the request handling, it should delegate other responsibilities to other parts of the application. But already, ours is doing something it shouldn't have to: it's holding our content, the HTML message.
To fix this, let's move that HTML out of our action.
HTML content belongs in a View, so let's create one to hold it:
<!-- app/views/application/hello_world.html --> <html> <body> <p>Hello, World!</p> </body> </html>
This is the same HTML as before, but now stored in its own view file. And notice where we placed it, because this is important:
All views live in the
app/views directory. From there, they are placed in a directory that corresponds to the controller and action that uses them. Here, this leaves us with an
With our view defined, let's make use of it in our controller:
### app/controllers/application_controller.rb ### class ApplicationController < ActionController::Base def hello_world render 'application/hello_world' end end
NOTE: Make sure to restart your Rails server with
bundle exec rails server before reloading the page
Now, we've used
render a couple times already, but here we're doing something different because we're simply passing it a string. Furthermore, you'll note that this string matches the path of the view that we just created. As a result, our
hello_world action will now render our HTML response body using our freshly defined
render this way is the equivalent of doing:
render inline: File.read('app/views/application/hello_world.html')
Whether we're pointing it to a view or setting the response body in the action itself, keep in mind that it's always the job of
render to set the HTTP response body. Though, as we pointed out above, it's typically bad practice to leave content sitting in your controller, so quite commonly you'll see
render calls rendering views, like the one above.