10 Ruby on Rails 3 Tips That Will Make You a Better Rails Programmer
If you already are a Rails programmer, or if you are just beginning to learn about rails in your computer programming classes, i’m pretty sure that you have already been dazzled by the things that Rails can do for you. However, all this convenience comes at a cost. That cost comes for the fact that you need to know how to work with the internal Rails conventions and traps. Since i’ve been programming in Rails for quite some months now, i would like to give you what i think are some very useful tips that will make your Rails life easier. On my previous post, i’ve described how Rails associations work, so you might want to take a look. Let’s now take a look at some important Rails techniques-tips.
1. A Relation is Different Than an Array of Records in Active Record
Take a look at the screenshot please (click on it for larger view) :
Notice that when we execute User.where(“name = ?”, ‘hthought’) and then get the class of object, we see that this one is a Relation. A Relation behaves like a pointer. It never actually executes the database query, unless asked by a specific operand. However, we can use it to get a pointer to a scope inside the database. This means that in this case :
the_users = User.where("name = ?", 'hthought')
The variable the_users is now a relation that describes a scope. This scope concerns all these users table rows that have the name ‘hthought’. Remember, at that point, no database select has been made. The actual database query will happen if we now execute :
the_users.first
This is exactly the same as the second User.where above. This one is actually an array of records now, or actual a single object, since we called first to retrieve the first record.
2. Use Ready Made Rails Plugins
We both know that we are using Rails in order to make our lives easier. We hate doing repetitive things with php, mySQL and the likes. That is why we decided to take on Rails and learn as much as possible, in order to fully harvest its power. Therefore, it would make no sense to reinvent the wheel for no reason. Rails has many people who are working behind the scenes to make it better. In that process, many of them create some very useful plugins, that make our lives a whole lot easier. There is no need to write your own authentication routine, RBAC, messaging system, or even a forum. Take a very close look on the hundred of Rails plugins first. A good starting point is http://agilewebdevelopment.com/, and as always, use a search engine for more
3. Understand What a Model, Controller, View, and Helper are
Rails heavily depends on the model view controller (MVC) design pattern. Every one of them has a specific job and jeopardizing them is never a good idea. A controller is responsible for handling Rails requests and passing data from a model to a view. You can think of the controller as a manager between the logic of your program and the actual view that a user actually sees. Generally, a controller should have very few code. It should just execute some functions and retrieve instance variables to be used directly in a view. Moreover, it is used to do redirects with redirect_to and the likes.
A model is where your actual business logic is. The body of your main functions should always lie inside a model that is responsible for handling that data. Since a model operates on data, it’s pretty sensible that a model actually represents a database table and the operations that can be done on that. Always make sure that your functions and core code is inside your models.
A view is where data is represented to the user. You should never (really, never) include logic inside your views. If you feel that you need to include some sort of code inside your views, chances are high that you will be executing more database queries than actually needed. If you feel that you can use a hash instead, do it; although a bit more code to write, it’s the superior choice.
Some people may believe that a helper is the way to elegantly include code in your views. However, that is not really the case. A helper is actually (or should be) sort of a formatting underlying task. For instance, suppose that you have a hash that contains the costs of 4 different products, that you need to present to your view. If you would like to present some of the prices in euros and some in dollars, you could use a helper that would create a string like “this costs 20 dollars” or a string like “this costs 18 euros”, based on the helper function input.
Always put code having this priority in your mind :
1. model
2. helper
3. controller
4. view
4. Yes, Nil and Empty are a Bit Weird in Rails. Hopefully, this section will make it a bit more clear for you.
One of the things that are a bit weird in Rails, is the the way it handles true, false, and nil values. One may think that a false is equal to a nil, like 0 is equal to false in languages like php. However, this is not the case with Rails. Let’s illustrate using rails console :
irb(main):013:0> false.nil?
=> false
irb(main):014:0> true.nil?
=> false
irb(main):015:0> 0.nil?
=> false
irb(main):016:0> [].nil?
=> false
irb(main):017:0> User.find_by_id(1).nil?
=> true
irb(main):018:0> User.find_by_name('hthought').nil?
=> false
This should now make more sense. In Rails, you check whether an object meets a certain condition, using the ? operand like : “1.nil?”. This would check whether 1 is a nil object (would return false, of course). In the examples above, you first notice that true, false, and 0 are not nil objects. Also, an empty hash is still not a nil object. However, trying to find a user that has an id of 1 returns nil if this user does not exist. On the other side, a user with the name ‘hthought’ does exist, and that is why we get a not nil value in the last example. Let’s now take a look at empty? as well :
irb(main):019:0> [].empty? => true irb(main):020:0> "".empty? => true irb(main):021:0> 1.empty? NoMethodError: undefined method `empty?' for 1:Fixnum from (irb):21 irb(main):022:0> "hello".empty? => false irb(main):023:0> "".blank? => true irb(main):024:0> User.find_by_id(1).blank? => true
Checking for empty? is like checking whether an array object, like a hash or a string does not have anything in it. A nil object cannot be checked for empty? because it is not an array; that would give us an error. An empty hash or string returns true, as expected. 1.empty? is not correct, because 1 is not an array. Checking for [1].empty? though, is applicable.
Another interesting method is blank?. This one is actually the combination of checking for a nil object or an empty array. Thus, “”.blank? is like “”.empty? and User.find_by_id(1).blank? is like User.find_by_id(1).nil?. Hope this clears things for you.
5. Populate your Database using Fixtures
The folder test/fixtures holds a yml representation for each of your models. Use them to define static data for your database and then use a task to drop, create, migrate and seed your database.
6. When You Are Deeply Messed With Your Associations, It’s Probably Time To Use Scopes
A scope (or a named_scope in previous rails versions), is a way to create ready made relations, that can pretty much simplify some of your model code. Imagine a scenario when you have created a user inventory that contains lots of inventory items. Each inventory item is actually a game item and describes the inventory that holds it. Now, an item can be equipped or not and can be a weapon, gloves, a helmet or anything else. The question is, “What is an efficient way to get a user’s items (or a single item), if they are equipped or not ?
Scopes is a very elegant way to do that. First, you would go to the InventoryItem model and create a scope that describes whether an item is equipped :
scope :equipped, where(:is_equipped => 1).includes(:game_item)
The attribute inventory_item.is_equipped specifies whether an item is equipped and also includes the game_item model within the returned object. If we now execute something like user.inventory_items.equipped, we would receive an array with all the equipped user items. Let’s take it a step further. We just want to receive an equipped helmet, or an equipped weapon. Thus, we create a new scope :
scope :item, lambda { |item_type|
joins(:game_item).
where("game_items.item_type = ?", item_type ).
limit(1)
}
We define a scope named item that is described by a lambda function. This one has an argument based on the item type and joins the game_item model in order to check for that value. We are now able to execute something like “user.equipped.item(‘Weapon’)” to get an equipped weapon. Pretty cool, isn’t it ?
7. If You Need Repetitive Non Model Functionality, Use Modules
There are times when we need to do the same things over and over, but in different modules. Moreover, the things we need to do are not really part of a particular model. This is most probably a good time to use a module. Modules are generally loaded from /lib. Be a bit cautious though. In Rails 3, the lib path does not autoload modules. You need to explicitly specify that in application.rb like :
# autoload lib modules
config.autoload_paths += %W(#{config.root}/lib)
Creating a module is really easy. You can just create an rb file with the name of your module (the name is used to load the module), or create a separate folder and store your module there. Let’s say that you need to create a utilities.rb module (you can omit the class if you like of course) :
module Utilities class Utils #get a random number for min,max range def self.rand_range(min,max) min + rand(max-min) end end end
From your other models, you just need to “include Utilities” and you can use these functions as if they were part of your model. But what if we have our module in a folder like “message_modules/private_message.rb” ? You create the module the same way, but you include it like :
include MessageModules::PrivateMessage
Rails converts MessageModules::PrivateMessage to message_modules/private_messag, locates your code and is now ready to use it.
8. Avoid Scaffolding In Your First Projects
Who isn’t aware of the good old create a blog in Rails in 15 minutes video ? That is probably why some of us started to learn Rails in the first place. While this video is really good in showing how quickly things can be done in Rails, it does all these things by scaffolding. While scaffolding is a great way to do CRUD (create, read, update, delete) models, controllers and views really fast, it can confuse a newcomer quite a lot. The reason is that scaffolding creates a whole new premade environment for you. If you are not really comfortable with its internals, it can be a bit devastating. To effectively understand scaffolding, you already need to be a seasoned Rails programmer, know about routes, redirects and more. That is why i would never suggest that somebody begins a project with scaffolding. Better start by creating your models, controllers, views and helpers explicitly and avoid scaffolding for now.
9. Use Partials For Views That Are Used In Many Places
Partials are simply templates that can be included from your main views. A partial can be anywhere inside your views folder. I prefer to create a partials folder and have subfolders for some of my partials. You can even pass variables through partials. However, that is never a good idea, since you are including business logic in your views, if you do that. This could be an include :
<%= render :partial => "partials/attack_display", :locals => { :attack_type => 'monster' } %>
This renders the view that resides in partials/_attack_display.erb and passes an attack_type = ‘monster’ variable (for the sake of this example, but never do that). The code inside _attack_display.erb is now displayed in place of this include.
10. Create Your Routes From Scratch
It’s a very good idea to create your routes yourself. Eventually, you will need to learn how Rails routing works, so it’s better to learn is fast. It’s pretty easy anyway. Do not just use the standard global Rails route for every controller/action/:id but rather include your own ones, even better with scopes like :
scope :path => '/pvp', :controller => :pvp do
match '/' => :index
match 'pvp_attack/:id' => :pvp_attack
end
This defines that the pvp_controller is responsible for a call to domain/pvp. Then, for no specified action(/), the index action is called. If domain/pvp/pvp_attack/7361 is called, this is handled by the action pvp_attack of the pvp controller and a param[:id] = 7361 is passed to the action.

























Very cool! Thanks for sharing!
You’re welcome
Number 1 saved me. Great explanation, thank you so much!
Nice job!
Hi, I have a few doubts in Ruby on rails since I am a novice in this language.
My first question, how do we pass random variables from one model to another.
Nehal, you do not pass variables between models. Each model represents a particular entity that is encapsulated. Take a look at the model view controller design pattern for more details.
Tip no. 4 – there’s nothing weird. for Ruby everything but false and nil is truth (0, “”, [], {}, ” etc.)
#nil? check if receiver is instance of NilClass.
(or empty)
#blank? check if receiver is .. blank
there’s also #present? (in Rails only) which check if receiver is not empty or nil
“(…) an object meets a certain condition, using the ? operand (…)” – what? methods with question mark are .. methods. Nothing special here
For Ruby ? and ! in method names are normal signs. That’s only convention that methods with ? returns boolean (true/false).
Hello @Krzysztof, thanx for the remarks. Yeah, ruby has its own way of doing things for sure.
For Tip 5, i was actually talking about static data(i mention it explicitly). FactoryGirl and the likes are mostly there to provide a way to create dynamic data where you do not need duplicate keys etc. For rspec, i also prefer FactoryGirl and have used it quite extensively.
One could also argue that seeds.db is even better than fixtures, and i would probably agree. Fixtures are slowly becoming a thing of the past with newer Rails versions.
I guess you have a typo on tip 3. The part where you are tackling views – “A view is where data is represented to the user. You should never (really, never) include logic inside your models.” What you probably mean is “inside your views.” ?
@Corix : Oops, missed that
Fixed it, thanx for mentioning it !
Definately appreciate no. 8 from personal experience! Great post for the beginner
nic 1.. i wanted to abt mod (%)… it behaves diffrntly when it comes to negative numbers..!!!
mind sharing what color settings you have for your irb console? that is a great color settings and perfect on my eyes.
@mike:
I use TotalTerminal with the Homebrew theme
@spyros Aw I am actually looking at the second set of screenshots which are at http://postimage.org/image/xy4v67mwr/ , do you know which scheme that is? Also although I change any color setting in terminal how does that impact the rails console scheme? thx mate!
@mike : The theme is Homebrew as I mentioned. I think that the rails console should inherit the theme that you use in your terminal. If not, take a look at this, it may help :
http://jetpackweb.com/blog/2011/01/20/pretty-paging-in-rails-console/