0
0
Rubyprogramming~15 mins

Send for calling methods dynamically in Ruby - Deep Dive

Choose your learning style9 modes available
Overview - Send for calling methods dynamically
What is it?
In Ruby, the 'send' method lets you call another method by its name stored as a symbol or string. Instead of writing the method name directly, you pass it as an argument to 'send', and Ruby runs that method for you. This allows you to decide which method to call while the program is running, not just when you write the code.
Why it matters
Without 'send', you would have to write every method call explicitly, making your code less flexible and harder to change. 'Send' lets programs adapt by choosing methods on the fly, which is useful for things like handling user input, building reusable code, or metaprogramming. It makes Ruby powerful for dynamic tasks and reduces repetitive code.
Where it fits
Before learning 'send', you should understand how to define and call methods normally in Ruby. After mastering 'send', you can explore metaprogramming techniques, method_missing, and dynamic proxies that rely on calling methods dynamically.
Mental Model
Core Idea
'Send' is like a remote control that lets you press any button (method) by name, even if you decide the button only when the program runs.
Think of it like...
Imagine a TV remote with many buttons. Normally, you press a button directly to change the channel. Using 'send' is like telling someone the button's name out loud, and they press it for you. You don't need to press the button yourself; you just say which one to press.
┌─────────────┐
│ Object      │
│             │
│  ┌────────┐ │
│  │ send() │─┼─> Calls method named by argument
│  └────────┘ │
└─────────────┘
       │
       ▼
┌─────────────┐
│ Method Name │
│ (symbol/str)│
└─────────────┘
Build-Up - 7 Steps
1
FoundationBasic method calling in Ruby
🤔
Concept: Learn how to define and call methods normally.
def greet puts 'Hello!' end greet # Calls the greet method normally
Result
Hello!
Understanding normal method calls is essential before using dynamic calls like 'send'.
2
FoundationSymbols and strings as method names
🤔
Concept: Method names can be represented as symbols or strings in Ruby.
method_name = :greet puts method_name.class # Symbol method_name_str = 'greet' puts method_name_str.class # String
Result
Symbol String
Knowing that method names can be stored as symbols or strings allows dynamic method calling.
3
IntermediateCalling methods dynamically with send
🤔Before reading on: do you think 'send' can call private methods? Commit to your answer.
Concept: 'Send' calls a method by its name given as a symbol or string, even if the method is private.
class Person def greet puts 'Hi!' end private def secret puts 'This is a secret.' end end p = Person.new p.send(:greet) # Calls public method p.send('secret') # Calls private method
Result
Hi! This is a secret.
Understanding that 'send' bypasses normal access controls helps you use it carefully and powerfully.
4
IntermediatePassing arguments with send
🤔
Concept: 'Send' can call methods that take arguments by passing them after the method name.
class Calculator def add(a, b) a + b end end calc = Calculator.new result = calc.send(:add, 5, 7) puts result
Result
12
Knowing how to pass arguments with 'send' makes it flexible for many method calls.
5
IntermediateUsing send for dynamic method selection
🤔Before reading on: do you think 'send' can be used to call methods based on user input safely? Commit to your answer.
Concept: 'Send' lets you choose which method to call at runtime, for example, based on user input or program state.
class Robot def walk 'Walking' end def run 'Running' end end robot = Robot.new command = :walk # Could come from user input puts robot.send(command)
Result
Walking
Using 'send' for dynamic calls enables flexible programs but requires care to avoid security risks.
6
Advancedsend vs public_send differences
🤔Before reading on: do you think 'public_send' can call private methods? Commit to your answer.
Concept: 'public_send' only calls public methods, unlike 'send' which can call private and protected methods.
class SecretAgent def public_info 'Public info' end private def secret_info 'Top secret' end end agent = SecretAgent.new puts agent.public_send(:public_info) # Works puts agent.public_send(:secret_info) # Raises error # agent.send(:secret_info) would work
Result
Public info Error: NoMethodError for secret_info
Knowing the difference helps avoid accidental access to private methods and improves code safety.
7
Expertsend in metaprogramming and method_missing
🤔Before reading on: do you think 'send' is used internally by Ruby's method_missing? Commit to your answer.
Concept: 'Send' is a core tool in metaprogramming, letting you forward calls, define dynamic behavior, and implement method_missing handlers.
class DynamicProxy def initialize(target) @target = target end def method_missing(name, *args, &block) puts "Forwarding #{name} to target" @target.send(name, *args, &block) end end class Speaker def hello 'Hello from Speaker' end end proxy = DynamicProxy.new(Speaker.new) puts proxy.hello
Result
Forwarding hello to target Hello from Speaker
Understanding 'send' as the backbone of dynamic method forwarding unlocks advanced Ruby metaprogramming.
Under the Hood
'Send' works by taking the method name as a symbol or string and looking up that method in the object's method table at runtime. It then invokes the method with any given arguments, bypassing normal method call syntax. Because Ruby methods are objects internally, 'send' uses this dynamic lookup to call methods even if they are private or protected.
Why designed this way?
Ruby was designed for flexibility and expressiveness. 'Send' was created to allow dynamic method calls, enabling metaprogramming and reducing boilerplate. It lets programmers write code that adapts at runtime, which was a key design goal of Ruby's creator, Yukihiro Matsumoto. Alternatives like static method calls would limit this flexibility.
┌───────────────┐
│ Object        │
│  ┌─────────┐  │
│  │ send()  │  │
│  └────┬────┘  │
└───────│───────┘
        │
        ▼
┌─────────────────────┐
│ Method Name (symbol) │
└─────────┬───────────┘
          │
          ▼
┌─────────────────────────────┐
│ Look up method in object's   │
│ method table (including priv)│
└─────────┬───────────────────┘
          │
          ▼
┌─────────────────────────────┐
│ Invoke method with arguments │
└─────────────────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does 'send' respect Ruby's private method access rules? Commit to yes or no.
Common Belief:Many think 'send' only calls public methods and respects access controls.
Tap to reveal reality
Reality:'Send' can call private and protected methods, ignoring normal access restrictions.
Why it matters:This can lead to unexpected bugs or security holes if private methods are called unintentionally.
Quick: Can 'send' call methods that don't exist without error? Commit to yes or no.
Common Belief:Some believe 'send' can call any method name safely, even if it doesn't exist.
Tap to reveal reality
Reality:'Send' raises a NoMethodError if the method name does not exist on the object.
Why it matters:Assuming 'send' is safe for any method name can cause runtime crashes.
Quick: Is using 'send' always safe with user input? Commit to yes or no.
Common Belief:People often think it's safe to use 'send' with any user input as method names.
Tap to reveal reality
Reality:Using 'send' with unchecked user input can allow calling dangerous or private methods.
Why it matters:This can cause security vulnerabilities or unexpected behavior in applications.
Quick: Does 'public_send' behave exactly like 'send'? Commit to yes or no.
Common Belief:Some assume 'public_send' is just a synonym for 'send'.
Tap to reveal reality
Reality:'Public_send' only calls public methods and raises errors for private/protected ones.
Why it matters:Confusing these can lead to bugs or accidental exposure of private methods.
Expert Zone
1
'Send' can be overridden in classes, which can change its behavior and cause subtle bugs.
2
Using 'send' bypasses method visibility, so it should be used carefully to avoid breaking encapsulation.
3
'Send' is slower than direct method calls because of dynamic lookup, so avoid it in performance-critical code.
When NOT to use
Avoid 'send' when you can call methods directly or use 'public_send' for safer public method calls. For very dynamic dispatch, consider method_missing or define_method instead.
Production Patterns
'Send' is often used in DSLs (domain-specific languages), dynamic proxies, serializers, and frameworks like Rails to call methods based on strings or symbols dynamically.
Connections
Reflection in programming
'Send' is a form of reflection that lets programs inspect and call methods dynamically.
Understanding 'send' helps grasp how reflection allows programs to modify behavior at runtime.
Command pattern (software design)
'Send' enables dynamic method invocation similar to how the command pattern encapsulates method calls.
Knowing 'send' clarifies how commands can be stored and executed flexibly in software.
Human language verbs
Just like verbs describe actions that can be chosen dynamically in sentences, 'send' lets programs choose actions (methods) dynamically.
This connection shows how dynamic method calls mirror flexible action choices in communication.
Common Pitfalls
#1Calling private methods unintentionally with send
Wrong approach:object.send(:private_method)
Correct approach:Use object.public_send(:public_method) to avoid calling private methods
Root cause:Misunderstanding that 'send' ignores method visibility and can call private methods.
#2Using send with unchecked user input
Wrong approach:user_input = gets.chomp object.send(user_input)
Correct approach:allowed = [:start, :stop, :pause] user_input = gets.chomp.to_sym object.send(user_input) if allowed.include?(user_input)
Root cause:Not validating user input before using it as a method name leads to security risks.
#3Assuming send can call non-existent methods safely
Wrong approach:object.send(:non_existent_method)
Correct approach:if object.respond_to?(:non_existent_method) object.send(:non_existent_method) else puts 'Method not found' end
Root cause:Not checking method existence before calling with 'send' causes runtime errors.
Key Takeaways
'Send' lets you call methods by name dynamically, using symbols or strings.
'Send' can call private and protected methods, so use it carefully to avoid breaking encapsulation.
Passing arguments with 'send' works like normal method calls, making it flexible.
'Public_send' is a safer alternative that only calls public methods.
Using 'send' without validating input can cause security and stability problems.