Trusted by
Hire Ruby on Rails developers and engineers
Victor Olteanu, United States
member since June 25, 2012
Victor has 13+ years experience working as a senior engineer and architect. His list of past clients includes a variety of successful startups and Fortune 100 companies. He is a great communicator and team player with strong understandings of business, UI, and all phases of software development. [click to continue...]
Mark Wong-VanHaren, Spain
member since March 22, 2013
Mark is an entrepreneur, engineer, CTO, and artisan with decades of start-up experience, including co-founding Excite.com. He makes complex problems simple with expressive, maintainable code. He believes in building small, well-tested, functional pieces, loosely joined by well-documented contract. [click to continue...]
Federico Dayan, Argentina
member since August 15, 2013
Federico is a passionate, senior, full-stack developer with more than a decade of experience working on the web ecosystem. He has extensive experience helping clients develop ideas and making them real. He believes that clean code and separation of concerns makes great software. [click to continue...]
Teng Siong Ong, United States
member since August 13, 2013
Teng is a developer and entrepreneur who has helped build applications that with millions of users. He started a company after his freshman year, which was later acquired. He has extensive experience working with early stage start-ups and helping them to build quick prototypes for market validation. [click to continue...]
Jake Varghese, United States
member since September 20, 2013
As an architect, Jake understands the process of solving complex problems that plague enterprise and medium size businesses. He is a full-stack problem solver--he can build entire apps from scratch or he can optimize an existing app already in the field. [click to continue...]
Joshua Ballanco, Turkey
member since November 22, 2013
Joshua is an architect, engineer, and scientist with experience building large-scale systems dealing with everything from massive amounts of video data to heavy web traffic to integration with a wide array of components in an SOA infrastructure. He's worked for Apple and AOL, and also led a group of 20+ consultants. [click to continue...]
Graham Powrie, United States
member since November 22, 2013
Graham is a designer and developer focused on creating custom web applications that automate and improve business processes, while remaining flexible for iteration. He's a full-stack developer who can deliver a complete product from start to finish individually, or alongside a team. [click to continue...]
Slobodan Kovacevic, Serbia
member since September 2, 2013
Slobodan is a senior web developer and programmer with over a decade of experience working on the web. He is passionate about Ruby and Ruby on Rails. He can work in different roles, ranging from an individual developer to technical team lead to project manager. [click to continue...]
João Paulo Lethier, Brazil
member since December 19, 2013
João is a retired basketball player and has been a web developer and coder since 2009. He has created a variety of complex web apps using Ruby on Rails. He enjoys reading books, watching movies, and playing sports. [click to continue...]
Kenneth Kalmer, South Africa
member since December 16, 2013
Kenneth is passionate about solving problems, especially in an elegant and sustainable manner. He loves learning about anything, especially things that make his better at his craft. He has been up and down the web stack for the last 15 years, and does not seeing himself stopping anytime soon. [click to continue...]
Eqbal Quran, Jordan
member since March 5, 2014
Eqbal is a senior full-stack developer with more than a decade of experience working in web and mobile development. He is a masterful problem solver, and boasts and extensive portfolio of finished professional products. [click to continue...]
Rafael Ernane Dalprá, Brazil
member since July 9, 2014
Rafael is an entrepreneur and developer with extensive experience in server management, leading teams, Ruby on Rails, and front-end development. He is highly motivated, creative, and efficient, with an eye for user experience. [click to continue...]
Mike Harris, United States
member since January 28, 2014
Mike is an experienced Ruby developer who also has real world experience in JavaScript, C#, C++, Java, and SQL. He has more than 10 years of experience in a wide variety of environments, including IT consulting, in-house web development/data architecture, and freelance contracting. [click to continue...]
A hiring guide

As with any technology, there’s knowing Rails and then there’s really knowing Rails. This guide offers a sampling of questions that are key to evaluating the breadth and depth of a candidate’s mastery of the language.

Testimonials
“Toptal understood our project needs immediately. We were matched with an exceptional freelancer from Argentina who, from Day 1, immersed himself in our industry, blended seamlessly with our team, understood our vision and produced top-notch results. Toptal makes connecting with superior developers and programmers very easy.”
Jason Kulik
Co-Founder @ ProHatch
“We needed a talented developer and we needed him/her very quickly. So we turned to Toptal and couldn't be happier with the results! Our Toptal freelancer has contributed extraordinary knowledge, talent, and startup experience to our team. We will continue to work with Toptal to fulfill our future talent needs.”
Lindsay Fairman
Founder & Owner @ FairTech Labs, LLC
“We used Toptal to hire a developer with extensive Amazon Web Services experience. The process was quick and effective. We interviewed four candidates one of which turned out to be a great fit for our requirements. We plan to use Toptal again in the future and would recommend their services.”
Abner Guzmán Rivera
CTO and Chief Scientist @ PhotoKarma, Inc.
“Working with Marcin is a joy, I can't find a better word. He is competent, professional, flexible, and extremely quick to understand what is required -- and to implement it -- even if the source code that's given to him is, shall we say, less than optimally elegant and clear. Oh and he has the same sense of humour as me. ;)”
André Fischer
CTO @ App Promotions
“Dario was recently assigned to our company in order to help with PHP and JW Video player refinements. He listens well and offers common sense suggestions that save both time and money. Dario speeds up the process by asking questions and has delivered our first project on time. His redesigned player offers a very pleasing appearance and delivers functions that are both ergonomic and intuitive.”
Dennis B. Jacobs
President @ College TV Ticket
“Toptal offers a no-compromise solution to businesses undergoing rapid development and scale. Every engineer we've contracted through Toptal has quickly integrated into our team and held their work to the highest standard of quality while maintaining blazing development speed.”
Greg Kimball
Co-Founder @ Nifti
“The task of finding and hiring the right developers and programmers can be daunting, especially for startups. After sifting through countless unfit freelancers, we came across Toptal. They were able to fill our open position in no time, and I'd highly recommend the service!”
Josef Holm
CEO @ Tubestart
“We've used Toptal developers multiple times for multiple projects, and they've always been world-class—regardless of whether they've been from South Africa, Brazil, or the United States.”
Alex Haro
CEO @ Life360
“Toptal’s ability to rapidly match our project with the best developers was just superb! The developers have become part of our team, and I’m amazed of the level of professional commitments each one of them have demonstrated. For those looking to work remotely with the best engineers, look no further. Thank you, Toptal.”
laurent Alis
Founder @ Livepress
“After my hard drive crashed, I needed a quick script to recover my data, which was crucial to my research. After almost three weeks struggling with freelancers, I was ready to try Toptal. It turned out to be the right move: even if a little more expensive, my developer, Chatri, was highly punctual and got the job done in a quick, painless, and focused manner. Thanks, Chatri!”
Rob Ellis
“The developers I was paired with were incredible—smart, driven, and responsive. It used to be hard to find quality engineers and consultants. Now it isn't.”
Ryan Rockefeller
CEO @ Radeeus
“Working with Enrique has been a pleasure and a relief. His knowledge in the IT space is broad and in-depth. Zoomedia has been in need of this level of support for some time and I feel confident we are an exponentially stronger team with Enrique on board.”
Justin Bane
Senior Technical Lead @ Zoomedia
“We have been incredibly happy with our Toptal experience. Initially a sceptic, the process to find and recruit a fabulous iOS developer was very easy. Rather than sifting through hundreds of CVs, we saw two and hired them. They have worked effectively, getting up to speed incredibly quickly and have almost become part of the team. We would definitely use Toptal again. ”
James O'Day
“I couldn’t have been more pleased with Toptal. These guys are professional, quick, well priced, and fun! I will be using them again for my next project, and the next, and the next, and the next.”
Mac Smith
President @ New Texas Internet MGT
“Toptal's developers and architects have been both very professional and easy to work with. The solution they produced was fairly priced and top quality, reducing our time to launch. Thanks again, Toptal.”
Jeremy Wessels
CEO @ Kognosi
“While looking for a high-level Python/Django developer, I found Toptal via a simple Google search, and that was a stroke of luck for our company. We needed a expert engineer who could start on our project immediately as we had a tight deadline. We were introduced to Simanas and immediately knew he was a great choice who had already been vetted... and he exceeded our expectations with his work. Not having to interview and chase down an expert developer was an excellent time-saver and made everyone feel more comfortable with our choice to switch platforms to utilize a more robust language. Toptal made the process easy and convenient, and we are extremely happy with the results. Toptal is now the first place we look for expert-level help.”
Derek Minor
Hire a top Ruby on Rails developer now
Toptal is a marketplace for top Ruby on Rails developers, engineers, programmers, coders, architects, and consultants. Top companies and start-ups choose Toptal freelancers for their mission critical software projects.
Full
profile
Victor OlteanuUnited States
Victor has 13+ years experience working as a senior engineer and architect. His list of past clients includes a variety of successful startups and Fortune 100 companies. He is a great communicator and team player with strong understandings of business, UI, and all phases of software development.
[click to continue…]Hire
Full
profile
Mark Wong-VanHarenSpain
Mark is an entrepreneur, engineer, CTO, and artisan with decades of start-up experience, including co-founding Excite.com. He makes complex problems simple with expressive, maintainable code. He believes in building small, well-tested, functional pieces, loosely joined by well-documented contract.
[click to continue…]Hire
Full
profile
Federico DayanArgentina
Federico is a passionate, senior, full-stack developer with more than a decade of experience working on the web ecosystem. He has extensive experience helping clients develop ideas and making them real. He believes that clean code and separation of concerns makes great software.
[click to continue…]Hire
Full
profile
Teng Siong OngUnited States
Teng is a developer and entrepreneur who has helped build applications that with millions of users. He started a company after his freshman year, which was later acquired. He has extensive experience working with early stage start-ups and helping them to build quick prototypes for market validation.
[click to continue…]Hire
Full
profile
Jake VargheseUnited States
As an architect, Jake understands the process of solving complex problems that plague enterprise and medium size businesses. He is a full-stack problem solver--he can build entire apps from scratch or he can optimize an existing app already in the field.
[click to continue…]Hire
Full
profile
Joshua BallancoTurkey
Joshua is an architect, engineer, and scientist with experience building large-scale systems dealing with everything from massive amounts of video data to heavy web traffic to integration with a wide array of components in an SOA infrastructure. He's worked for Apple and AOL, and also led a group of 20+ consultants.
[click to continue…]Hire
Full
profile
Graham PowrieUnited States
Graham is a designer and developer focused on creating custom web applications that automate and improve business processes, while remaining flexible for iteration. He's a full-stack developer who can deliver a complete product from start to finish individually, or alongside a team.
[click to continue…]Hire
Full
profile
Slobodan KovacevicSerbia
Slobodan is a senior web developer and programmer with over a decade of experience working on the web. He is passionate about Ruby and Ruby on Rails. He can work in different roles, ranging from an individual developer to technical team lead to project manager.
[click to continue…]Hire
Full
profile
João Paulo LethierBrazil
João is a retired basketball player and has been a web developer and coder since 2009. He has created a variety of complex web apps using Ruby on Rails. He enjoys reading books, watching movies, and playing sports.
[click to continue…]Hire
Full
profile
Kenneth KalmerSouth Africa
Kenneth is passionate about solving problems, especially in an elegant and sustainable manner. He loves learning about anything, especially things that make his better at his craft. He has been up and down the web stack for the last 15 years, and does not seeing himself stopping anytime soon.
[click to continue…]Hire
Full
profile
Eqbal QuranJordan
Eqbal is a senior full-stack developer with more than a decade of experience working in web and mobile development. He is a masterful problem solver, and boasts and extensive portfolio of finished professional products.
[click to continue…]Hire
Full
profile
Rafael Ernane DalpráBrazil
Rafael is an entrepreneur and developer with extensive experience in server management, leading teams, Ruby on Rails, and front-end development. He is highly motivated, creative, and efficient, with an eye for user experience.
[click to continue…]Hire
Full
profile
Mike HarrisUnited States
Mike is an experienced Ruby developer who also has real world experience in JavaScript, C#, C++, Java, and SQL. He has more than 10 years of experience in a wide variety of environments, including IT consulting, in-house web development/data architecture, and freelance contracting.
[click to continue…]Hire
Testimonials
“Toptal understood our project needs immediately. We were matched with an exceptional freelancer from Argentina who, from Day 1, immersed himself in our industry, blended seamlessly with our team, understood our vision and produced top-notch results. Toptal makes connecting with superior developers and programmers very easy.”
Jason Kulik
Co-Founder @ ProHatch
“We needed a talented developer and we needed him/her very quickly. So we turned to Toptal and couldn't be happier with the results! Our Toptal freelancer has contributed extraordinary knowledge, talent, and startup experience to our team. We will continue to work with Toptal to fulfill our future talent needs.”
Lindsay Fairman
Founder & Owner @ FairTech Labs, LLC
“We used Toptal to hire a developer with extensive Amazon Web Services experience. The process was quick and effective. We interviewed four candidates one of which turned out to be a great fit for our requirements. We plan to use Toptal again in the future and would recommend their services.”
Abner Guzmán Rivera
CTO and Chief Scientist @ PhotoKarma, Inc.
“Working with Marcin is a joy, I can't find a better word. He is competent, professional, flexible, and extremely quick to understand what is required -- and to implement it -- even if the source code that's given to him is, shall we say, less than optimally elegant and clear. Oh and he has the same sense of humour as me. ;)”
André Fischer
CTO @ App Promotions
“Dario was recently assigned to our company in order to help with PHP and JW Video player refinements. He listens well and offers common sense suggestions that save both time and money. Dario speeds up the process by asking questions and has delivered our first project on time. His redesigned player offers a very pleasing appearance and delivers functions that are both ergonomic and intuitive.”
Dennis B. Jacobs
President @ College TV Ticket
“Toptal offers a no-compromise solution to businesses undergoing rapid development and scale. Every engineer we've contracted through Toptal has quickly integrated into our team and held their work to the highest standard of quality while maintaining blazing development speed.”
Greg Kimball
Co-Founder @ Nifti
“The task of finding and hiring the right developers and programmers can be daunting, especially for startups. After sifting through countless unfit freelancers, we came across Toptal. They were able to fill our open position in no time, and I'd highly recommend the service!”
Josef Holm
CEO @ Tubestart
“We've used Toptal developers multiple times for multiple projects, and they've always been world-class—regardless of whether they've been from South Africa, Brazil, or the United States.”
Alex Haro
CEO @ Life360
“Toptal’s ability to rapidly match our project with the best developers was just superb! The developers have become part of our team, and I’m amazed of the level of professional commitments each one of them have demonstrated. For those looking to work remotely with the best engineers, look no further. Thank you, Toptal.”
laurent Alis
Founder @ Livepress
“After my hard drive crashed, I needed a quick script to recover my data, which was crucial to my research. After almost three weeks struggling with freelancers, I was ready to try Toptal. It turned out to be the right move: even if a little more expensive, my developer, Chatri, was highly punctual and got the job done in a quick, painless, and focused manner. Thanks, Chatri!”
Rob Ellis
“The developers I was paired with were incredible—smart, driven, and responsive. It used to be hard to find quality engineers and consultants. Now it isn't.”
Ryan Rockefeller
CEO @ Radeeus
“Working with Enrique has been a pleasure and a relief. His knowledge in the IT space is broad and in-depth. Zoomedia has been in need of this level of support for some time and I feel confident we are an exponentially stronger team with Enrique on board.”
Justin Bane
Senior Technical Lead @ Zoomedia
“We have been incredibly happy with our Toptal experience. Initially a sceptic, the process to find and recruit a fabulous iOS developer was very easy. Rather than sifting through hundreds of CVs, we saw two and hired them. They have worked effectively, getting up to speed incredibly quickly and have almost become part of the team. We would definitely use Toptal again. ”
James O'Day
“I couldn’t have been more pleased with Toptal. These guys are professional, quick, well priced, and fun! I will be using them again for my next project, and the next, and the next, and the next.”
Mac Smith
President @ New Texas Internet MGT
“Toptal's developers and architects have been both very professional and easy to work with. The solution they produced was fairly priced and top quality, reducing our time to launch. Thanks again, Toptal.”
Jeremy Wessels
CEO @ Kognosi
“While looking for a high-level Python/Django developer, I found Toptal via a simple Google search, and that was a stroke of luck for our company. We needed a expert engineer who could start on our project immediately as we had a tight deadline. We were introduced to Simanas and immediately knew he was a great choice who had already been vetted... and he exceeded our expectations with his work. Not having to interview and chase down an expert developer was an excellent time-saver and made everyone feel more comfortable with our choice to switch platforms to utilize a more robust language. Toptal made the process easy and convenient, and we are extremely happy with the results. Toptal is now the first place we look for expert-level help.”
Derek Minor

The Insider's Guide to Ruby on Rails Interviewing

The Technology

Just as France’s Train à Grande Vitesse (TGV) (traveling at speeds of up to 320 km/h) dramatically reduces travel time for modern day rail passengers, Ruby on Rails (a.k.a. “Rails”) substantially reduces the time and effort required to build powerful web applications. Tim O’Reilly (founder of O’Reilly Media) refers to Rails as breakthrough technology and Gartner Research noted in a recent study that many high-profile companies are using Rails to build agile, scalable web applications.

The rate at which Rails has gained popularity is noteworthy, with estimates of over 200,000 web sites currently built with the technology. Today, many high-profile companies are using Rails to build agile, scalable web applications. Examples include Twitter, GitHub, Yammer, Scribd, Groupon, Shopify, and Basecamp, to name but a few.

Rails is a framework for web application development, written in Ruby, that also features its own routing system independent of the web server. The goal of Rails is to significantly simplify the development of web applications, requiring less code and time than would otherwise be required to accomplish the same tasks.

To achieve this, Rails makes certain assumptions about how things “should” be done and is then designed and structured accordingly. While imbibing this “Rails view of the world” can sometimes be a bit of a culture shock for developers strongly grounded in other languages and frameworks, over time most come to greatly appreciate the Rails approach and the productivity that it engenders.

The Challenge

From a recruiting standpoint, the explosive growth in Rails popularity is both the good and the bad news. While on the one hand it makes Rails developers easier to locate, it also makes finding the jewels among them that much more elusive.

Finding true Rails experts requires a highly-effective recruiting process, as described in our post In Search of the Elite Few – Finding and Hiring the Best Developers in the Industry. Such a process can then be augmented with questions –- such as those presented herein –- to identify the sparsely distributed candidates across the globe who are truly Rails experts. The manifold benefits of finding them will likely be realized in the productivity and results that they will be able to achieve.

Yeah, I know Rails…

The extent to which Rails streamlines and simplifies the development of web applications can mislead neophyte developers into underestimating its capabilities and oversimplifying its conceptual underpinnings. While Rails is relatively easy to use, it is anything but simplistic.

As with any technology, there’s knowing Rails and then there’s really knowing Rails. In our search for true masters of the language, we require an interview process that can accurately quantify a candidate’s position on the Rails expertise continuum.

Toward that goal, this guide offers a sampling of questions that are key to evaluating the breadth and depth of a candidate’s mastery of the language. It is important to bear in mind, though, that these sample questions are intended merely as a guide. Not every “A” candidate worth hiring will be able to properly answer them all, nor does answering them all guarantee an “A” candidate. At the end of the day, hiring remains as much of an art as it does a science.

Frequent Rail Traveler?

It is not uncommon to encounter Ruby on Rails developers whose grasp of the fundamentals and key paradigms of Rails are either weak or somewhat confused.

Questions that can help assess a developer’s grasp of the Rails foundation, including some of its more subtle nuances, are therefore an important component of the interview process.

Here are some examples:

Q: Explain the processing flow of a Rails request.

At the highest level, Rails requests are served through an application server, which is responsible for directing an incoming request into a Ruby process. Popular application servers that use the Rack web request interface include Phusion Passenger, Mongrel, Thin, and Unicorn.

Rack parses all request parameters (as well as posted data, CGI parameters, and other potentially useful bits of information) and transforms them into a big Hash (Ruby’s record / dictionary type). This is sometimes called the env hash, as it contains data about the environment of the web request.

In addition to this request parsing, Rack is configurable, allowing for certain requests to be directed to specific Rack apps. If you want, for example, to redirect requests for anything in your admin section to another Rails app, you can do so at the Rack level. You can also declare middleware here, in addition to being able to declare it in Rails.

Those requests that are not directed elsewhere (by you in Rack) are directed to your Rails app where it begins interacting with the Rails ActionDispatcher, which examines the route. Rails apps can be spit into separate Rails Engines, and the router sends the request off to the right engine. (You can also redirect requests to other Rack compatible web frameworks here.)

Once in your app, Rails middleware – or your custom middleware – is executed. The router determines what Rails controller / action method should be called to process the request, instantiates the proper controller object, executes all the filters involved, and finally calls the appropriate the action method.

Further detail is available in the Rails documentation.

Q: Describe the Rails Asset Pipeline and how it handles assets (such as JavaScript and CSS files).

Rails 3.1 introduced the Asset Pipeline, a way to organize and process front-end assets. It provides an import/require mechanism (to load dependent files) that provides many features. While the Asset Pipeline does have its rough edges, it does solve and provide many of the modern best practices in serving these files under HTTP 1.1. Most significantly, the Asset Pipeline will:

  • Collect, concatenate, and minify all assets of each type into one big file
  • Version files using fingerprinting to bust old versions of the file in browser caches

The Asset Pipeline automatically brings with it Rails’ selection of Coffeescript as its JavaScript pre-processed / transpiled language of choice and SASS as its CSS transpiled language. However, being an extensible framework, it does allow for additional transpiled languages or additional file sources. For example, Rails Assets brings the power of Bower to your Rails apps, allowing you to manage third-party JavaScript and CSS assets very easily.

Q: What is Active Record and what is Arel? Describe the capabilities of each.

Active Record was described by Martin Fowler in his book Patterns of Enterprise Application Architecture as “an object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data”.

ActiveRecord is both an Object Relational Mapping (ORM) design pattern, and Rails’ implementation of that design pattern. This means that fetching, querying, and storing your objects in the database is as much a part of the API of your objects as your custom business logic. A developer may see this as an undesired side effect, or as a welcome convention, depending on their preference and level of experience.

Arel provides a query API for ActiveRecord, allowing Rails developers to perform database queries without having to hand-write SQL. Arel creates lazily-executed SQL whereby Rails waits until the last possible second to send the SQL to the server for execution. This allows you to take an Arel query and add another SQL condition or sort to the query, right up to the point where Rails actually executes the query. Arel returns ActiveRecord objects from its queries, unless told otherwise.

Q: What is the Convention over Configuration pattern? Provide examples of how it is applied in Rails.

Convention over Configuration (CoC) is a software design pattern by which only the unconventional aspects of an application need to be specified by a developer. When the default convention matches the desired behavior, the default behavior is followed without any configuration being required. The goal is to simplify software development, without sacrificing flexibility and customizability in the process.

Here are some examples of how CoC principles are applied in Rails:

  • Model and database table naming. Rails automatically pluralizes class names to find the respective database tables. For a class Book, for example, it will expect a database table named books. For class names composed of multiple words, the model class name should employ CamelCase (e.g., BookClub and book_clubs).
  • Primary and foreign keys. By default, Rails uses an integer column named id as the table’s primary key. Foreign key names by default follow the pattern of appending _id to the singularized tablename (e.g., item_id for a foreign key into the items table).
  • Reserved words for automatic functionality. There are also some optional column names which, if used, automatically add features and functionality to Rails database tables. created_at, for example, will automatically be set to the date and time when the record was created. Similarly, updated_at will automatically be set to the date and time whenever the record was last updated.
  • Auto-loading of class definitions. Auto-loading is the “magic” by which classes appear to be accessible from anywhere, without the need to explicitly require them. Here’s how it works: When you reference a class in your code, Rails takes the class name (with namespace) as a string, calls underscore on it, and looks for a file with that name (in all directories specified in your config.autoload_paths). For example, if you reference a class named FileHandling::ZipHandler, Rails will automatically search for file_handling/zip_handler.rb in your config.autoload_paths. This feature often results in novice Rails programmers thinking that they don’t need to explicitly require referenced classes and that Rails will just auto-magically find them anyway. They then become baffled when they don’t follow this convention and are suddenly being told by Rails that their classes can’t be found.

It is important to note that CoC specifies a default –- but not immutable –- convention. Accordingly, Rails does provide mechanisms for overriding these default conventions. As an example, the default database table naming scheme mentioned above can be overridden by specifying the ActiveRecord::Base.table_name as shown here:

class Product < ActiveRecord::Base
  self.table_name = "LEGACY_PRODUCT_TABLE"
end

Q: What is the “fat model, skinny controller” approach? Discuss some of its advantages and pitfalls, as well as some alternatives.

“Fat model skinny controller” is an MVC-based Rails design pattern.

MVC is itself a software design pattern that separates a system into three separate and distinct layers; namely, Model, View, and Controller. MVC strives to ensure a clean separation between each of its layers through clearly defined APIs. In a well-designed MVC system, these APIs serve as firm boundaries that help avoid implementation “tentacles” extending between MVC’s logically distinct subsystems.

The “Fat model skinny controller” design pattern advocates placing as much logic as possible in the Model for (a) maximum reuse and (b) code that is easier to test.

That said, a common pitfall for Rails developers is to end up with “overly bloated” models by adhering too blindly to the “fat model, skinny controller” paradigm. The infamous User model is a prime example of this. Since many Rails apps are about the user entering data into the system, or sharing information with their friends socially, the user model will often gain more and more methods, eventually reaching the point where the user.rb model becomes bulky and unmanageable in size.

A few key alternatives worth considering include:

  • Use of other objects: Extract functionality out of models into other objects (such as Decorators or Service objects)
  • Hexagonal architecture for Rails: Employ a hexagonal architecture that views the application as a hexagon, each side of which represents some sort of external interaction the application needs to have.
  • DCI (Data Context Interaction): Instead of focusing on individual objects, focus on the communication and interactions between data and its context.

Q: Describe the Rails testing philosophy.

Rails built testing support in from the beginning of the framework, and it became a part of the culture. As a result, there are a plethora of tools available for testing in the Rails environment.

By default, Rails 4.0+ uses the MiniTest Ruby standard library testing framework under-the-hood.

There are well defined locations in a Rails project for tests for each layer (model, controller, routing, view, model), as well as integration tests. Because of the MVC foundation of Rails, often these layers (with the exception of integration tests) can be tested without reliance on the other layers.

For example, we can create a database record, before the test runs, that contains the attributes we expect the test to return. Our test can focus on making sure our show post controller action retrieves the post we want it to by checking to see if it returns the object we created above as expected. If not, something went wrong or our code must have a bug. Here’s an example of such a test:

class PostsControllerTest < ActionController::TestCase
  setup do
    @post = posts(:one)
  end

  test "should show post" do
    get :show, id: @post
    assert_response :success
  end
end

Integration tests (often called Feature tests) will usually drive the application as if a user is clicking buttons, using testing tools like Capybara (which can simulate user actions in a variety of manners, including driving embedded WebKit, or using Selenium).

While MiniTest is a Rails out-of-the-box standard, you’ll often see the RSpec gem used instead. This provides a Domain Specific Language for testing that may make it more natural to read than MiniTest.

Some Rails projects use the Cucumber testing framework to describe software behavior in plain English sentences. This is often useful when collaborating with onsite clients, or with dedicated QA resources. In the ideal world, these non-developers can write automated integration tests without having to see a line of Ruby code.

Down on the tracks

Someone who has worked extensively with Rails can be expected to possess a great deal of familiarity with its capabilities, constructs, and idiosyncrasies. These questions demonstrate ways of gauging the extent and depth of this expertise.

Q: Explain the use of yield and content_for in layouts. Provide examples.

yield identifies where content from the view should be inserted. The simplest approach is to have a single yield, into which the entire contents of the view currently being rendered is inserted, as follows:

<html>
  <head>
  </head>
  <body>
    <%= yield %>
  </body>
</html>

You can also create a layout with multiple yielding regions:

<html>
  <head>
        <%= yield :head %>
  </head>
  <body>
        <%= yield %>
  </body>
</html>

The main body of the view will always render into the unnamed yield. To render content into a named yield, use the content_for method. content_for allows for insertion of content into a named yield block in a layout. This can be helpful with layouts that contain distinct regions, such as sidebars and footers, into which distinct blocks of content are to be inserted. It can also be useful for inserting tags that load page-specific JavaScript or CSS files into the header of an otherwise generic layout.

Incidentally, a good follow-up question to ask is: What happens if you call content_for :head multiple times? The answer is that all of the values get concatenated.

Q: What are N+1 queries, and how can you avoid them?

Consider the following code, which finds 10 clients and prints their postal codes:

clients = Client.limit(10)
clients.each do |client|
  puts client.address.postcode
end

This code actually executes 11 queries; 1 (to find 10 clients) and then 10 more (one per each client to load its address). This is referred to as an “N+1 query” (where in the case of this example, N is 10).

Eager loading is the mechanism for loading the associated records of the objects returned by Model.find using as few queries as possible.

Active Record’s eager loading capability makes it possible to significantly reduce the number of queries by letting you specify in advance all the associations that are going to be loaded. This is done by calling the includes (or preload) method on the Arel (ActiveRecord::Relation) object being built. With includes, Active Record ensures that all of the specified associations are loaded using the minimum possible number of queries.

We could therefore rewrite the above code to use the includes method as follows:

clients = Client.includes(:address).limit(10)
clients.each do |client|
  puts client.address.postcode
end

This revised version of this code will execute just 2 queries, thanks to eager loading, as opposed to 11 queries in the original version.

Q: What are “filters” in Rails? Describe the three types of filters, including how and why each might be used, and the order in which they are executed. Provide examples.

Filters are essentially callback methods that are run before, after, or “around” a controller action:

  • Before filter methods are run before a controller action and therefore may halt the request cycle. A common before filter is one which requires a user to be logged in for an action to be performed.
  • After filter methods are run after a controller action and therefore cannot stop the action from being performed but do have access to the response data that is about to be sent to the client.
  • Around filter methods are “wrapped around” a controller action. They can therefore control the execution of an action as well as execute code before and/or after the action is performed.

For example, in a website where changes have an approval workflow, an administrator could be able to preview them easily with an around filter as follows:

class ChangesController < ApplicationController
  around_action :wrap_in_transaction, only: :show

  private

  def wrap_in_transaction
        ActiveRecord::Base.transaction do
          begin
            yield
          ensure
            raise ActiveRecord::Rollback
          end
        end
  end
end

Note that an around filter also wraps rendering. In particular, in the example above, if the view reads from the database (e.g., via a scope), it will do so within the transaction and thus present the data to preview. You can also choose not to yield and build the response yourself, in which case the action will not be run.

The order of execution is a bit tricky and is important to understand clearly. Filter methods execute in the following order:

  1. Before filter methods, in order of definition.
  2. Around filter methods, in order of definition.
  3. After filter methods, in reverse order.

Also, because of the way Ruby instantiates classes, the filter methods of a parent class’ before will be run before those of its child classes.

Q: What is Rack middleware? How does it compare to controller filters/actions?

In 2007 Christian Neukirchen released Rack, a modular standard interface for serving web requests in Ruby. Rack is similar to other similar mechanisms in other languages, such as WSGI on the Python side, or Java Servlets, or Microsoft’s Internet Server Application Programming Interface (ISAPI).

Before requests are processed by your Rails action method, they go through various Rack middleware functions declared by Rails or by the developer. Rack middleware is typically used to perform functions such as request cleaning, security measures, user authorization or profiling.

You can see a list of available middleware components (both developer defined and those defined by Rails) by running rake middleware on the command line.

A key distinction between Rack middleware and filters is that Rack middleware is called before Rails does its routing and dispatching, whereas filters are invoked after this routing has occurred (i.e., when Rails is about to call your controller action method). As such, its is advantageous to filter out requests to be ignored in middleware whenever possible, such as requests from common attack URLs (phpadmin.php requests, for example, can be discarded in middleware, as they will never resolve in a Rails app and is probably just some attempt to hack the site.)

Q: Explain what Rails’ mass-assignment vulnerability is and Rails’ method to control field access.

When the user performs a post (such as, for example, creating a new User) Rails needs to save all that new data into the database. This data is accessible from your Rails action via the params Hash.

Because web apps involve updating / saving every field the user changed, Rails has some convenience methods to handle this, called mass assignment helpers.

For example, prior to Rails 4, creating a new User object with parameters from a submitted form looked like:

User.create(params[:user])

params[:user] will contain keys for the elements the user entered on the form. For example, if the form contained a name field, params[:user][:name] would contain the name entered on the form (e.g., “Jeff Smith”).

Convention vs. configuration strikes again here: name is the name of both the input element in the form and the name of the column in the database.

In addition to the create method, you can update a record the same way:

@user = User.find(params[:id])
@user.update_attributes(params[:user])

But what happens when a hacker goes in and edits your HTML form to add new fields? They may, for example, guess that you have an is_admin field, and add it to the HTML form field themselves. Which now means that – even though you didn’t include it on the form that’s served to users – your hacker has gone in and made themselves an admin on your site!

This is referred to as mass assignment vulnerability; i.e., assigning all these fields with no filtering en masse, just trusting that the only field names and values will be those that were legitimately on the HTML form.

Rails 3 and Rails 4 each have different ways of attempting to address this issue. Rails 3 attempted to address it via attr_protected / attr_accessible controls at the model level, while Rails 4 addresses it via strong parameters and a filtering mechanism at the controller level. Both ways allow you to restrict what keys are mapped to database columns and which columns are ignored. Using these mechanisms, in the prior is_admin example, you can set the is_admin field to only change when code explicitly modifies the field value, or only allow it to be changed in certain situations.

The Big Picture

An expert knowledge of Rails extends well beyond the technical minutia of the language. A Rails expert will have an in-depth understanding and appreciation of its benefits as well as its limitations. Accordingly, here are some sample questions that can help assess this dimension of a candidate’s expertise.

Q: Why do some people say “Rails can’t scale”?

Twitter was one of the first extremely high profile sites to use Rails. In roughly the 2006-2008 timeframe, the growth rate of Twitter made server errors (“fail whale”) appearances a very common occurrence for users, prompting users and tech pundits to lay blame at Rails’ feet. As is true with any software, the causes of scalability issues can be complex and multi-faceted. Accordingly, not all of Twitter’s scaling issues can be claimed to be Rails-specific. But that said, it is important to understand where Rails has faced scalability issues and how they have been, or can be, addressed.

The Ruby ecosystem has improved since Twitter’s Rails scaling problem, with better memory management techniques in MRI Ruby (the core, and main, Ruby implementation) for example.

Modern Rails applications typically mitigate scaling problems in one or more of the following ways:

  • Implementing caching solutions (Rails 4 introduces good advances here)
  • Leveraging (or implementing) server or platform solutions with automatic scaling built in
  • Profiling costly operations and moving them out of Ruby or out of one monolithic Rails app
  • Placing some operations in a background / worker queue to be completed at a later time (e.g., perform an export operation asynchronously, notifying the user by email with a download link when the export is completed)

While there has traditionally been a one-to-one mapping between websites and Rails app (i.e., one website = one Rails app), there’s been an increasing movement towards more of a Service Oriented Architecture (SOA) approach whereby performance critical parts of the app are split off into new/separate apps which the main app usually talks to via web service calls. There are numerous advantages to this approach. Perhaps most noteworthy is the fact that these independent services can employ alternate technologies as appropriate; this might be a lightweight / more responsive solution in Ruby, or services written in Scala (as in Twitter’s case), or Node.js, Clojure, or Go.

But writing separate services isn’t the only way to speed up a Rails app. For example, Github has an interesting article on how it profiled Rails and ended up implementing a set of C apis for performing text escaping on the web.

Q: When is Rails a good choice for a project?

Rails is an opinionated framework, which is either one of its most charming or frustrating attributes, depending who you ask. Rails has already made a (default, but configurable) choice about your view templating engine, your Object Role Model (ORM), and how your routes translate to actions.

As a result of these choices, Rails is a great choice for a project where your application has total control over its own database, mostly returns HTML (or at least doesn’t solely return JSON), and for the most part displays data back to the users consistently with the way it is stored.

Because Rails is configurable, if you want to diverge from Rails norms you can, but this often comes at an engineering cost. Want to hook into an existing MS SQL database? You can do that, but you’ll hit some bumps along the way. Want to build a single page app with Rails, returning mostly JSON object? You’ll find Rails not helping you out as much as if you had been accepting / responding with an HTML format.

Q: What are some of the drawbacks of Rails?

Rails is generally meant for codebases of greater than a few hundred lines of code, and that primarily work with its own database objects. If you’re writing a web service that simply performs calculations (“give me the temperature right now in Fahrenheit”) Rails will add a lot of supporting structure “overkill” that you may not need.

Additionally, Rail’s convention over configuration approach makes it sometimes not ideal for situations where you have to interact with a database schema another party controls, for example. Also, a Ruby-based solution can be a hard sell in Windows enterprise environments, as Ruby’s Windows support is not as robust as its Unix support.

Like Python, the concurrency story in the default Ruby implementation (MRI; a.k.a. CRuby) is somewhat hobbled by a Global Interpreter Lock (GIL), which in broad strokes means only one thread can execute Ruby code at a time. (JRuby and Rubinius, other implementations of Ruby, have no GIL.

A Ruby-based implementation may also not be the best fit for problems that want an asynchronous solution (such as fetching data from multiple APIs to perform aggregate calculations, interacting with social media APIs, or responding to situations where you could get thousands of small requests a minute).

Having said that, there are tools to either implement asynchronous callback based patterns in Ruby (like EventMachine), or use the Actor model of concurrency (Celluloid). And of course there are a number of background worker mechanisms if your problem fits in that space.

And finally… Ruby Rookie or Gemologist?

Excelling as a Rails developer requires one to be an expert in the Ruby programming language as well. Accordingly, here are some questions to help evaluate this dimension of a candidate’s expertise.

Q: What are Ruby mixins, how do they work, and how would you use them? What are some advantages of using them and what are some potential problems? Give examples to support your answers.

A “mixin” is the term used in Ruby for a module included in another class. When a class includes a module, it thereby “mixes in” (i.e., incorporates) all of its methods and constants. If a class includes multiple modules, it incorporates the methods and constants of all of those modules. Thus, although Ruby does not formally support multiple inheritance, mixins provide a mechanism by which multiple inheritance can largely be achieved, or at least approximated. (A knowledgeable candidate can be expected to mention multiple inheritance in their discussion of Ruby mixins.)

Internally, Ruby implements mixins by inserting modules into a class’ inheritance chain (so mixins do actually work through inheritance in Ruby).

Consider this simple example:

module Student
  def gpa
    # ...
  end
end

class DoctoralStudent
  include Student
  def thesis
    # ...
  end
end

phd = DoctoralStudent.new

In this example, the methods of the Student class are incorporated into DoctoralStudent class, so the phd object supports the gpa method.

It is important to note that, in Ruby, the require statement is the logical equivalent of the include statement in other languages. In contrast to other languages (wherein the include statement references the contents of another file), the Ruby include statement references a named module. Therefore:

  • The module referenced by an include statement may either be in the same file (as the class that is including it) or in a different file. If in a different file, a require statement must also be used to properly incorporate the contents of that file.
  • A Ruby include makes a reference from the class to the included module. As a result, if the definition of a method in the included module is modified, even at runtime, all classes that include that module will exhibit the new behavior when that method is invoked.

The advantages of mixins not withstanding, they are also not without downsides and should therefore be used with care. Some potential pitfalls include:

  • Instance variable name collisions. Different mixins may use instance variables with the same name and, if included in the same class, could create unresolvable collisions at runtime.
  • Silent overriding of methods. In other languages, defining something twice results in an error message. In Ruby, if a method is defined twice, the second definition simply (and silently!) overwrites the first definition. Method name clashes across multiple mixins in Ruby are therefore not simple errors, but instead can introduce elusive and gnarly bugs.
  • Class bloat. The ease-of-use of mixins can also lead to their “abuse”. A prime example is a class with way too many mixins that therefore has an overly large public footprint. The rules of coupling and cohesion start to come into play, and you can end up with a system where changes to a module that’s frequently included can have disastrous effects. Traditional inheritance or composition is much less prone to this type of bloat. Quite often extracting parts of a class into modules that are mixed in is akin to cleaning your room by putting the mess into large bins. It looks clean until you start opening the bins.

Q: Compare and contrast Symbols and Strings in Ruby? Why use one vs. the other?

Symbols are singleton based on value, immutable, non-garbage collected objects. Strings, however, create multiple objects even if they share a value, are mutable, and are garbage collected when the system is done with the object.

Since symbols are singleton based on value (there is only one symbol object for a value, even if it appears multiple times in a program), this makes it trivial to compare whether two symbols are the same (Ruby basically just needs to compare their object_id values). Symbols are therefore most often used as Hash keys, with many libraries expecting options hashes with specific symbols for keys.

Strings can be made immutable (“frozen”) via the freeze method. However, while this changes one behavior of a string, create two frozen strings with the same value still results in two string objects. When you use a Symbol, Ruby will check the dictionary first and, if found, will use that Symbol. If the Symbol is not found in the dictionary, only then will the interpreter instantiate a new Symbol and put it in the heap.

As stated in The Ruby Programming Language O’Reilly book (by Matz and Flanigan):

A typical implementation of a Ruby interpreter maintains a symbol table in which it stores the names of all the classes, methods, and variables it knows about. This allows such an interpreter to avoid most string comparisons: it refers to method names (for example) by their position in this symbol table. This turns a relatively expensive string operation into a relatively cheap integer operation.

Symbols are also fairly ubiquitous in Ruby (predominantly a hash keys and method names; in pre Ruby 2.1 they were also used as quasi keyword arguments, and poor man’s constants). Because of their performance, memory and usage considerations, Symbols are most often used as Hash keys, with many libraries expecting option hashes with specific symbols for keys.

Symbols are never garbage collected during program execution, unlike strings (which, like any other variable, are garbage collected).

Because strings and symbols are different objects, here’s an example of something that often catches less experienced Ruby programmers unaware.

Consider the following hash, for example:

irb(main):001:0> a = {:key => 1}
irb(main):002:0> puts a['key']
=> nil.

You may be expecting to see 1 printed here, especially if a was defined elsewhere in your program. But, as strings and symbols are different; i.e., key (the symbol) and 'key' (the string) are not equivalent. Accordingly, Ruby correctly returns nil for a['key'] (even though this is annoying for the unsuspecting programmer wondering where her value is!)

Rails has a class, HashWithIndifferentAccess, which acts like a Hash object, except it treats strings and symbols with the same values as equivalent when used as key names, thereby avoiding the above issue:

irb(main):001:0> a = HashWithIndifferentAccess.new({:key => 1})
irb(main):002:0> puts a['key']
=> 1

There is one important caveat. Consider this controller action:

def check_value
  valid_values = [:bad, :ok, :excellent]
  render json: valid_values.include?(params[:value].to_sym)
end

This innocent looking code is actually a denial-of-service (DOS) attack vulnerability. Since symbols can never be garbage collected (and since here we cast user input into a symbol), a user can keep feeding this endpoint with unique values and it will eventually eat up enough memory to crash the server, or at least bring it to a grinding halt.

Q: Describe multiple ways to define an instance method in Ruby.

Instance methods can of course be defined as part of a class definition. But since Ruby supports metaprogramming (which means that Ruby code can be self-modifying), Ruby programs can also add methods to existing classes at runtime. Accordingly, there are multiple techniques for defining methods in Ruby, as follows:

(1) Within a class definition, using def (The simplest answer)

class MyObject

  def my_method
    puts "hi"
  end
end

This is the standard way to define instance methods of a class.

(2) Within a class definition, without using def

class MyObject
  define_method :my_method do
    puts "hi"
  end
end

Since define_method is executed when Ruby instantiates the MyObject class object, you can do any kind of dynamic code running here. For example, here’s some code that only creates our method if it’s being run on a Monday:

require 'date'

class MyObject
  if Date.today.monday?
    define_method :my_method do
      puts "Someone has a case of the Mondays"
    end
  end
end

Executing MyObject.new.my_method on any other day of the week will give us an exception about no such method existing. Which is true: it’ll only exist on Mondays!

(It’s important to note that classes are objects too in Ruby, so our MyObject class is an instantiation of a Class object, just like in a = MyObject.new, a is an instance of MyObject.)

(3) Extending an existing class definition

Ruby also allows class definitions to be extended. For example:

class MyObject
  def say_hello
    puts "hey there!"
  end
end

class MyObject
  def say_goodbye
    puts "buh-bye"
  end
end

The above code will result in the MyObject class having both the say_hello and the say_goodbye methods defined.

Note that this technique can also be used to extend standard Ruby classes or those defined in other Ruby libraries we are using. For example, here we add a squawk method to the standard Ruby string class:

class String

  def squawk
    puts "SQUAWK!!!"
  end
end

"hello".squawk

(4) Using class_eval

class_eval dynamically evaluates the specified string or block of code and can therefore be used to add methods to a class.

For example, we can define the class MyObject:

class MyObject
  ...
end

… and then come back at a later time and run some code to dynamically add my_method to the MyObject class:

MyObject.class_eval do
  def my_method
    puts "hi"
  end
end

(5) Using method missing

Ruby also provides a hook to check for undefined methods. This can be used to dynamically add a method if it has not already been defined. For example:

class MyObect
  def method_missing(method_name_as_symbol, *params)
    if method_name_as_symbol == :my_method
      puts "hi"
    end
  end
end

Wrap Up

Ruby on Rails is a powerful framework for rapid development of web applications. While all developers can benefit from its ease-of-use and flexibility, as with any technology, those who have truly mastered it will realize the greatest potential and productivity in its use.

While no brief guide such as this can entirely cover the breadth and depth of technical topics to cover in a Rails interview, the questions provided herein offer an effective basis for identifying those who possess a sound and principled foundation in the Rails framework and its paradigms.