-
Why Ruby is easy to get started but hard to maintain: "The meta-programming and object injection that makes (Ruby) easy to install 1,000 gems into your project without a single line of configuration, is exactly why it's hard to debug. It also gives you zero confidence or guarantees about what you've just added to your work and whether it all plays nice together. You may have just peed in your own kiddie pool. The magic of active record, the crazy levels of duck typing and the expressiveness of ruby, are exactly why it runs poorly even on your development box, and costs so much in server fees when you try to scale. It's why you have to build a caching strategy in as a requirement from first line of code."
-
Ruby has clearly lost the language war. 2019 "We're not looking to contribute to any language war," David added.
-
In Ruby, you put docstrings outside.
-
Methods do not require
()
to call. WTF? -
Methods that end in
?
are boolean functions by pure convention. -
And because boolean functions are purely by convention, this also means they can accept parameters:
@foo.bar?('baz')
-
?F
apparently means"F".ord
for Ruby < 1.9, and just"F"
in Ruby 1.9+. -
!
after a method applies changes the current object. Soa.upcase!
meansa = a.upcase
. -
.chomp
, which often followsgets
, removes the extra line at the end of console inputs. -
"Ruby prioritizes programmer productivity over program optimization."
-
if
,elsif
,else
,end
, becauseelseif
is just too long (butelif
is too Python, presumably). No need for:
at the end of each condition. -
Because if statements can be multi-line, it can be written in any form of indentation:
b = a? 5 else 3 end
, whereend
is required if you didn't oneliner it. -
Integer instantiation is
Integer(something)
. -
a_string.gsub(/regex/, "what")
-
while
is the same everywhere, except you needend
. No:
needed. -
until
is the backwardswhile
(executing while the check is false) -
There's no
++
, but there's still+= 1
. -
Hash.new(0)
creates adefaultdict
-like object, whose initial values are0
s. -
Hash
has somesort_by
thing which has some weird|a, b| b
array syntax. -
nil
is all lower case. -
an_array.each { |x| puts "#{x}\n" }
is totally possible. -
Hashes (dicts): the syntax is
{ a => b}
-
All ruby methods are available via
something.methods.sort
. -
All ruby methods specific to an object are avaiable via
something.own_methods.sort
. -
The Ruby REPL is
irb
. -
Ruby doesn't have functions; to get a reference to a callable without calling it, use
func_ref = method(:func_name)
ormethod_ref = instance.method(:method_name)
, and call withfunc_ref.call
. -
It would have been nice to have said that Ruby method names are also symbols.
-
Any class method automatically has a
self
(also@
; see below) for the instance, but you can rebind it withreference_to_method.bind(some_other_instance)
. It doesn't mean the instance now has that method; it just means you are calling the method with another instance. -
@foo
directly accesses an attribute..self.foo
accesses it first through adef foo
, if one exists, then falls back to@foo
. -
Results from the last expression is returned.
-
Ruby's
foldr
is calledinject
(if you use it this way). -
The
do
block has lower precedence than the bracket block syntax, allowing you to do concise loops in some cases:
123.upto 3 do |x|
puts x
end
123.upto 3 { |x| puts x }
# SyntaxError: compile error
- From above, "A [
do
] block is like an anonymous function or lambda. The variable between pipe characters is the parameter for this block." - I think functions can themselves be instances.
def something ... ... @names
is perfectly valid syntax. def
s needend
s.- The Ruby equivalent of
if __name__ == '__FILE__'
isif __FILE__ == $0
. some_obj.respond_to?(attribute)
is a special method that checks if an object has that attribute (or method, which is about the same for Ruby).- Having a
attr_accessor :name
line in a class creates automatic getters and setters for every instance'sname
, or@name
. def initialize
is the... uh... coffeescript? php? version for Ruby.- Since
nil
is Ruby'sNone
,.nil?
is the same as(... is None)
. - You can have double quotes in interpolated, doubled quoted strings! The guide's example was
puts "Goodbye #{@names.join(", ")}. Come back soon!"
Class.new(...)
returns an instance. Because of Ruby's awesome bracket omission,Class.new
also returns one, with no parameters given to the constructor.- To be consistent with their OOP philosophy,
sprintf
is a global function. - In a class, putting
private
somewhere in it makes everything below that line private. - Assuming
:method
is the syntax used to access the class method calledmethod
,private :method
marks it as private, if put underneath the declaration formethod
. - The "double at" (
@@foo
) is a class variable, making your previous point false. - The "double less than" (
class << instance
) adds all methods in that class to a particular instance of some other class, probably because there is noinstance.extend(class.__dict__)
equivalent. - Instead of
self.__class__
, it isself.class
.self
is not a named parameter. - Functions are not hoisted.
- Whitespace in blocks doesn't matter. Well, because there is a required
end
keyword. func do |arg1| ... end
is essentiallygenr = func(); (cb(arg1) for arg1 in genr)
, iffunc
is a generator function that usesyield
(and only works withyield
).- Lists can turn into the
func
above by calling.each
, i.e.[1,2,3,4].each do |i| ...
- "With blocks" are also done using blocks in Ruby:
File.open('somefile.txt') do |f|
puts f.readline
end
-
One-liner if statements have the following syntax:
condition ? true : false
(no if, no else) -
One-liner blocks are also possible.
[1,2,3,4].map{|i| i + 1}
is a block that is acting as a lambda. -
List filters using
select
and blocks:[1,2,3,4].select{|i| i % 2 == 0}
-
a_list.select(&:foo?)
uses&
andSymbol#to_proc
to filter out items in the list whose methodfoo?
isn't falsy. -
Because methods are immediately invoked, obtaining an attribute from it is also an invocation. However:
sentence.split.length # fine
sentence.split().length() # fine
sentence().split.length # not fine, strings (or maybe some things just) aren't callable
- The last-run statement in a function is the return value. Guess where coffeescript got this from!
- There's apparently a
for ... in
syntax, but nobody uses it, claims redditor. print
is a thing, andputs
is a thing too. Their equivalents areprint foo,
andprint foo
.is_a
andkind_of
are the same method: true if the object is an instance of that class or its subclasses.instance_of
, on the other hand, checks for its exact class.- Symbols are pairs of ids and immutable strings. They look like
:this
, and have performance benefits because of their immutability. - Use symbols whenever you would use a constant, including dictionary keys.
- In Ruby 1.9+, dictionaries whose keys are symbols don't need to use the
=>
association syntax. Use the more "normal" syntax instead:{simon: "Talek", lorem: "Ipsum"}
- Not until Ruby 2.2 did it GC symbols, creating security issues for Rails sites.
- The
gem
thing lets you list available versions if you provide two flags:gem list package_name --remote --all
[a..b]
includes theb
th element.[a...b]
does not. This makes[a...b]
the formally correct slicing operator.- There is the
||=
operator, which is actually intuitive:a = a || ...
&:
is the pluck shortcut, which means|thing| thing.foo
. "The&
callsSymbol#to_proc
on the object, and passes it as a block to the method.":foo
, which is a Symbol, is what gets passed into the method.- Ruby also does the whole
defined?
thing that PHP does.defined?
appears to be a top-level global, and accepts any class in any namespace. - Ruby try/catch/else/finally blocks are named
begin/rescue/else/ensure
. Because there is noas
, the exception is assigned with the association syntax (that's right)rescue SomeExceptionClass => some_variable
- There are also
(*positional_arguments)
,(default=value)
, and in Ruby 2. There is also(required_keyword_argument:, **everything_else)
in Ruby 2.1. - A special version of double splat is
(**_)
, which means you ignore all unexpected arguments. - Call a function with keyword arguments using a colon instead of equals.
foo(bar: 100)
- This also means the minimum Ruby version you should run is 2.
super
(the word) issuper()
.- Single-quoted strings are like Python's
r"raw strings"
. - "Python prevents modification of built-ins — Ruby does not."
- Only
false
andnil
are falsy. Everything else, including0
and0.0
, is truthy.[]
is truthy and is a special case you need to handle.{}
is truthy and is a special case you need to handle.''
is truthy and is a special case you need to handle. - There is no
del
, but you can set something tonil
. Referencing something that has been set tonil
never raisesNameError
, however. =~
is "matches":if mystring =~ /^\s+hello word!/
- A constant is a thing starting with upper case and they can be modified. That's right.
- The
require()
method is quite similar toload()
, but it's meant for a different purpose. You useload()
to execute code, and you userequire()
to import libraries. If youextend
a class with a module, that means you're "bringing in" the module's methods as class methods. If youinclude
a class with a module, that means you're "bringing in" the module's methods as instance methods.\ 3.times { ... }
means "do this 3 times".- If a function accepts nothing, its declaration brackets are optional.
- Modules are not classes. Modules are mixin-equivalents, whereas classes can be instantiated.
- Ruby is a lot more heavily influenced by Perl than Python is, and Perl was (at some point, possibly even trying to be interoperable with shell), which is why its syntax is both more powerful and horrible at the same time.
p foo
==puts foo.inspect
- Slicing a string from some index until the end is not
[n..]
, but[n..-1]
, for some reason. - Similarly, slicing a string from the beginning is not
[..n]
either. It is[0..n]
. - The parameter used when making a new Hash (dict) is the default value for any keys, default being
nil
.Hash.new(0)
will have all defaults being 0. - Like in python, positional/keyword arguments can have a default only if the arguments before them are also positional/keyword.
- Apparently to get the first and last elements from a range (which is not an array for some reason), you just do
array.begin
andarray.end
. That will go through all elements in the range, but what do you know. - It is tradition for Rails to muck with builtin types so that the integer
1
can have the methodday
. gem
is really nice, becausegem fetch abc
downloads the package, andgem install abc.gem
(with the.gem
) installs it.- Arrays are pretty much operable as sets if you do it.
[1,2,3,4,5] | [2,4,6]
indeed gives you[1,2,3,4,5,6]
, and[1,2,3,4,5] - [2,4,6]
indeed gives you[1,3,5]
. - Ruby 2.6 introduces endless ranges like
(1..)
that goes to Infinity, sort of useful for things you would otherwise do with a while loop but don't like that. 0
is truthy because it's just a number.""
is truthy because it's just a string. Literally everything is truthy other thannil
andfalse
. Might as bloody well makefalse
truthy because it's just a boolean.- Both
exit
andquit
exits theirb
.find
anddetect
are synonyms.map
andcollect
are the same. When you type something, ruby does what you think you mean... and that is the behaviour some people like, over explicit understanding, and "one way to do things". require 'foo'
imports literally everything from thefoo
package. This is equivalent tofrom foo import *
, where you have no way to prevent something you don't just from being imported.unless
is like,if not
, except there is a keyword for it, and it confuses everyoneunless
you were the one who wrote it.- Ruby doesn't have separate keyword arguments until 2.7.
- rbenv has fewer gotchas than rvm. So they say.
- If everything is a block, then how do you
break
in a.each do ... end
? Apparentlybreak
works in blocks, too. Not sure how it works if the block is not part of a "loop".