[Rails] Weird signs in Ruby (||=, <<, ?, *, :, !)

Tags
Rails
Engineering
Created
Oct 24, 2023 02:57 AM
Edited
Oct 23, 2023
Description
||=, <<, ?, *, :, !

||=

a ||= b
If a is nil or false, then a = b.
irb(main):001:0> x = true
=> true
irb(main):002:0> x ||= "ruby"
=> true
irb(main):003:0> x
=> true

# And, likewise, with nil:
irb(main):014:0> x = nil
=> nil
irb(main):015:0> x ||= "ruby"
=> "ruby"
irb(main):016:0> x
=> "ruby"

# Also with false
irb(main):019:0> x = false
=> false
irb(main):020:0> x ||= "ruby"
=> "ruby"
irb(main):021:0> x
=> "ruby"

<<

'<<' as an ordinary method

Append to the end of the array (most common)

array = []
array << new_element

Concatenate two strings (most common)

"a" << "b"

Writing output to an IO

io << "new line\n"

Writing data to a message digest, HMAC or cipher

sha << "Text to be hashed"

?

It is a code style convention; it indicates that a method returns a boolean value (true or false) or an object to indicate a true value (or “truthy” value).
if alvin.present?
	puts "alvin is present"
end

*

Like a pointer?
💡
No! It is just like unwrap a list of arguments in Python.

:

  • A colon before text indicates a symbol in Ruby

!

In front of a variable

Just like not, but !has a higher precedence.
!true && false
=> false

not true && false
=> true # (true && false) is false

After a method

Part of a method name

Surprise! ! or ?are allowed in method names.

Convention to indicate "in-place" modifications

String#gsub: return a copy
String#gsub!: modify string in-place

Sometimes ! means mutation on the object

my_string.downcase() # returns a new instance
my_string.downcase!() # override the object

In Rails as a convention, method! raise an exception

Record.find_by(id: 10) # => Can return nil if not found
Record.find_by!(id: 10) # => Can raise ActiveRecord::RecordNotFound
This makes flow-control easier and code cleaner.
# update without !
def update
  if (user.save)
    if (purchase.save)
      if (email.sent?)
        redirect_to(success_path)
      else
        render(template: 'invalid_email')
      end
    else
      render(template: 'edit')
    end
  else
    render(template: 'edit')
  end
end
# update using !
def update
  user.save!
  purchase.save!
  email.send!

  redirect_to(success_path)

rescue ActiveRecord::RecordNotFound
  render(template: 'edit')
rescue SomeMailer::EmailNotSent
  render(template: 'invalid_email')
end

Sources