Ruby is a dynamic, open-source programming language that focuses on simplicity and productivity. Exceptionally user-friendly, it is widely used to develop web applications and systems scripting. This blog post comprises various Ruby interview questions and answers, focusing on the language’s concepts, capabilities, and data structures. Practical for potential job applicants, it provides useful insight into how well a candidate understands Ruby and its applications, including object-oriented programming, error handling, and testing techniques. In technical interviews, proficiency in Ruby allows for a broad examination of an applicant’s programming acumen.
Ruby Fundamentals
- 1.
What is Ruby, and why is it popular for web development?
Answer:Ruby is a dynamic, object-oriented programming language known for its simplicity and focus on developer productivity. Its main claim to fame in web development is the web application framework, Ruby on Rails (RoR), which transformed the way web applications are built by promoting convention over configuration.
Key Features & Contributions to Web Development
-
Language Syntax: Ruby’s syntax has an appeasing natural language style. This, paired with its dynamic typing, powerful metaprogramming features, and absence of semicolons, results in clean and expressive code.
-
Gems: Ruby’s package manager, RubyGems, simplifies library management, making it easy to integrate numerous third-party extensions.
-
Database Integration: ActiveRecord, a popular object-relational mapping system, aids in managing database records via a natural, object-oriented interface.
-
MVC Pattern: Rails, in particular, is famed for its adherence to the Model-View-Controller pattern, offering a clear separation of concerns.
-
Code Rearrangement: The auto-loading mechanism allows for seamless navigation between related files and classes while coding.
-
Ecosystem Consistency: RoR brought about a
many-to-manyrelationship with databases, streamlining and simplifying existing development patterns. -
Strong Community: The language’s supportive community and its commitment to clean, readable code are evident in guiding principles like “Mediterranean” quality and “Matz’s kindness.”
-
Test-Driven Development: RoR promotes best-testing practices from the project’s inception, ensuring reliability.
-
Giant Corporations’ Indulgence: Prominent organizations such as GitHub, Shopify, and Airbnb have successfully tapped into the potential of Ruby on Rails.
Code Example: Ruby on Rails (RoR) Routing
Here is the Ruby code:
# config/routes.rb Rails.application.routes.draw do root 'welcome#index' get 'products/:id', to: 'products#show' resources :articles endThis file configures routes for different URLs, specifying which controllers and actions to invoke. For instance, upon receiving a
GETrequest forproducts/5, RoR would route it to theshowaction in theProductsControllerwith the ID parameter set to5. Such straightforward setups contribute to RoR’s appeal. -
- 2.
How do you create a Ruby script file and execute it on a command line?
Answer:First, you create a
Rubyscript file with a.rbextension that contains your Ruby code. You can then execute this script using therubycommand in your command line.Basic Steps for Creating and Running a Ruby Script in a File
-
Create a File: Use any text editor to write your Ruby code, and save the file with a
.rbextension, e.g.,my_ruby_script.rb. -
Write Ruby Code: Here is a simple example.
# Filename: my_ruby_script.rb puts "Hello, Ruby Script!" -
Run the Ruby Script: Go to your command line and navigate to the folder where the Ruby file is saved. Then, type the following command:
ruby my_ruby_script.rbAfter pressing enter, you will see the output:
Hello, Ruby Script!
Getting More Advanced
Command-Line Arguments
You can access command-line arguments using special variables called
ARGV.Here is the code:
# Filename: script_with_args.rb puts "Arguments: #{ARGV.join(', ')}"In the command line, you would run this script as:
ruby script_with_args.rb arg1 arg2 arg3The output would be:
Arguments: arg1, arg2, arg3Interactive Scripts
Ruby scripts can engage with users using the
getsmethod.Here is an example:
# Filename: interactive_script.rb puts "What is your name?" name = gets.chomp puts "Hello, #{name}!"When you run this script using
ruby interactive_script.rb, it will prompt you for your name, and after you provide it, it will greet you.Background Processing
If you want a script to run in the background without blocking your command line, you can use the
&character.For instance, to run a script called
background_script.rbin the background, you can use:ruby background_script.rb &Ruby Shell
For more complex shell operations,
Rubyoffers theshelllibrary.Here is the sample code:
require 'shell' # Use 'open' to open a URL in your default browser. sh = Shell.new sh.open "https://example.com" -
- 3.
What are the basic data types in Ruby?
Answer:Ruby is claimed to treat “everything as an object”. But like many languages, Ruby has both primitive and abstract data types.
Primitive Types
- Numbers:
- Integers can be of any size (limited by system memory).
- Floating-Point numbers follow the IEEE 754 standard.
- Booleans: Represented by
trueandfalse. - Symbols: Unique, immutable identifiers represented with a
:followed by a name.
Abstract Types
- Strings: Unicode with multiple encodings.
- Arrays: Ordered, indexed collections.
- Hashes: Key-value pairs, also known as dictionaries or maps in other languages.
Others assimilated Primitive Types
Ruby, despite its philosophy of being completely object-oriented, has some underlying primitive paradigms due to its performance concerns and efficiency considerations.
-
nil: Represents ‘nothing’ or ‘empty’. It’s the only instance of
NilClass. -
Booleans: While
trueandfalseare themselves keywords, any other value in Ruby is considered truthy in a conditional context.
Advanced Types
- Rational Numbers: Represented as a fraction (e.g.,
1/3r). - Complex Numbers: Have real and imaginary parts (e.g.,
2 + 3i). - Dates and Times: Provide various built-in classes like
Timefor dealing with date and time values.
Ruby Uniqueness
Ruby shuns a “strictly-typed” system. Variables need not be declared upfront and can be reassigned to different types during execution. This freedom, although liberating, can lead to unexpected behavior, especially in larger codebases.
- Numbers:
- 4.
Explain the difference between symbols and strings in Ruby.
Answer:Ruby features both strings and symbols, each with distinct use cases.
Key Distinctions
- Type: Strings are of class
String, while symbols are instances ofSymbol. - Mutability: Strings are mutable, symbols are not.
- Memory: Symbols are stored as a single, unique object in memory, while each string is unique.
- Performance: As symbols are immutable, lookups are faster than for equivalent strings.
Primary Usages
- Strings: For text and dynamic data that may change or be unique across different objects or occurrences.
- Symbols: Typically used as keys for hashes or unique identifiers in the program. They’re advantageous for lookup efficiency and when the actual content of the identifier is less relevant than its unique identity.
Memory Considerations
- As symbols are stored only once in memory, they are memory-efficient in certain scenarios, like using the same symbol across different objects or operations. Be cautious, though, as unnecessarily creating a large number of symbols can lead to memory bloat.
- Strings may be more memory-intensive, especially when there are numerous unique strings. However, they are the right choice when dealing with data that genuinely varies or where mutability is required.
Code Example: String vs Symbol
Here is the Ruby code:
# Strings str_1 = "Hello" str_2 = "Hello" puts str_1.object_id == str_2.object_id # Output: false # Symbols sym_1 = :hello sym_2 = :hello puts sym_1.object_id == sym_2.object_id # Output: true - Type: Strings are of class
- 5.
How are constants declared and what is their scope in Ruby?
Answer:In Ruby, you declare a constant by using all uppercase letters. Constants are subject to lexical scoping. While reassignment is technically possible (spawning a warning), it should be avoided as a practice.
Constant Declaration
You can declare a Ruby constant using
Object::CONSTANTnotation or by assigning a value directly to an identifier.Code Example: Constant Declaration
# Using Object::CONSTANT notation Math::PI # Direct assignment RADIUS = 5.0Constant Scope
Constants have a global scope, but their visibility can be restricted within classes and modules.
Global VS. Local Scope
-
Global Scope: Constants are accessible throughout the entire application.
A = 1 # Top level module M puts A # Outputs: 1 end -
Local Scope: Constants are defined within a module or a class.
module M A = 2 A = 3 puts A # Outputs: 3 end
Best Practices
- Avoid re-assigning constants. Although this generates a warning, the reassignment can still take place, which can lead to unintended behavior.
- For areas where you want to have a constant’s value remain unchanged, use
.freezeon the constant or variable storing the constant’s value.
Code Example: Avoiding Reassignment
require "warning" # Generates a warning: already initialized constant A = 1 A = 2 warning 'constant reassignment' puts A # Outputs: 2Object#freezeCIRCLE_AREA = Math::PI * (RADIUS ** 2) CIRCLE_AREA.freeze # Any reassignment will generate an error # CIRCLE_AREA = 100 puts CIRCLE_AREA -
- 6.
Explain the use of ‘require’ and ‘include’ in Ruby.
Answer:Ruby uses both Require and Include to manage dependencies and to mix modules into classes.
Require
-
Purpose: Loads external libraries, enabling access to their defined classes and modules.
-
Execution: Done at the top of the file or script.
-
Trigger: A
LoadErroris raised if the required file is not found. -
State Management: Tracks loaded libraries, subsequently ignoring further
requirecalls for the same library.
Example: Using Require
Here is the Ruby code:
# In file application.rb require 'my_library' # In file my_library.rb class MyLibrary # ... endInclude
-
Purpose: Integrates a module’s methods within a class, giving the class access to those methods.
-
Execution: On the specific class that necessitates the module’s functionality.
-
State: Not applicable for classes, as they can include multiple modules.
Why is it Used?
- Require: Ensures the presence of the external library before continuing, a basic necessity for external code.
- Include: Mixes in module functionality only when needed, aligning with Rails’ convention of using it in the classes contextually.
-
- 7.
What are Ruby iterators and how do they work?
Answer:When it comes to Ruby, iterators allow for easy, streamlined data manipulation. Whether you’re working with arrays, ranges, or other data structures, iterators help you efficiently apply operations to each element without needing to manage loop counters.
Most Common Ruby Iterators
- Each: The most basic iterator, it goes through each element.
- Each with index: Similar to each, but it also gives the index of the current element.
Code Example: Each & Each with Index
Here is the Ruby code:
arr = [5, 4, 3, 2, 1] # Iterating with Each arr.each { |num| puts num } # Output: # 5 # 4 # 3 # 2 # 1 # Iterating with Each with Index arr.each_with_index { |num, index| puts "#{index}: #{num}" } # Output: # 0: 5 # 1: 4 # 2: 3 # 3: 2 # 4: 1Common Usage
- Each Char: Often used with strings, this iterator loops through each character.
- Each Line: Handy for reading files, it processes lines one at a time.
Code Example: Each Char & Each Line
Here is the Ruby code:
str = "Hello, World!" # Iterating Each Character str.each_char { |char| puts char } # Output: # H # e # l # l # o # , # ...File.open('example.txt').each_line do |line| puts line endPredicative Iterators
These iterators select elements from a collection that match specific conditions. They are typically used in combination with blocks.
Examples include
select,reject, andgrep. Each is designed to achieve specific selection goals:selectreturns elements that yield true in the block.rejectreturns elements that yield false in the block.grepreturns elements that match a specified pattern.
Code Example:
select,reject, andgrepHere is the Ruby code:
# Select even numbers numbers.select { |num| num.even? } # Reject short names names.reject { |name| name.length < 5 } # Grep to find email addresses text = "Email me at user@example.com" text.grep(/\b\w+@\w+\.\w+\b/)Chase & Transform
These iterators process the elements and return a result. They include
map,collect, andpartition.map: Transforms each input and returns a new array.collect: Identical to map, but ops include the return value.partition: Separates elements into two groups based on whether the block returns true or false.
Code Example:
map,collect, andpartitionHere is the Ruby code:
# Double each number numbers.map { |num| num * 2 } # Names all uppercase names.collect { |name| name.upcase } # Split numbers based on even or odd numbers.partition { |num| num.even? }Execute Operations
These iterators modify their elements or perform side effects. Examples include
eachandeach_with_index.Often used for their simplicity, do exercise caution as these functions can have unexpected results, especially when combined with unintended side effects.
each: Processes each element but does not return anything.each_with_index: Similar to each, but also gives the index of the current element.
Sort-Related Operations
When working with ordered collections like arrays or ranges, Ruby provides various sorting options. Common sorting iterators include
sort,sort_by, andreverse_each. They all work with blocks to customize the sorting or iteration behavior.Repetition-Based Iterators
These Ruby constructs are particularly useful in the context of text manipulation, allowing you to repeat characters (such as hyphens for formatting headers) for a specified number of times.
each_line: Useful when processing multi-line strings or files.each_char: Ideal for character-level processing in strings or enumerations.downto: Iterates downwards to a specified value.upto: Iterates upwards to a specified value.times: Repeats the associated block a predetermined number of times.step: Indents a set number of times, confined by a range.cycle: Used primarily with blocks, it repeatedly moves through the specified range.
Code Example: Repetition-Based Iterators
Here is the Ruby code:
# Print a line of stars '*'.upto('*****') { |s| puts s } # Output: # * # ** # *** # **** # ***** # Print numbers from 5 to 10, then their squares 5.upto(10) { |num| puts num } 5.upto(10).each { |num| puts num**2 } - 8.
How are errors handled in Ruby?
Answer:Ruby’s exception hierarchy enables developers to manage different kinds of errors. The two main exception types cater to a multitude of issues:
- StandardError: For generic problems that occur during code execution.
- SystemCallError: Specifically deals with errors originating from system calls.
Ways to Handle Exceptions in Ruby
Top-Level Exception Handling
Ruby leverages the
at_exitmethod for centralized error handling. This approach is mainly useful for logging errors before program exit or for cleaning up resources.at_exit do puts $!.message if $! endSingle Statement Unwind
Utilize inline rescue, marked by the
beginandendblock. If an exception arises during the evaluation of the enclosed expression, it’s caught.result = begin raise StandardError, "This is an error" rescue StandardError => e "Rescued: #{e.message}" end puts result # Output: Rescued: This is an errorCustom Exception Handling
Developers benefit from creating their custom exception classes or identifying specific exception types to tailor their error management strategies.
Defining Custom Exception Classes
The
Exceptionclass or, more preferably, its subclass,StandardError, are parents to all user-defined exceptions. This inheritance ensures that all custom exceptions are catchable viarescue.class MyCustomError < StandardError # Additional behavior or settings end raise MyCustomError, "Something went wrong!"Identifying the Right Exception
An error’s distinct nature often demands a corresponding exception. For instance, consider a method handling file operations:
def read_file(file_path) raise ArgumentError, "File path is empty" if file_path.to_s.empty? raise IOError, "File not found" unless File.exist?(file_path) File.read(file_path) endUpon calling
read_file, any exception correlated to an invalid file path can be reliably caught and addressed with a targetedrescueblock.Error Handling Best Practices
-
Keep it Precise: Make use of granular
rescueblocks orcasestatements to align the corrective measures with the specific error. -
Maintain a Balance: Overuse of exceptions can convolute code and hinder its readability. Carefully select the exceptions likely to surface and necessitate special attention.
-
Locale Transparency: Choose either a local exception resolver that terminates in the current method or a global one that percolates up the call stack, but aim for consistency.
Performance Considerations
While exceptions can be invaluable for isolated and unexpected mishaps, triggering and managing them incurs a performance cost. It’s typically wiser to leverage them predominantly in such scenarios and not as part of conventional program flow.
- 9.
Describe the difference between local, instance, and class variables.
Answer:Let’s set the record straight on the differences between local, instance, and class variables in Ruby.
Common Features
All three variable types support:
- naming: 
- assignment:
variable_name = value - access control:
public,private, andprotected - immediacy: their scope begins from where they are initialized and exists until the scope ends.
Local Variables
- Scope: Limited to the block where they are defined.
- Life Cycle: Created when the program reaches their definition and destroyed when the block is exited.
Example: Local Variable
Here is the Ruby code:
def hello name = "Ruby" puts "Hello, #{name}!" # Output: Hello, Ruby! end # Accessing name outside its defined block will cause an error. # puts name # Will raise an errorInstance Variables
Naming Convention
An instance variable is prefixed with a single ‘@’ symbol.
- Scope: Primarily within the class, but is accessible from outside the class if the class is instantiated.
- Life Cycle: Created when an object is instantiated and remains available until that particular object is destroyed.
Example: Instance Variable
Here is the Ruby code:
class Greeting def set_name(name) @name = name end def display_greeting puts "Hello, #{@name}!" # Output: Hello, Ruby! end end greeting_instance = Greeting.new greeting_instance.set_name("Ruby") greeting_instance.display_greetingClass Variables
Naming Convention
A class variable is prefixed with two ‘@’ symbols.
- Scope: Within the class and its inheritors but not accessible from outside.
- Life Cycle: Created when assigned within the class or its inheritors and accessible as long as the class or one of its inheritors is in memory.
Example: Class Variable
Here is the Ruby code:
class Employee @@company_name = "ABC Corporation" def self.company_name=(name) @@company_name = name end def display_company_name puts @@company_name end end employee1 = Employee.new employee2 = Employee.new # Output: "ABC Corporation" for both employee1 and employee2. employee1.display_company_name employee2.display_company_name Employee.company_name = "New Company" # changes the class variable # After changing, outputs for both employee1 and employee2 will be "New Company". employee1.display_company_name employee2.display_company_name - 10.
What are Ruby’s accessor methods?
Answer:In Ruby, accessor methods allow you to manipulate object attributes. There are three types of accessor methods:
attr_reader,attr_writer, andattr_accessor, each serving a specific role in the attribute’s lifecycleAttribute Methods
attr_reader: Generates a simple getter method for an attribute. It can be accessed but not modified externally.attr_writer: Generates a basic setter method. The attribute can be modified but not read externally.attr_accessor: Combines both getter and writer methods in one. This creates a full-fledged getter and setter for the attribute.
Code Example: Accessor Methods
Here is the Ruby code:
class Person attr_reader :name, :age attr_writer :name, :age def initialize(name, age) @name = name @age = age end end person = Person.new("Alice", 30) person.name # Returns "Alice" person.name = "Bob" # Error: undefined method 'name=' person.age # Returns 30 person.age = 35 # Error: undefined method 'age=' person.instance_variables # Returns [:@name, :@age] - 11.
How does garbage collection work in Ruby?
Answer:Ruby employs automatic memory management, which is primarily influenced by garbage collection techniques. Let’s understand the specifics.
Mark-and-Sweep Algorithm
-
Step 1 - Mark: The process starts from the root of object references. The GC traverses memory, marking referenced objects.
-
Step 2 - Sweep: It scans for unmarked objects and reclaims their memory, making it available for future use.
Generational Garbage Collection
To optimize the Mark-and-Sweep approach, Ruby introduces generational garbage collection.
-
Focused on Object Age: Objects are classified based on their age.
-
Young vs. Old Objects:
- New objects start in the Young Generation.
- Objects that persist multiple GC cycles move to the Old Generation.
-
Collection Frequency: The Young Generation is collected more frequently.
-
Short- and Long-Lived Object Management: It’s easier to collect younger objects, reducing the scope and overhead of a complete garbage collection cycle.
Reference-Counting and
ObjectSpaceAlthough CPython uses reference-counting to track object lifespans, Ruby typically does not.
-
ObjectSpace: It’s a module that allows retrieval of all objects.
However, note that modern Ruby versions represent a hybrid system, sensitive to object types and context.
Code Example: Garbage Collection in Ruby
Here is the Ruby code:
# Enable trashcan (Ruby 2.6 onwards) ObjectSpace::count_objects[:FREE] > 100_000 && GC.start # Ruby versions before 2.6 GC.start -
- 12.
Explain the difference between ‘gets.chomp’ and ‘gets.strip’.
Answer:Let me go through the major difference.
Key Distinctions
-
Input Requirement:
gets.chompremoves all trailing whitespace and the newline character.gets.stripeliminates all leading and trailing whitespace, including the newline character.
-
Use Cases:
gets.chomp: Suited when you anticipate or require specific trailing characters to be preserved.gets.strip: Ideal for scenarios where you need to sanitize or validate user input by removing any extra leading or trailing spaces.
Code Sample:
gets.chomp&gets.stripHere is the Ruby code:
# Using the gets.chomp method puts "Enter your name (including a trailing space): " name_chomp = gets.chomp puts "Name with trailing space: #{name_chomp}" # Using the gets.strip method puts "Enter your name: " name_strip = gets.strip puts "Name without trailing space: #{name_strip}" -
- 13.
What is the role of ‘self’ in Ruby?
Answer:In Ruby,
selfserves as a “mirror” that reflects the current context. Depending on where it’s used,selfcan represent different objects.Here’s the breakdown:
Selfin Different Contexts1. Instance Methods
In this context,
selfrefers to the instance of the object on which the method is called.Consider the following code:
class MyClass def instance_method puts self end end object = MyClass.new object.instance_methodThe output would be the object reference
#<MyClass:0x007fb4fa869358>.2. Class Methods
Within a class definition,
selfrefers to the class itself. This is why you useself.method_nameto define class methods.For instance:
class MyClass def self.class_method puts self end end MyClass.class_methodThe output will be the class
MyClass.3. Method Invocation
When a method is missing due to a typo or other reason, Ruby executes
method_missingwhich can help handle such cases.Consider this example:
class MyClass def method_missing(m, *args) puts "There's no method called #{m}" end def test_method method_thaat_doesnt_exist end endCalling
test_methodwill invokemethod_missingwith the method name"method_thaat_doesnt_exist". - 14.
Explain the principle of ‘Convention over Configuration’ in the context of Ruby.
Answer:Convention over Configuration (CoC) is a software design principle that simplifies development by reducing the number of decisions developers need to make.
In its essence, CoC means that frameworks come with best practice defaults or “conventions” that are automatically applied unless explicitly configured to behave differently.
Practical Application
- Code-Base Structures: Many Ruby web frameworks, like Ruby on Rails or Sinatra, expect a certain directory structure that groups related files.
- Naming Conventions: Specially designed rules for naming classes, methods, and databases to help in identification and automatic linking.
- API Endpoints: Through consistent naming, it’s possible to infer routing information in web applications.
- Database Schemas: Named fields and tables allow the ORM to deduce relationships and configurations.
Example: CRUD Actions in RoR
In Ruby on Rails, the “conventions” for a resourceful route automatically map HTTP verbs to CRUD actions:
# config/routes.rb resources :articles # Routes: # HTTP Path Controller#Action Used For # ------------------------------------------------------------ # GET /articles articles#index Display a list # GET /articles/:id articles#show Display a specific article # GET /articles/new articles#new Display a form to create a new article # POST /articles articles#create Add a new article to the database # GET /articles/:id/edit articles#edit Display a form to edit an existing article # PATCH /articles/:id articles#update Update an existing article in the database # PUT /articles/:id articles#update (Alternate for update) # DELETE /articles/:id articles#destroy Remove a specific article from the databaseHere, the convention to map action names to routes frees the developer from configuring each route manually.
Benefits
- Speed: It streamlines development and reduces boilerplate.
- Interoperability: CoC enables consistency across different projects and teams.
Risks and Challenges
- Over-optimization: While it’s efficient for simple, well-understood requirements, it can make advanced configurations and customizations cumbersome.
- Learning Curve: Newcomers might find it challenging to adapt to these standard conventions.
- Magic: Over-reliance on CoC can make the system seem like it has hidden, unexplained behaviors.
- 15.
How does Ruby support metaprogramming?
Answer:Ruby offers powerful metaprogramming capabilities, enabling developers to write flexible, dynamic code. Key to Ruby’s metaprogramming are
classmethods such asdefine_methodand language features likeOpen Classesleading to advanced techniques likeDynamic Dispatch.Dynamic Dispatch Mechanism
- Dynamic Dispatch: Methods can be called at runtime, based on the object’s context, using
send. This makes it easier to manage method invocations in metaprogrammed code.
class MathOperations def do_operation(operator, x, y) send(operator, x, y) # Dynamic dispatch end private def add(x, y) x + y end def subtract(x, y) x - y end end result = MathOperations.new.do_operation(:add, 10, 5) # 15Class Modifications with
Open Classes-
Open Classes: Ruby allows changing a class’s definition dynamically, even after its initial declaration.
This example adds a
reversemethod to theStringclass.class String def reverse chars.reverse.join end end
Code Evaluation and Execution
-
Code Evaluation: Code strings can be executed within a bound context, enabling runtime code execution and evaluation.
This is an example using
evalto define a method at runtime, equivalent todef double(x) x * 2; end, but the method signature is constructed dynamically.method_signature = 'double(x)' method_body = 'x * 2' eval("def #{method_signature}; #{method_body}; end") -
Binding Tasks:
procobjects capture both the method (or block) and its associated context. They can be transferred across lexical scopes, allowing delayed execution of code.context = binding task = Proc.new { eval 'some_method', context } -
Context Toggling: By toggling a method’s visibility, you can control its access scope.
class MyClass def some_method "Public method" end private def toggle_method_visibility(visibility) # `send` here is being used for dynamic dispatch send(visibility, :some_method) end end instance = MyClass.new instance.toggle_method_visibility(:private)
Internationalization: Advanced Use of
sendandeval-
Localizing Method Calls: In internationalization tasks where method calls need to be localized,
send,public_send, or even the more generalevalcan be suitable.def greeting(language) eval("#{language}_greeting") end def spanish_greeting "Hola Mundo" end
Method Missing and Missing Method Feature
-
Method Missing: This feature is the heart of Ruby’s duck typing. It allows classes and objects to respond to method calls even when their definitions are absent, rather than resorting to method-not-found errors.
This example cleans up a method call, removing spaces or underscores.
def method_missing(name, *args, &block) cleaned_name = name.to_s.delete(' ').delete('_') send(cleaned_name, *args, &block) end -
respond_to_missing?: This method is often used in conjunction withmethod_missing, providing a way for a class to communicate whether it handles a method call beyond what is statically defined.
- Dynamic Dispatch: Methods can be called at runtime, based on the object’s context, using