Skip to content

Instantly share code, notes, and snippets.

@laurenlucero
Last active November 22, 2022 22:26
Show Gist options
  • Save laurenlucero/4d77b7249d1df3a2020218189ccc7604 to your computer and use it in GitHub Desktop.
Save laurenlucero/4d77b7249d1df3a2020218189ccc7604 to your computer and use it in GitHub Desktop.
Ruby on Rails

Ruby Cheatsheet

"strings" are objects so they have a lot of .methods Strings represent text and data.

:symbols are identifiers to represent method & instance variable names. Every symbol is unique. Symbols are immutable (can't be changed). Symbols are not pointers to values, they are values themselves.

You should use symbols as names or labels for things (like methods) & use strings when you care more about the data (individual characters).

You might convert a symbol to a string because symbols only have a subset of the methods that a string has and symbols can’t be changed. If you want to work with the individual characters of the symbol then use.to_s You can also convert a string object into a symbol using .to_sym

To create an array of symbols: symbols = %i(a b c) [:a, :b, :c]

To creat an array of strings: strings = %w(a b c) ["a", "b", "c"]

A Hash is a dictionary-like collection of unique keys and their values AKA associative arrays. They are similar to Arrays, but where an Array uses integers as its index, a Hash allows you to use any object type.

nil is a special Ruby object used to represent an “empty” or “default” value. It’s also a “falsy” value, meaning that it behaves like false when used in a conditional statement. Everything else in Ruby is considered true in a boolean context.

In Ruby we don’t have a Boolean class, but we have boolean objects! true & false are the singleton objects of TrueClass & FalseClass

Boolean logic: AND & true/true=true true/false=false OR | true/true=true true/false=true XOR ^ true/true=false true/false=true

File methods: Read & Write files in Ruby with File.read & File.write Renaming a file File.rename("old-name.txt", "new-name.txt") File size in bytes File.size("users.txt") Does this file already exist? File.exists?("log.txt") Get the file extension, this works even if the file doesn't exists File.extname("users.txt") => ".txt" Get the file name without the directory part File.basename("/tmp/ebook.pdf") => "ebook.pdf" Get the path for this file, without the file name File.dirname("/tmp/ebook.pdf") => "/tmp" Is this actually a file or a directory? File.directory?("cats")

Regular expressions help you find specific patterns inside strings, with the intent of extracting data for further processing. Two common use cases for ruby regex include validation & parsing. Using a tool like Rubular can help you build your ruby regex in a more interactive way.

A gem is a package aka dependency that adds extra functionality to your Ruby program. A Bundler is a tool for dependency management.

Classes are the basic building blocks in OOP & they help you define a blueprint for creating objects ::class_method Objects are the unique products of the class, an individual “thing” with its own identity & its own data. Class names start with an uppercase letter. We use the class keyword then the end keyword.

Variables An @instance_variable is something your class knows and defines attributes. @@ClassVariables attribute all related objects $GlobalVariables can be used anywhere

Ruby Foundations

Blocks, Procs, and Enumerable

Enumerable is a Ruby module used to iterate over the elements of any class that implements the each method, like Array, Range & Hash

Blocks allow methods to take arbitrary snippets of code as arguments and run them Can be implicit or explicit

Procs is the concept of passing functions as arguments to other functions aka higher order functions We can pass a proc object instead of a block to any method by prefixing it with &

In Ruby, you might express “multiply each element of this collection by 2 and return the result” by passing the anonymous function n * 2 to the Enumerable#map method:

[1, 2, 3].map { |n| n * 2 } # => [2, 4, 6]

Proc example: double = Proc.new { |n| n * 2 } [1, 2, 3].map(&double) # => [2, 4, 6]

Ruby doesn’t immediately try to run the Proc passed into the function but instead calls #to_proc on it before execution which allows us to pass in any object that responds to #to_proc

Symbol defines #to_proc as a function that sends the message of the same name as the symbol to the target object i.e. [1,2,3].map(&:to_s) # => ["1", "2", "3"] sends the message :to_s to each item in the array

inject aka reduce is one of the most powerful methods provided by Enumerable

Constants and Environment Variables

Constants are a type of variable defined by starting with a Capital Letter or ALL CAPS which should not change. You can change the value of a constant but it will print a warning. Class names are constants. Avoid const_get with user input.

An environment variable is a key/value pair to share configuration options between all the programs in your computer

Requiring in Ruby

require and load are file-level methods used to "read" and parse files include and extend are language-level methods that can extend your class with other modules

RubyGem Each gem has a name, version, and platform. For example, the rake gem has a 0.8.7 version (May 2009). Rake’s platform is ruby, which means it works on any platform Ruby runs on. Inside gems are the following components:

  • Code (including tests and supporting utilities)
  • Documentation
  • gemspec

Common RubyGems Commands: gem search ^rails find gem search ^rails$ -d find with details gem install >< gem uninstall >< gem list ri >< view docs gem fetch >< audit contents without installing then gem unpack >< to extract content or use this modify installed gem gem help platform

Exceptions and Errors

Exceptions are Ruby's way of dealing with unexpected events.

"rescuing," "handling," or "catching" an exception means stopping the shutdown process caused by an error

begin
  # Any exceptions in here... 
  1/0
rescue
  # ...will cause this code to run
  puts "Got an exception, but I'm responding intelligently!"
    do_something_intelligent()
end 

^ This program does not crash.

Exception objects are normal Ruby objects that hold all of the data about "what happened" for the exception you just rescued.

"raising" with the raise method triggers your own exceptions

To make a custom exception, just create a new class that inherits from StandardError

class PermissionDeniedError < StandardError
end

raise PermissionDeniedError.new()
  • Rescuing errors of a specific class also rescues errors of its child classes.

  • Never rescue Exception in Ruby! The problem with rescuing Exception is that it actually rescues every exception that inherits from Exception. Which is....all of them!

  • Rescue StandardError Instead! All of the exceptions that you should care about inherit from StandardError. These are our old friends:

    • NoMethodError - raised when you try to invoke a method that doesn't exist
    • TypeError - caused by things like 1 + ""
    • RuntimeError - who could forget good old RuntimeError?
class SomethingBad < StandardError
end

raise SomethingBad

The Exception Tree:

Exception NoMemoryError ScriptError LoadError NotImplementedError SyntaxError SignalException Interrupt StandardError ArgumentError IOError EOFError IndexError LocalJumpError NameError NoMethodError RangeError FloatDomainError RegexpError RuntimeError SecurityError SystemCallError SystemStackError ThreadError TypeError ZeroDivisionError SystemExit fatal

Equality and Comparison

== returns true if both objects can be considered the same === checks equality in case statements eql? checks if 2 objects refer to the same hash key

when you actually need to check if two objects are the same object there’s the method equal? ex: "A".equal?("A") returns false

Other comparison operators are: less than <, less than or equal <=, greater than >, and greater than or equal >=

the ==, === and eql? methods are designed to be overridden in specialisations of the Object class

the only method to check object equality at an object ID level is equal?

Composition and Duck Typing

Composition-based solutions break up a problem into distinct responsibilities and encapsulate the implementation of each into separate objects. Composition is a more robust and flexible approach to architect reusable object-oriented software.

In an inheritance-based solution, a given object often has multiple responsibilities it has inherited from its various ancestors. Only reach for inheritance when it makes sense such as when building ActiveRecord models.

Dependency Management Patterns in Ruby

Delegation and method forwarding are useful patterns for dividing responsibilities between related objects. In plain Ruby projects, both Delegator and Forwardable can be used, whereas Rails code tends to gravitate towards its delegate method. For maximum control on what is delegated, the Casting gem is an excellent choice, though it's slightly more complex than the other solutions.

In Ruby the Observable module makes it possible for an object to maintain a list of its dependents and notify them automatically of any state changes.

Singleton pattern and Singleton Class (Eigenclass)

Use the Singleton module in Ruby to create singleton classes and prevent other instances from accidentally being created.

The Singleton pattern is simply an object-oriented programming pattern where you make sure to only have 1 and only 1 instance of some class. Ruby implement the Singleton pattern with a module: just write Include Singleton in your class definition and you're good to go.

  • Classes are what we use to define our objects (classes are just a particular kind of object)
  • Instances of classes are the objects created by our classes
  • The Eigenclass is called the Singleton class because it is a Class that follows the Singleton pattern.

The metaclass is called the singleton class because there is a single instance of it. Just like instance methods are defined in a class, class methods are defined in the metaclass of a class object. The inheritance chain of metaclasses is what allows to inherit and override class methods and call super.

Introspection and Reflection

Type introspection is a core feature of Ruby that makes it possible for your code to ask questions about itself. With type introspection a program can examine the type or properties of an object at runtime.

ObjectSpace gives you information about the current state of your application. Using ObjectSpace you can know what objects are currently ‘alive’ in your program.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment