Variables & Types
name = "Alice"Local variable — lowercase or underscore prefix@name = "Alice"Instance variable — available throughout the object@@count = 0Class variable — shared across all instances$global = "shared"Global variable — available everywhere, use sparinglyMAX = 100Constant — uppercase, warns if reassigned42 / 3.14Integer / Float"hello" / 'hello'String — double quotes allow interpolation, single are literaltrue / falseBooleannilAbsence of value (like null):name / :statusSymbol — immutable, memory-efficient identifier[1, 2, 3]Array{ name: "Alice", age: 30 }Hash (with symbol keys)(1..10) / (1...10)Inclusive range / exclusive rangex, y = 1, 2Multiple assignmenta, *rest = [1, 2, 3, 4]Splat unpacking — rest = [2, 3, 4]x.classReturn the class of an objectx.is_a?(Integer)True if x is an Integer (or subclass)x.nil?True if x is nilStrings
"Hello, #{name}!"String interpolation — only works in double-quoted strings"a" + "b" / "a" << "b"Concatenate — << mutates the receiver"ab" * 3Repeat: "ababab"s.length / s.sizeNumber of characterss[0] / s[-1] / s[1..3]Character / last char / substring by ranges.upcase / s.downcaseChange cases.capitalizeFirst letter uppercase, rest lowercases.strip / s.lstrip / s.rstripStrip whitespace from both / left / rights.chomp / s.chopRemove trailing newline / remove last characters.include?("sub")True if substring founds.start_with?("pre") / s.end_with?("suf")Check prefix / suffixs.index("sub")First index of substring (nil if not found)s.split(",") / s.splitSplit on delimiter / split on whitespace["a","b"].join(", ")Join array into strings.gsub("a", "b")Replace all occurrencess.gsub(/\d+/, "N")Replace all regex matchess.sub("a", "b")Replace first occurrence onlys.match?(/pattern/)True if regex matchess.chars / s.bytesArray of characters / bytess.to_i / s.to_f / s.to_symConvert to integer / float / symbol42.to_s / 3.14.to_sConvert to string<<~HEREDOC ... HEREDOCHeredoc — squiggly (~) strips leading whitespaceArrays & Hashes
arr = [1, 2, 3]Array literalarr.push(4) / arr << 4Append to endarr.pop / arr.shiftRemove and return last / first elementarr.unshift(0)Prepend elementarr.first / arr.lastFirst / last elementarr.first(3) / arr.last(3)First / last N elementsarr.length / arr.size / arr.countNumber of elementsarr.include?(val)True if value existsarr.flatten / arr.flatten(1)Flatten nested arrays / one level deeparr.compactRemove nil valuesarr.uniqRemove duplicatesarr.sort / arr.sort_by { |x| x.name }Sort / sort by keyarr.reverseReturn reversed arrayarr.min / arr.max / arr.sum / arr.minmaxMin / max / sum / [min, max]arr.map { |x| x * 2 }Transform each element — returns new arrayarr.select { |x| x > 2 }Filter — returns matching elementsarr.reject { |x| x > 2 }Filter — returns non-matching elementsarr.reduce(0) { |sum, x| sum + x }Fold to single valuearr.each_with_index { |x, i| }Iterate with indexarr.each_with_object({}) { |x, h| h[x] = x**2 }Iterate, building an accumulatorarr.zip([4,5,6])Pair up elements: [[1,4],[2,5],[3,6]]arr.take(3) / arr.drop(3)First N / skip first N elementsarr.any? { |x| x > 2 } / arr.all? { |x| x > 0 } / arr.none? { |x| x < 0 }Any / all / none match predicatearr.flat_map { |x| [x, x*2] }Map then flatten one levelhash = { name: "Alice", age: 30 }Hash with symbol keyshash[:name] / hash["key"]Access by symbol / string keyhash[:name] = "Bob"Set or update keyhash.fetch(:name) / hash.fetch(:name, "default")Fetch — raises KeyError or returns default if missinghash.key?(:name) / hash.value?("Alice")Check key / value existencehash.keys / hash.valuesArray of keys / valueshash.merge(other) / hash.merge!(other)Merge — merge! mutates receiverhash.select { |k, v| v > 1 }Filter key-value pairshash.map { |k, v| [k, v * 2] }.to_hTransform values into new hashhash.each { |k, v| }Iterate key-value pairshash.delete(:name)Remove key and return its valueControl Flow
if x > 0 ... elsif x < 0 ... else ... endif / elsif / else — end closes the blockputs "positive" if x > 0Inline if (modifier form)unless x.nil? ... endunless = if notputs "present" unless x.nil?Inline unlessx > 0 ? "pos" : "neg"Ternary operatorcase x\nwhen 1 then "one"\nwhen 2, 3 then "two or three"\nelse "other"\nendcase/when — uses === for comparisoncase x\nwhen String then "string"\nwhen Integer then "int"\nendcase with type matchingx = value || "default"Return x if truthy, else default (only nil and false are falsy)x ||= "default"Assign default if x is nil or falsex&.methodSafe navigation — call method only if x is not nilwhile x > 0 ... endLoop while condition is trueuntil x == 0 ... enduntil = while notloop do ... break if condition ... endInfinite loop with explicit break5.times { |i| }Repeat N times1.upto(5) { |i| } / 5.downto(1) { |i| }Iterate range up / down(1..5).each { |i| }Iterate over rangenext / break / redoSkip iteration / exit loop / restart iterationMethods
def greet(name)\n "Hello, #{name}!"\nendMethod — last expression is implicitly returneddef greet(name = "World")Default parameterdef fn(*args)Splat — collects extra positional args as arraydef fn(**opts)Double splat — collects keyword args as hashdef fn(*args, **opts, &block)Accept any combination including a blockdef greet(name:, greeting: "Hello")Keyword arguments with optional defaultfn(name: "Alice")Call with keyword argumentsreturn valueExplicit return — not usually neededdef valid?\ndef save!Convention: ? for predicates, ! for mutating/dangerous methodsprivate / protected / publicVisibility modifiers — apply to methods below themprivate def helperInline visibility on a single method (Ruby 2.1+)method(:name) / obj.respond_to?(:name)Get method object / check if method existsClasses & Modules
class Dog < Animal\n def initialize(name)\n @name = name\n end\nendClass inheriting Animal with constructordog = Dog.new("Rex")Instantiate objectdog.name / dog.name = "Max"Getter / setterattr_reader :nameGenerate getter onlyattr_writer :nameGenerate setter onlyattr_accessor :name, :ageGenerate both getter and setterdef self.create(name)\n new(name)\nendClass method (factory pattern)super / super(args)Call same method on parent classselfCurrent object — the receiver of the current methoddog.instance_of?(Dog)True if exactly Dog (not subclass)dog.is_a?(Animal)True if Dog or any ancestormodule Greetable\n def greet = "Hello!"\nendModule — namespace and mixin containerinclude GreetableMix module into instances (adds instance methods)extend GreetableMix module into the class itself (adds class methods)prepend GreetableLike include but inserted before the class in method lookupComparable / EnumerableBuilt-in modules — include to get <=>, sort, min/max etc.Blocks, Procs & Lambdas
[1,2,3].each { |x| puts x }Block with braces — convention for single-line[1,2,3].each do |x|\n puts x\nendBlock with do/end — convention for multi-linedef run\n yield\nendyield — calls the block passed to the methoddef run\n yield(42) if block_given?\nendyield with argument, guard with block_given?def run(&block)\n block.call(42)\nendCapture block as explicit Proc parameterdouble = Proc.new { |x| x * 2 }Proc — block as an objectdouble = proc { |x| x * 2 }Shorthand Proc.newdouble = lambda { |x| x * 2 }Lambda — strict argument count, own scope for returndouble = ->(x) { x * 2 }Lambda stabby syntax (preferred)double.call(5) / double.(5) / double[5]Call a Proc or Lambda[1,2,3].map(&method(:puts))Convert method to block with & and method()[1,2,3].map(&:to_s)Symbol#to_proc — shorthand for { |x| x.to_s }fn = ->(x, y) { x + y }\nadd = fn.curry.(1)Curry — partially apply arguments