5 Ruby on Rails Interview Questions and Answers

Have an upcoming Ruby on Rails interview for a junior web developer position?

Ruby on Rails Interview Question #1

The product team has a great new feature they want to add to your Ruby on Rails application: they want every model in the system to be able to retain special user notes. You realize that there will be a collection of forms and model code that will be duplicated in the dozen ActiveRecord models already in your application.

What are some strategies you can employ for reducing duplication and bloated Active Record models? What are the pros/cons of each strategy?

Because Ruby on Rails is an MVC framework, it can become tempting to try and fit everything into the Model or the Controller. Ruby on Rails is a powerful framework that provides many different mechanisms for describing our application and keeping our models and controllers nice and tidy.

Below are two ways of reducing fat models. They illustrate different levels of shared understanding between the extracted functionality and the model in question.

1. Use ActiveSupport::Concern

If the code really belongs in the model (because it relies on ActiveRecord helpers), but there is a coherent grouping of methods, a concern might be worth implementing. For example, many models in a system could enable a user to create a note on a number of models:

    require 'active_support/concern'
    
    module Concerns::Noteable
      extend ActiveSupport::Concern
    
      included do
        has_many :notes, as: :noteable, dependent: :destroy
      end
    
      def has_simple_notes?
        notes.not_reminders_or_todos.any?
      end
    
      def has_to_do_notes?
        notes.to_dos.any?
      end
    
      def has_reminder_notes?
        notes.reminders.any?
      end
      ...
    end

The Concern can then be applied like so:

    class Language < ActiveRecord::Base
      include TryFind
      include Concerns::Noteable
    end

Pros:
This is a great way of testing a cohesive piece of functionality and making it clear to other developers that these methods belong together. Unit tests can also operate on a test double or a stub, which will keep functionality as decoupled from the remaining model implementation as possible.

Cons:
ActiveSupport::Concerns can be a bit controversial. When they are over-used, the model becomes peppered in multiple files and it’s possible for multiple concerns to have clashing implementations. A concern is still fundamentally coupled to Rails.

See also:
https://signalvnoise.com/posts/3372-put-chubby-models-on-a-diet-with-concerns
http://api.rubyonrails.org/classes/ActiveSupport/Concern.html
http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/

Delegate

Depending on the source of the bloat, sometimes it makes better sense to delegate to a service class. 10 lines of validation code can be wrapped up in a custom validator and tucked away in app/validators. Transformation of form parameters can be placed in a custom form under app/forms. If you have custom business logic, it may be prudent to keep it in a lib/ folder until it’s well defined.

The beauty of delegation is that the service classes will have no knowledge of the business domain and can be safely refactored and tested without any knowledge of the models.

Pros:
This approach is elegant and builds a custom library on top of what Ruby on Rails provides out of the box.

Cons:
If the underlying APIs change, your code will likely need to be updated to match. Instead of coupling to your model layer, you’ve now coupled yourself to either Ruby on Rails or a third-party library.

See also:
http://guides.rubyonrails.org/active_record_validations.html#custom-validators
https://github.com/apotonick/reform
https://robots.thoughtbot.com/activemodel-form-objects
https://github.com/timcraft/formeze

Conclusion :
This question helps demonstrate two critical skills every Ruby developer needs to develop: how handle complexity from emerging requirements and how to decide the most appropriate refactoring.

By working through different refactoring strategies, I can explore a candidate’s problem solving skills and their overall familiarity with Ruby on Rails and their knowledge of MVC. It’s important to know what is code that is specific to the application and what can be generalized into a completely decoupled piece of functionality.

Ruby on Rails Interview Question #2

Given an array [1,2,34,5,6,7,8,9], sum it up using a method:

    def sum(array)
      return array.inject(:+)
    end    

Summation of an array is one of the most fundamental concepts in programming, and there are a lot of methods to achieve it, such as iterating the array and summing the numbers. In Ruby, it’s neat to know there is method that called inject, because it’s so powerful yet simple.

Ruby on Rails Interview Question #3

What is metaprogramming?

Ruby developers should know what’s metaprogramming, because it is widely used, especially in popular frameworks such as Rails, Sinatra, and Padrino. By using metaprogramming, we can reduce duplicate code, but there is a downside where it will increase the complexity of the code in the long run.

Here’s an example of metaprogramming in Ruby:

A user can have a lot of roles, and you want to check the authorization.

Normal scenario:

    def admin?
         role ==  'admin'
    end
    
    def marketer?
        role == 'marketer'
    end
    
    def sales?
       role == 'sales'
    end

Metaprogramming:

    ['admin', 'marketer', 'sales'].each do |user_role|
        define_method "#{user_role}?" do
            role == user_role
        end
    end

Ruby on Rails Interview Question #4

Given this Human class implementation

    class Human
    
        def talk
            puts "I’m talking"
        end
    
         private
    
         def whisper
              puts "I’m whispering"
         end
    end

What’s the output of :

  1. Human.new.talk

  2. Human.new.whisper

  3. Human.new.send(:talk)

  4. Human.new.send(:whisper)

  5. I’m talking

  6. NoMethodError: private method ‘whisper’ called for #<Human:0x007fd97b292d48>

  7. I’m talking

  8. I’m whispering

To explain, the class object Human.new.talk is calling an instance method, so it works perfectly. The talk method is a public method and can be called by everyone.

The class object Human.new.whisper is trying to access a private method, which it is not allowed to. Private and Protected methods are not accessible from outside. They are only used internally. This is an object-oriented design and can be used to structure the code, which the implementation is not supposed to expose to consumer object.

Finally, Human.new.send(:talk) sends a bypass control check to the method so it can be called without raising an error. Same goes to Human.new.send(:whisper).

Ruby on Rails Interview Question #5

Write code that splits a given array of integers into two arrays; the first containing odd numbers and second containing even numbers

    %i|select reject|.map { |m| array.partition(&odd?)}

or

    array.each_with_object({odd:[], even:[]}) do |elem, memo|
      memo[elem.odd? ? :odd : :even] << elem
    end # inject for ruby < 2.0 is fine as well

The straightforward approach would be to call array.select to store odds and then array.reject to store evens. There is nothing wrong with this, except it violates DRY principle:

    odds = array.select &:odd?
    evens = array.reject &:odd?

Future modification of this code might accidentally change the only one line from the above pair, breaking consistency. It is not likely the case for this particular example, but DRY usually works for future use.

One might notice that the latter example does one iteration through an array, while the former is still iterating the array twice, once for each method. In most cases, the performance penalty is not significant, but it should be taken into consideration when dealing with huge arrays.


Hope these 5 Ruby on Rails interview questions help you find and vet a Ruby developer's technical skill. What's more important is to also review a candidate's past projects, how the candidate goes about solving issues previously faced, as well as other soft skills. By no means is this an exhaustive list of interview questions, but these are some ones to help you get started.

5 Ruby on Rails Interview Questions and Answers

Share this on 👉

Join the newsletter 💌