find and find_by return a single record, while where returns a collection of every match, even when nothing matches.
find searches by primary key and raises ActiveRecord::RecordNotFound if the record is missing.
find_by takes any conditions and returns the first match, or nil if there is none. Its bang version, find_by!, raises instead.
where returns an ActiveRecord::Relation. The query does not run until you use the records, so you can chain more conditions first. When nothing matches, you get an empty relation, not nil.
User.find(1) # Raises error if not found
User.find_by(email: "a@b.com") # Returns nil if not found
User.where(active: true) # Returns Relation (chainable)
Use find when the record must exist, find_by when it may not, and where when you need a set of records.
Rewriting in plainer words…
This answer doesn't lend itself to a diagram - it reads best . No credits were charged.