Ruby is a dynamic, open-source programming language with a focus on simplicity and productivity. It has an elegant syntax that is natural to read and easy to write.
Variables in Ruby are created by simply assigning a value, e.g., x = 5. There is no need to declare the type.
'puts' adds a new line after outputting the content, while 'print' does not add a new line.
Single-line comments start with a # symbol. Multi-line comments can be written between =begin and =end.
Methods are defined using the 'def' keyword, followed by the method name and an optional parameter list. Example: def greet(name); puts \"Hello, #{name}\"; end
String interpolation allows embedding expressions inside string literals using #{expression} syntax within double-quoted strings.
Arrays are created using square brackets, e.g., arr = [1, 2, 3].
Elements are accessed using zero-based indexing, e.g., arr[0] returns the first element.
A hash is a collection of key-value pairs, created using curly braces, e.g., h = { 'a' => 1, 'b' => 2 }.
If statements use the 'if' keyword. Example: if x > 5; puts 'Greater'; end
You can use 'while', 'until', or 'for' loops. Example: while i < 5; puts i; i += 1; end
Use gets to read input from the user. Example: name = gets.chomp
'==' checks for value equality, while '===' is used in case statements and can have custom behavior depending on the class.
Use begin-rescue-end blocks. Example: begin; # code; rescue; # handle error; end
Use the 'require' or 'require_relative' keywords to include external files or libraries.
A module is a collection of methods and constants that can be mixed into classes using 'include' or 'extend'. Unlike classes, modules cannot be instantiated or subclassed.
Mixins allow sharing reusable code across multiple classes by including modules. This enables multiple inheritance-like behavior without the complexity of class hierarchies.
Class variables are prefixed with @@ and are shared among all instances of a class. Example: @@count = 0. They can be accessed and modified by all instances and the class itself.
'self' refers to the current object or class context. It is used to define class methods, access instance variables, or refer to the current receiver of a method.
Custom exceptions are created by subclassing the StandardError class. Example: class MyError < StandardError; end
'include' mixes module methods as instance methods, while 'extend' adds module methods as class methods to the target object.
Blocks are chunks of code passed to methods. Procs and lambdas are objects representing blocks, but lambdas check arguments strictly and handle 'return' differently compared to procs.
'map' transforms each element and returns a new array, while 'select' filters elements based on a condition. Example: arr.map { |x| x*2 }, arr.select { |x| x > 2 }
Method overriding is redefining a method in a subclass that already exists in the parent class. The subclass's method will be called instead of the parent's.
Use 'attr_reader' to create a getter method without a setter, making the attribute read-only from outside the class.
'super' calls the same method from the superclass, allowing you to extend or modify inherited behavior while still using the parent implementation.
Monkey patching is the practice of modifying or extending existing classes or modules at runtime, often to add or change functionality.
Use the File class to read and write files. Example: File.open('file.txt', 'w') { |f| f.puts 'Hello' }
'require' loads a file once and is used for libraries, while 'load' loads the file every time it is called, making it suitable for dynamic code reloading.
A singleton method is defined on a single object using 'def object.method_name; end'. This method is only available to that specific object.
Metaprogramming is writing code that writes or manipulates other code at runtime. In Ruby, this is achieved using methods like define_method, method_missing, and class_eval to dynamically define methods or alter classes/modules.
Ruby uses a mark-and-sweep garbage collector to automatically reclaim memory occupied by objects that are no longer referenced. Modern Ruby versions use generational and incremental garbage collection for improved performance.
Class variables (@@var) are shared across a class and all its descendants, while class instance variables (@var) belong only to the class object itself and are not shared with subclasses.
Thread safety can be achieved using Mutexes to synchronize access to shared resources, using thread-local variables, or leveraging concurrent data structures provided by gems like 'concurrent-ruby'.
'method_missing' is a hook method called when an object receives a message it cannot handle. It allows dynamic handling of undefined methods, often used in DSLs and proxies.
Refinements provide a way to scope monkey patches to specific modules or classes, avoiding global changes. They are activated with 'using' and are useful for safely extending core classes.
Fibers are lightweight concurrency primitives for cooperative multitasking. They allow pausing and resuming execution at specific points, useful for implementing coroutines and non-blocking I/O.
DSLs are created using Ruby's flexible syntax, blocks, and metaprogramming features like instance_eval and method_missing to provide a natural, readable interface for specific problem domains.
'prepend' inserts a module before the class in the method lookup chain, so its methods override those in the class. 'include' inserts the module after the class, so class methods take precedence.
The Enumerator class allows external iteration over collections. You can create custom enumerators using Enumerator.new or by calling to_enum on objects, enabling lazy evaluation and chaining.
Monkey patching modifies existing classes or modules at runtime. While powerful, it can lead to maintenance issues, unexpected behavior, and compatibility problems, especially in large or shared codebases.
Ruby searches for methods in the receiver's singleton class, then its class, included modules (in order), superclass, and so on up the inheritance chain, following the method lookup path.
An eigenclass is a hidden, anonymous class attached to every object, where singleton methods are stored. It allows per-object method definitions and is accessed via 'class << obj'.
Memoization caches the result of expensive method calls. In Ruby, it's commonly implemented by storing results in an instance variable and returning the cached value on subsequent calls.
'yield' passes control from a method to an associated block. Alternatives include using 'block_given?' to check for a block, or explicitly passing and calling a Proc or lambda.
Lambdas check the number of arguments strictly and return only from themselves, while procs are lenient with arguments and return from the enclosing method.
Methods can be dynamically defined using define_method, class_eval, or instance_eval, allowing runtime creation of methods based on program logic.
'alias' and 'alias_method' create new names for existing methods. 'alias' is a keyword used at the class level, while 'alias_method' is a method that can be called dynamically.
To create custom enumerables, include the Enumerable module and define an 'each' method that yields elements. This provides access to many useful iteration methods.
Global variables (prefixed with $) are accessible from anywhere in the program, which can lead to code that is hard to maintain, debug, and test due to unintended side effects.