Ruby On Rails: Week 3

Ruby on Rails from Scratch Week 3

Sep 26th in Ruby by Connor Zwick

Welcome to Ruby on Rails From Scratch Week 3! This week, we'll focus on specific things that you need to know about the framework. For example, we're going to talk about manipulating the structure of the project in two ways (rendering & redirecting). We'll also talk about how you add links in rails, and how to comment code. Let's get started already!

Author: Connor Zwick

I am a freelance web designer. I am currently renovating my personal site, which will be up within the month hopefully. I know HTML, CSS, Javascript, JQuery, PHP, Flash, and Ruby on Rails. I am also doing several website for pay currently. As well as designing a web site for a robotics team for free. This website will feature a lot of what I will cover in this tutorial. I have also coded a media management site and blog in Ruby on Rails. I also have extensive Photoshop experience.

Catching Up

If you haven't read Parts 1 and 2, it is strongly advised that you review them before continuing on with this tutorial.

Adding Interactions Amongst Actions

Now that we've learned how to set instance variables to transfer information from the controller to the view, it is time to learn how to transmit data between different actions in a controller. For this tutorial, we're going to continue using the learn controller. We don't really need to keep what we did last week, but you can if you feel like it is a good resource.. We'll start off simple:

Perform Another Action in a different Action

For this example, the heading is more complex than the actual lesson. We are going to simply use what's in one action and do the same in another. Lets use the knowledge we gained last week about instance variables, and apply it now. First, let's create a new action called "another_action"; then another action called "text". We are going to then get the action from text and put it in "another_action". We are going to prove this, by referencing an instance variable in the view of "another_action" that was assigned in the "text" controller. Sorry, if that didn't make sense. If you didn't get what I just said, look at the following code, which will hopefully help you:

class LearnController < ApplicationController
    
  def another_action
  	text
  end

  def text
  	@text = 'This text came from another action'
  end
  end

We are then going to create a view called "another_action.html.erb", where we reference the variable text.

<html>
  <head>
  <title>Action Demo</title>
  </head>
<body>
    
  <%= @text %>
  </body>
  </html>

Explanation

As you can see, we referenced the action "text" simply by putting that inside of "another_action". By doing this, we also passed the definition of "text", which was the instance variable. To further demonstrate this principle, let's put this in several different situations, all of which work.

Situation 1- Setting An Instance Variable Equal to an Action

class LearnController < ApplicationController
	
	def another_action
		@text = text
	end
	
	def text
		misc_text = 'This text really traveled!'
	end	
end

Situation 1 Result

Text Travelled

Situation 2 - Replace Variable

Now we're going to get even more complex:

<html>
class LearnController < ApplicationController
	
	def another_action
		@text = "text you'll never see"
		@text = text
	end
	
	def text
		wanted_text = overwrite_view
	end
	
	def overwrite_view
		overwrite_text = 'This text overwrote the original text'
	end
end

Situation 2 Result

This is the order of events that the following code did:

  • Gave the instance variable "text" a value of "text you'll never see"
  • Then it re-assigned it to the action "text"
  • The variable "text", now has the value of the local variable wanted text.
  • The wanted_text variable has a value of the action "overwrite_view"
  • Overwrite_view has a local variable with a value of "This text overwrote the original text"
  • This carries back to the instance variable of @text.

Situation 3 Carry a Variable

We'll keep this one simpler:

class LearnController < ApplicationController
	
	def another_action
		@text = "text you'll never see"
		text
	end
	
	def text
		@text = 'This text overwrote the original text'
	end
end


Situation 3 Result

pass the variable

Situation 4 Returning Something Specific

class LearnController < ApplicationController
	
	def another_action
		@text = text
	end
	
	def text
		first = 'This text should not be passed to @text'
		second = 'This text would be put into the variable on default'
		return first
	end
		
end

This example is particularly important, as you are now learning a little bit more syntax; the return command. This will tell the action what to return at the end.

Situation 4 Result

return

Rails Links

Everyone should already know how to create a normal HTML link. (Using <a href="">Text</a>) But there's also a way to do it with Rails. This method is not Ruby, but rather a part of the framework. That being said, you can only use it in embedded ruby HTML files, not pure rb files. So how do we do it? Here is the code:

<html>
  <head>
  <title>Rails Link Demo</title>
  </head>
<body>
    
  <%= link_to('Another Action Link', :controller => 'learn', :action => 'another_action')%>
  </body>
  </html>

At first glance, you might wonder why you would ever change the way you write links, especially if the replacement is longer! Well one main reason is readability. You can easily read this and know exactly what it's going to link to. As for length, the :controller => part is not necessary if you're linking to an action within the same controller.

With this piece of rails code we are also seeing symbols. The ":controller =>" is a symbol. We'll talk more about what they do later, but for right now just recognize the colon.

Rendering in Rails

Earlier in this series, we talked a little bit about rails' sensible defaults. One of the defaults is to generate a view that has the same name as the action in the corresponding view. But what if we wanted to overwrite what rails automatically does? This is actually quite easy, and a very useful technique. When you're working on a real world project, you can imagine how 'clunky' your controller would get if you needed to create a separate view and action in the controller for each page. Rails has a solution though, which is called rendering. Rendering allows you to specify what view to use for each action. Keep in mind though, that like rails links, this is also rails exclusive code and not ruby, and meant only for the controller.

If the above has left you a little confused, let me show you how to do it. This will hopefully clarify it a little bit. For this first example, we're going to render the action to the view that it would normally render anyway. In other terms, this render code does nothing that wouldn't happen without it. All it is doing is showing some code that usually is just 'assumed'.

	def index
		render :action => 'index'
	end
    

Rendering an Action to another View

The last example isn't really useful since the result is achieved automatically anyway. But what if you had a really advanced view for another action, and you wanted the same view for a different action. It would not only be tedious to create another identical view for each action you create, but it would also be nearly impossible to update! All of that can be fixed though by rendering every similar action to a specific action. Examine the following piece of code which I will explain afterwards, and notice the different parts.

text_controller.rb:

class LearnController < ApplicationController
	
	def index
		render :action => 'text'
	end
	
	def text
		@text = '<u>Text</u>'
	end
	
	def other
		@text = '<b>Other</b>'
		render :action => 'text'
	end
		
end

text.html.erb:

<html>
  <head>
  <title>Rails Rendering Demo</title>
  </head>

<body> <p>Welcome to the <%= @text %> Page</p>

</body> </html>

Explanation of Code:

Index Action

You might have noticed that I included an action called "index". This action will be viewed if you go up a directory to "learn". It works like an ordinary index file would. You don't have to create a specific action for index though. You can use the previously covered topic of inheriting another action as well.

Rendering to the same view

For this example, we only needed one view for all of the actions; and they all produced different pages. To me, this is pretty incredible for the amount of work we put in.

Note: This might seem obvious to some, but beware of double rendering. Double rendering will cause an error because you're trying to render an action to two different places. Can you be in two places at once? No, and neither can an action. If you want to see what it looks like, just render an action to two different views. The reason it happens as you're doing more complex projects is because the trail of actions can get pretty complex, and you might accidentally create this error.

Make sure you get the basic concept of rendering, as it will be a very vital technique that you will use often as a rails developer.

Redirecting An Action

Redirecting an Action is similar to rendering an action in the fact that it too is rails code and only used in the controller. Also, it effects the flow of the application. As you might guess from the name, redirecting allows you to... well redirect.

You might be surprised by how many times you use the redirect command. Here are some common uses:

  • Creating alias pages
  • Performing an action in the controller and then redirecting to a secondary page
  • If there is an error, redirect to an error page
  • If user is not logged in, send them to a login page

Enough chit chat, let's get to the code! For this code example, we're just going to modify the last example's controller and leave the view the same. As you'll see, redirecting is very similar in format to rendering:

class LearnController < ApplicationController
	
	def index
		redirect_to :action => 'text'
	end
	
	def text
		@text = '<u>Text</u>'
		redirect_to :action => 'other'
	end
	
	def other
		render :action => 'text'
	end
		
end

Now go to the index action in your browser. You'll notice that you end up at the other action in your address bar. Let's run through this code:

  • First, we redirect to the action text. Like linking in rails, you can specify a controller too if you're redirecting to another controller. You would just put :controller => 'learn', before the action.
  • The browser now goes to the text action. Here it sets a value for @text. But the browser has no value for @text. This is because redirecting essentially forgets anything you tell it in that action.
  • We are now redirected to other. Here we render out to the text view.

Render or Redirect?

While there are some obvious scenarios where you would chose either to render or to redirect; there can be some harder decisions. One important key though is that if you're submitting data into a database or anything that is changing the application, use a redirect. Otherwise, a refresh could resubmit the data.

Final Thoughts

Hope you guys learned a lot from this week's tutorial! We covered a lot of important concepts so if you are still confused by anything, re-read it. Next week we'll probably get into ruby syntax!

As always, feel free to leave questions in the comments. Also, please digg this article if it helped you!


Related Posts

Check out some more great tutorials and articles that you might like

Enjoy this Post?

Your vote will help us grow this site and provide even more awesomeness

User Comments

( ADD YOURS )
  1. yusuf1 September 26th

    this is very nice, ive been really looking forward to this ruby tuts. cheers mate tho :)


  2. insic September 26th

    its nice to end the weekend with this great tutorial. thank you.


  3. Jim Neath September 26th

    The text method in your controller should be protected, unless you want to access it directly.

    Also you appear to be assigning HTML tags in the controller, this should be in the view, as you’re breaking MVC.


  4. Shane September 26th

    Nice to have another RoR tutorial. Thanks.


  5. Paul Gendek September 26th

    I don’t know if you guys have seen this yet or not, but it’s pretty hilarious: http://railscantscale.com/


  6. Niklas September 26th

    Splendid! Excellent for a late Friday night! :)


  7. Lamin Barrow September 26th

    Actually i am enjoying this Ruby stuff quite a lot. Please keep them coming. Thanks :)


  8. Miles Johnson September 26th

    ROR is amazing but I CANT STAND its syntax… if its a long piece of code its just confusing; everything looks open without a closing tag. Nothing ROR can do that PHP cant, so Ill stick with my PHP.


  9. Ben Griffiths September 26th

    Very clear and well explained, thanks :D


  10. Shane September 26th

    @Miles - it’s certainly different, that’s for sure, but RoR is often praised for its elegance. I have to say that I often find PHP a bit like a load of tag soup. I use it primarily because so many great things have been written in it.

    I guess it’s a case of getting used to it.


  11. Connor September 26th

    When you first see it, ruby syntax might seem a little foreign if you have no experience with similar languages, but once you get use to it, it is much more readable. And that makes it easier to modify and debug.


  12. Kevin Quillen September 26th

    If Rails can’t scale well, theres no sense using it for real-world projects. Clients don’t want to pay you for an application, then pay extra for hours of overhead and server expansion efforts. Heres a great article from Rob Conory:

    http://blog.wekeroad.com/blog/imploding-rails-jesus-dhh-and-the-uncle-ben-principle/


  13. Ivan September 26th

    Keep it coming! :)


  14. Furley September 26th

    you need a cakephp series. get snook to do it.

    http://snook.ca/jonathan/


  15. David Rojas September 27th

    Oh yes! A cakephp series by Jonathan Snook, please :-)


  16. Shane September 27th

    @Kevin - this is the only thing that’s stopped me going all out for Rails. I don’t come from a PHP background, and when I first started using it, I naively thought that it was a case of tag-soup and getting your hands dirty. Then I found that there are PHP frameworks out there too, stuff like cakephp and codeigniter that make it much easier and much fun to use PHP.

    I would love to deploy a large Rails app and actually see how it performed. Prior to that deployment, however, there would be the massive commitment in terms of time and intellectual effort. All this whilst that performance niggle remained in the back of my mind.

    I started doing some intensive reading on Rails, but the niggle grew, and I gave up.

    Then again, there’s a part of me that’s thinking that I’ve got the technical know-how and balls to question what sometimes seems like the prejudice against the great framework.


  17. Kevin Quillen September 27th

    I don’t come from a PHP background either. I’ve only been programming in PHP for about 6 months now. Before that we were Coldfusion. Knowing the flaws of Rails makes it impossible to get it past the supervisors to develop with, and expect clients to accept more than normal downtime and expensive scaling required (throwing in more server hardware) etc.

    A lot of research has to go in for a company before they select a framework to use. When we were getting off the Coldfusion train, the first thing I looked at was ROR, PHP, and Python. After taking into account a lot of factors, cost, speed, ease of use, reliability, online resources etc… we settled on PHP. CakePHP looks like a damn fine framework. As we develop most sites around Drupal at the moment, we don’t have an opportunity yet to fully employ a coding framework. But, coming from Fusebox, I would jump at the chance to dive into Cake or CodeIgniter.

    Seems like its ok to tinker with here and there, but when its all said and done ROR isn’t ready for enterprise use yet (despite some big names running ROR- they have more money resources than we care to throw around).


  18. Shane September 28th

    @Kevin - thanks for that link. I read the article and it was very interesting. I suggest other readers take a look.


  19. Adam Haskell September 28th

    @Kevin You know we have a PHP version of Fusebox? You could stick to Fusebox, even keep the same circuits and fusebox files during a transition period. Being a big CFML fan I dislike seeing folks leave CFML, especially with projects like Railo and Open BlueDragon, but I hate loosing folks from our framework more ;)


  20. jennnn September 28th

    Omg!


  21. lowell September 28th

    connor..

    last week, you were advised to adopt the html.erb naming scheme for your views as the old .rhtml was deprecated. it’s nice to see that you took the advice, but you need to let the readers know why - not because of humility or anything, but because you can’t mix .rhtml and html.erb in the same project.

    and now, i just saw an html tag in a CONTROLLER. by doing that, you just led every single reader following along into breaking MVC, which is the whole point of the framework. i stopped reading at that point.

    it doesn’t really seem like ruby’s your cup of tea, if you aren’t comfortable or familiar with something, you shouldn’t blog about it because the inexperience will show. i’m sure the framework has you excited, and it’s great you want to contribute to the community, but there are plenty of ways within your skill level. your readers deserve much, much better than what you’ve given them.


  22. Kevin Quillen September 28th

    Yep, I know there is a PHP version of Fusebox. FB served us well for rapid app development over the years, but the market is changing, you know? We’re in a state right now where a framework just can’t see any use, a lot of clients coming in want content management, and we’ve been building a very great CMS off the Drupal core.

    I have kind of been kicking around the notion in my head that someone should convert Drupal into CakePHP or a similar framework… so you could mesh merge and build apps into one another.. maybe.

    We used Fusebox to do a lot of ground up custom programming for web based applications but the demand for those solutions has been tapering off over the last 2 years, and Coldfusion can be expensive, with the server licensing and hosting and such. I still like CF. I’m not sure if Adobe can last another 5 years while charging for it though, where pretty much every other platform is free.

    Have you heard of Smith Project?

    http://www.smithproject.org/


  23. Danny September 28th

    To be honest i found the idea of learning RoR a little daunting to say the least. But these tutorials have been excellent. Ive gone through the three tonight already.

    It is certainly not as painful as i thought it would be. My only other similar experience was some ASP at college and dabbling in PHP from time to time. Ruby seems to be quite logical and easy to pick up in comparison.

    Keep up the good work Connor… (and hurry up with tutorial 4 lol)


  24. Bernie September 29th

    Great, keep em coming!


  25. insic September 29th

    Be it PHP or RoR, both of the two are great language. And i always find myself a challenge and learn a lot.


  26. Consufed September 30th

    I am getting errors in the example “Perform Another Action in a different Action”

    http://localhost:3000/learn

    Unknown action
    No action responded to index

    I added this files:
    C:\ruby\rails_apps\nettuts\app\views\learn\another_action.html.erb

    learn_controller.rb has the added code.


  27. Some Guy September 30th

    Confused: You want to be going to /learn/another_action rather than just /learn


  28. Connor October 1st

    @lowell,

    Once again, this is just a tutorial. There’ll be a later tutorial on conventions. When you’re first learning rails, it is more important to learn things like rendering, and ruby syntax, then to get that you shouldn’t put html tags in the controller.

    I guess that’s just the way that I view how you should learn it.


  29. Diego Gomes October 8th

    Already waiting for week 4!


  30. Travis October 14th

    I have to say that RoR is a much better language than PHP. While it is true that a system has to be optimized for the larger RoR apps, ruby is a much cleaner language than PHP. PHP lends itself to some of the worse programming practices out there. And trying to do anything in true OOP fashion is laughable. Ruby was created from the ground up as a true OOP language. If you’re a hobbyist or a beginner who is writing smaller apps, then sure, PHP is a great choice. But for someone who comes from a programming background and wants to write large scale apps that scale with ease, then RoR is the way to go.


  31. Connor October 22nd

    Yeah…it should be posted anytime now…


  32. M.A.Yoosuf November 10th

    i am stuck on this, :( can anybody help me on this!!!


Add Your Comment

( GET A GRAVATAR )
  • Gravatar

    Your Name November 21st

Arrow