Skip to content

Ruby Developer interview questions

100 real questions with model answers and explanations for Junior Ruby Developer candidates.

See a Ruby Developer resume example

Practice with flashcards

Spaced repetition · Hunter Pass

Questions

ruby

In Ruby, every value is an object and behavior is invoked through methods.

  • 7.class returns Integer, and "ruby".class returns String.
  • Even operators are methods, so 2 + 3 is equivalent to 2.+(3).
  • Classes are objects too, which is why User.new sends new to User.

Why interviewers ask this: The interviewer checks whether you understand Ruby's uniform object model rather than treating numbers or classes as special cases.

ruby

Ruby determines an object's type at runtime, and variables have no fixed declared type.

  • value can refer to 10 and later to "ten" without a declaration.
  • Code can accept any object supporting each instead of checking its exact class.
  • Calling 10.upcase raises NoMethodError at runtime, so tests and clear interfaces matter.

Why interviewers ask this: The interviewer checks whether you can explain both the flexibility and runtime risk of Ruby's type system.

ruby

Only false and nil are falsy in Ruby; every other object is truthy.

  • 0, an empty String, and an empty Array all enter the true branch of an if.
  • if users.any? checks for elements, while if users only checks for nil or false.
  • value || "default" replaces both nil and false, so use value.nil? when false is meaningful.

Why interviewers ask this: This reveals whether the candidate brings incorrect truthiness assumptions from other languages into Ruby.

ruby

Ruby uses naming prefixes to distinguish scope and ownership.

  • name is local, @name belongs to one object, and @@count is shared through a class hierarchy.
  • $stdout is global, while Billing::MAX_RETRIES is a namespaced constant.
  • Reassigning a constant warns but succeeds, and a constant's referenced object remains mutable unless frozen.

Why interviewers ask this: A strong answer distinguishes variable ownership and knows that constants are not automatically immutable.

ruby

A Ruby method returns its last evaluated expression unless return is used explicitly.

  • def double(n); n * 2; end returns 8 for double(4).
  • An explicit return suits an early exit such as return nil if user.nil?.
  • The question-mark suffix in active? is a predicate convention, not special return syntax.

Why interviewers ask this: The interviewer checks basic method semantics and sensible use of explicit return.

ruby

Ruby methods can combine positional arguments, defaults, and explicit keywords.

  • def greet(name, loud = false) has one required and one optional positional argument.
  • def create(name:, role: "member") requires name: and defaults role:.
  • create(name: "Ira") is clear at the call site, while a missing required keyword raises ArgumentError.

Why interviewers ask this: A strong answer shows current Ruby keyword syntax and the error raised by an invalid call.

args-kwargs

*args collects extra positional arguments into an Array, while **kwargs collects keywords into a Hash.

  • def sum(*numbers) receives sum(1, 2) as [1, 2].
  • def build(**options) receives build(color: "red") as { color: "red" }.
  • A splat also expands values, so sum(*[1, 2]) passes two positional arguments.

Why interviewers ask this: The interviewer verifies that you can collect and expand arguments without mixing positional and keyword data.

blocks

A block is behavior passed to a method, and yield executes that behavior.

  • [1, 2].each { |n| puts n } passes a block with n as its parameter.
  • A method can call yield(value) to send a value into the supplied block.
  • block_given? checks for a block before yielding and avoids LocalJumpError.

Why interviewers ask this: The interviewer checks whether you understand blocks as passed behavior rather than merely iterator syntax.

lambdablocks

Both turn a block into an object, but a lambda behaves more like a method.

  • square = proc { |n| n * n }; square.call(4) returns 16.
  • A lambda checks argument count strictly, while a regular Proc is lenient.
  • return exits only the lambda, but in a regular Proc it tries to exit the enclosing method.

Why interviewers ask this: For a junior, the key signal is knowing strict arguments and return behavior without discussing internals.

enumerable

Enumerable provides reusable traversal methods to a class that follows its iteration contract.

  • The class must include Enumerable and define each to yield its elements.
  • Once that contract exists, select and map can filter and transform the yielded values.
  • reduce can combine those values, such as [1, 2, 3].reduce(0, :+) returning 6.

Why interviewers ask this: The interviewer wants both parts of the Enumerable contract and concrete methods gained from it.

each visits elements, while map builds a new Array from each block result.

  • [1, 2].each { |n| puts n } performs output and returns the original Array.
  • [1, 2].map { |n| n * 2 } returns [2, 4].
  • Use map for transformation instead of manually appending results inside each.

Why interviewers ask this: This tests whether you choose a collection method by its return value and intent.

ruby

Array is an ordered, zero-indexed collection that can hold mixed object types.

  • items[0] reads the first element, while items[-1] reads the last.
  • items << "book" appends in place, and items.pop removes and returns the last element.
  • items[1, 2] returns a two-element slice starting at index 1.

Why interviewers ask this: The interviewer verifies practical use of Ruby's most common ordered collection.

ruby

Hash stores key-value pairs and retrieves a value by its key.

  • user = { name: "Mina" }; user[:name] returns "Mina".
  • user[:role] returns nil when absent, while user.fetch(:role) raises KeyError without a default.
  • user.each do |key, value| yields both parts of every pair.

Why interviewers ask this: A strong junior answer covers normal lookup plus safer fetch behavior for required keys.

Interpolation embeds an expression in a double-quoted String, while concatenation joins strings.

  • "Hello, #{name}" evaluates name, but single quotes keep #{name} literal.
  • "Hello, " + name creates a new String, while text << name mutates text.
  • With +, a number needs conversion, as in "Age: " + age.to_s.

Why interviewers ask this: The interviewer checks string syntax and whether you recognize mutating operations.

symbols

A Symbol is an immutable identifier, while a String represents mutable text.

  • Hash keys commonly use symbols, as in { name: "Ana" }[:name].
  • Symbols fit states and option keys such as :pending or :json.
  • User-entered text should remain a String rather than being converted into arbitrary symbols.

Why interviewers ask this: A good answer chooses symbols by meaning and immutability rather than calling them faster strings.

Range represents an interval that can be iterated or tested for membership.

  • 1..5 includes 5, while 1...5 excludes 5.
  • (18..65).cover?(age) is a readable boundary check.
  • array[1..3] uses a Range to select consecutive elements.

Why interviewers ask this: The evaluator expects the inclusive and exclusive forms plus one practical use.

A mutating method changes its receiver, while a non-mutating method returns another value.

  • name.upcase returns a new String, while name.upcase! changes name in place.
  • array.sort returns a sorted copy, while array.sort! reorders the same Array.
  • A bang often signals danger, but Ruby does not enforce that naming convention.

Why interviewers ask this: The interviewer checks whether you can predict object changes and avoid accidental shared-state bugs.

ruby

freeze prevents further mutation of that object, but the protection is shallow.

  • name = "Ruby".freeze makes name << "!" raise FrozenError.
  • Freezing an Array does not freeze mutable objects stored inside it.
  • frozen? reports the state, and dup normally creates an unfrozen shallow copy.

Why interviewers ask this: The evaluator wants the practical protection and the limitation that freeze is not deep immutability.

A Ruby class groups behavior, and initialize sets up each new instance.

  • class User; def initialize(name); @name = name; end; end stores an instance variable.
  • User.new("Ada") allocates an object and invokes initialize.
  • attr_reader :name creates a getter without exposing unrestricted writes.

Why interviewers ask this: The interviewer checks whether you can create an encapsulated object instead of exposing all state.

ownershipoop

A Ruby class inherits from one superclass and can reuse or override its methods.

  • class Admin < User declares Admin as a subclass of User.
  • If Admin defines greet, that implementation is chosen before User#greet.
  • super forwards to the next implementation; super passes current arguments, while super() passes none.

Why interviewers ask this: A strong junior answer explains single inheritance and the argument behavior of super.

Locked questions

  • 21

    What are modules and mixins used for?

    modules
  • 22

    What do public, protected, and private mean in Ruby?

    ruby
  • 23

    What is the difference between instance and class methods?

  • 24

    How do you handle exceptions in Ruby?

    error-handlingrubysoft-skills
  • 25

    How do you safely read and write files in Ruby?

    ruby
  • 26

    How do require, RubyGems, and Bundler work together?

    bundlinggems
  • 27

    What is the difference between ==, eql?, and equal? in Ruby?

    ruby
  • 28

    How do if, unless, and case express conditions?

  • 29

    What does the safe navigation operator do?

  • 30

    How does Ruby find a method to call?

    ruby
  • 31

    What belongs to Model, View, and Controller in Rails MVC?

    rails
  • 32

    How does Rails routing connect a URL to an action?

    rails
  • 33

    What should a basic Rails controller action do?

    rails
  • 34

    What are strong parameters?

  • 35

    What is an ActiveRecord model?

    orm
  • 36

    How do Rails model validations work?

    validationrails
  • 37

    What is a Rails database migration?

    databasemigrationsrails
  • 38

    How do belongs_to and has_many work?

  • 39

    How do you perform basic CRUD with ActiveRecord?

    orm
  • 40

    How do where, find_by, and find differ?

  • 41

    What is an ActiveRecord scope?

    orm
  • 42

    What is the N+1 query problem in Rails?

    queriesn+1rails
  • 43

    How do resource routes map to REST actions?

    rest
  • 44

    Which HTTP status codes should a basic Rails API return?

    httpstatus-codesrails
  • 45

    How does an ERB view render controller data?

  • 46

    What is a Rails partial, and how do locals work?

    rails
  • 47

    What is the Rails console useful for?

    rails
  • 48

    How do Rails environments differ?

    rails
  • 49

    How would you write a basic RSpec model example?

    testing
  • 50

    What should an RSpec request spec verify?

    testing
  • 51

    user.name raises NoMethodError because user is nil. How do you debug it?

  • 52

    An optional profile makes user.profile.city crash for some users. What small fix would you make?

  • 53

    Why does {"name" => "Ana"}[:name] return nil, and how do you fix it?

  • 54

    After copy = original.dup, changing copy[:settings][:theme] also changes original. Why?

  • 55

    A method must double an array without changing its input, but it uses map!. How do you fix it?

  • 56

    How should a custom EventLog#each behave when the caller provides no block?

    blocks
  • 57

    Why does def calculate; yield(4); 10; end return 10 when the block returns 8?

    blocks
  • 58

    What does formatter = proc { |name| name.strip.upcase } return for formatter.call(" Ada ")?

    blocks
  • 59

    Why does a Proc created inside build_formatter still know the local prefix after build_formatter returns?

    blocks
  • 60

    What does [1, 2, 3, 4].select(&:even?).map { |n| n * 10 } return?

  • 61

    You need the first active admin in an array. Why use find or detect instead of select.first?

  • 62

    A CSV import is missing required headers. How would you report that expected failure with a custom exception?

    error-handling
  • 63

    CSV.parse(File.read(path)) raises invalid byte sequence in UTF-8 for a customer file, although File.read succeeded. How do you handle it?

    soft-skills
  • 64

    An API wrapper logs a timeout, then its caller behaves as if the request succeeded. What is missing?

    resilienceapi
  • 65

    File.read("config/settings.json") works locally but raises Errno::ENOENT in tests. What do you inspect?

    config
  • 66

    require "csv_importer" raises LoadError although the file exists under lib/. What do you check?

  • 67

    The app boots with Bundler::GemNotFound. What are your first checks?

    bundlinggems
  • 68

    Bundler says gem A needs Rack below 3 while gem B needs Rack 3 or newer. What do you do?

    bundlinggemsrack
  • 69

    RSpec reports expected: 201, got: 422. How do you use that output?

    testing
  • 70

    A spec passes alone but finds two users in the full suite. What do you check?

  • 71

    Git shows conflict markers in orders_controller.rb after a merge. What steps do you take?

    git
  • 72

    You merged the wrong branch and have not committed the conflicted merge. What is the safe action?

  • 73

    Rails returns 404 for /orders/42, but OrdersController#show exists. What do you check first?

    rails
  • 74

    GET /orders works, but the form gets a routing error for POST /orders. Why?

    forms
  • 75

    Rails logs Unpermitted parameter: :role, and role never changes. How do you respond?

    rails
  • 76

    User.create(email: "bad") returns an unsaved object. How do you find the validation failure?

    validation
  • 77

    When would you use save! instead of save while debugging a Rails write?

    rails
  • 78

    post.author.name fails for one record despite belongs_to :author. What do you investigate?

  • 79

    How would you model users joining many projects when each connection also stores a membership role?

  • 80

    After pulling code, Rails raises PG::UndefinedColumn for orders.status. What do you check?

    railsfundamentals
  • 81

    A specific local migration added the wrong column, but newer migrations have also run. How do you reverse only that migration?

    migrationsschema
  • 82

    Why does Order.where(status: "paid") show no SQL until to_a is called?

    sql
  • 83

    A maintenance task must process 200,000 active users. How do you avoid loading them all at once?

    concurrency
  • 84

    A dashboard only needs the number of active users. Why should it use User.active.count instead of User.active.to_a.length?

  • 85

    You added includes(:author), but the page remains slow. What evidence do you gather?

  • 86

    Several Rails views repeat order.created_at.strftime("%d %b %Y"). Where would you put that formatting?

    rails
  • 87

    Why does form_with model: @article on the edit page submit PATCH /articles/7 instead of POST /articles?

  • 88

    A Rails request returns 500 only for one payload. How do logs narrow the bug?

    rails
  • 89

    How can you experiment with model updates in Rails console without keeping database changes?

    experimentsdatabaserails
  • 90

    GET /articles returns all 10,000 rows and uses too much memory. What basic pagination would you add?

    memorypagination
  • 91

    A missing API resource becomes a 500. How do you make the response correct?

    api
  • 92

    Order#subtotal sums each line item's quantity times unit price. How would you test this plain model method?

  • 93

    A request spec expects JSON from POST /orders, but response.parsed_body fails because the controller returned an HTML redirect. What do you inspect?

    html
  • 94

    A Sidekiq job stays queued while the worker logs Redis::CannotConnectError. What do you check?

    redisdata-structuresbackground-jobs
  • 95

    What happens when native Sidekiq code calls ReportJob.perform_async(user) with a User object, and what should it pass?

    background-jobs
  • 96

    A retried Sidekiq job adds 10 credits twice. How do you make it idempotent?

    background-jobsidempotency
  • 97

    A Turbo link replaces the whole page instead of frame comments. What do you inspect?

  • 98

    Walk through a successful Rails HTML request for GET /products/7.

    htmlrails
  • 99

    PostgreSQL raises PG::NotNullViolation when an order lacks currency. How do you fix it?

    postgres
  • 100

    Deleting a user raises PG::ForeignKeyViolation because orders still reference that user. What should you check before changing the constraint?