diff options
Diffstat (limited to 'ruby.html.markdown')
-rw-r--r-- | ruby.html.markdown | 168 |
1 files changed, 151 insertions, 17 deletions
diff --git a/ruby.html.markdown b/ruby.html.markdown index 861a94ad..962853a2 100644 --- a/ruby.html.markdown +++ b/ruby.html.markdown @@ -5,6 +5,11 @@ contributors: - ["David Underwood", "http://theflyingdeveloper.com"] - ["Joel Walden", "http://joelwalden.net"] - ["Luke Holder", "http://twitter.com/lukeholder"] + - ["Tristan Hume", "http://thume.ca/"] + - ["Nick LaMuro", "https://github.com/NickLaMuro"] + - ["Marcos Brizeno", "http://www.about.me/marcosbrizeno"] + - ["Ariel Krakowski", "http://www.learneroo.com"] + --- ```ruby @@ -30,11 +35,12 @@ You shouldn't either 8 - 1 #=> 7 10 * 2 #=> 20 35 / 5 #=> 7 +2 ** 5 #=> 32 # Arithmetic is just syntactic sugar # for calling a method on an object 1.+(3) #=> 4 -10.* 5 #=> 50 +10.* 5 #=> 50 # Special values are objects nil # Nothing to see here @@ -76,6 +82,10 @@ placeholder = "use string interpolation" "I can #{placeholder} when using double quoted strings" #=> "I can use string interpolation when using double quoted strings" +# Combine strings, but not with numbers +"hello " + "world" #=> "hello world" +"hello " + 3 #=> TypeError: can't convert Fixnum into String +"hello " + 3.to_s #=> "hello 3" # print to the output puts "I'm printing!" @@ -116,11 +126,11 @@ status == :approved #=> false # Arrays # This is an array -[1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5] +array = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5] # Arrays can contain different types of items -array = [1, "hello", false] #=> => [1, "hello", false] +[1, "hello", false] #=> [1, "hello", false] # Arrays can be indexed # From the front @@ -136,8 +146,8 @@ array.[] 12 #=> nil # From the end array[-1] #=> 5 -# With a start and end index -array[2, 4] #=> [3, 4, 5] +# With a start index and length +array[2, 3] #=> [3, 4, 5] # Or with a range array[1..3] #=> [2, 3, 4] @@ -158,11 +168,6 @@ hash['number'] #=> 5 # Asking a hash for a key that doesn't exist returns nil: hash['nothing here'] #=> nil -# Iterate over hashes with the #each method: -hash.each do |k, v| - puts "#{k} is #{v}" -end - # Since Ruby 1.9, there's a special syntax when using symbols as keys: new_hash = { defcon: 3, action: true} @@ -177,9 +182,9 @@ new_hash.keys #=> [:defcon, :action] if true "if statement" elsif false - "else if, optional" + "else if, optional" else - "else, also optional" + "else, also optional" end for counter in 1..5 @@ -191,9 +196,15 @@ end #=> iteration 4 #=> iteration 5 -# HOWEVER -# No-one uses for loops -# Use `each` instead, like this: +# HOWEVER, No-one uses for loops. +# Instead you should use the "each" method and pass it a block. +# A block is a bunch of code that you can pass to a method like "each". +# It is analogous to lambdas, anonymous functions or closures in other +# programming languages. +# +# The "each" method of a range runs the block once for each element of the range. +# The block is passed a counter as a parameter. +# Calling the "each" method with a block looks like this: (1..5).each do |counter| puts "iteration #{counter}" @@ -204,6 +215,17 @@ end #=> iteration 4 #=> iteration 5 +# You can also surround blocks in curly brackets: +(1..5).each {|counter| puts "iteration #{counter}"} + +# The contents of data structures can also be iterated using each. +array.each do |element| + puts "#{element} is part of the array" +end +hash.each do |key, value| + puts "#{key} is #{value}" +end + counter = 1 while counter <= 5 do puts "iteration #{counter}" @@ -228,17 +250,33 @@ when 'D' puts "Scraping through" when 'F' puts "You failed!" -else +else puts "Alternative grading system, eh?" end +#=> "Better luck next time" + +# cases can also use ranges +grade = 82 +case grade + when 90..100 + puts "Hooray!" + when 80...90 + puts "OK job" + else + puts "You failed!" +end + +#=> "OK job" + + # Functions def double(x) x * 2 end -# Functions (and all blocks) implcitly return the value of the last statement +# Functions (and all blocks) implicitly return the value of the last statement double(2) #=> 4 # Parentheses are optional where the result is unambiguous @@ -272,6 +310,18 @@ surround { puts 'hello world' } # } +# You can pass a block to a function +# "&" marks a reference to a passed block +def guests(&block) + block.call "some_argument" +end + +# You can pass a list of arguments, which will be converted into an array +# That's what splat operator ("*") is for +def guests(*array) + array.each { |guest| puts "#{guest}" } +end + # Define a class with the class keyword class Human @@ -296,6 +346,13 @@ class Human @name end + # The above functionality can be encapsulated using the attr_accessor method as follows + attr_accessor :name + + # Getter/setter methods can also be created individually like this + attr_reader :name + attr_writer :name + # A class method uses self to distinguish from instance methods. # It can only be called on the class, not an instance. def self.say(msg) @@ -325,6 +382,23 @@ dwight.name #=> "Dwight K. Schrute" # Call the class method Human.say("Hi") #=> "Hi" +# Variable's scopes are defined by the way we name them. +# Variables that start with $ have global scope +$var = "I'm a global var" +defined? $var #=> "global-variable" + +# Variables that start with @ have instance scope +@var = "I'm an instance var" +defined? @var #=> "instance-variable" + +# Variables that start with @@ have class scope +@@var = "I'm a class var" +defined? @@var #=> "class variable" + +# Variables that start with a capital letter are constants +Var = "I'm a constant" +defined? Var #=> "constant" + # Class also is object in ruby. So class can have instance variables. # Class variable is shared among the class and all of its descendants. @@ -371,4 +445,64 @@ end Human.bar # 0 Doctor.bar # nil +module ModuleExample + def foo + 'foo' + end +end + +# Including modules binds the methods to the object instance +# Extending modules binds the methods to the class instance + +class Person + include ModuleExample +end + +class Book + extend ModuleExample +end + +Person.foo # => NoMethodError: undefined method `foo' for Person:Class +Person.new.foo # => 'foo' +Book.foo # => 'foo' +Book.new.foo # => NoMethodError: undefined method `foo' + +# Callbacks when including and extending a module are executed + +module ConcernExample + def self.included(base) + base.extend(ClassMethods) + base.send(:include, InstanceMethods) + end + + module ClassMethods + def bar + 'bar' + end + end + + module InstanceMethods + def qux + 'qux' + end + end +end + +class Something + include ConcernExample +end + +Something.bar # => 'bar' +Something.qux # => NoMethodError: undefined method `qux' +Something.new.bar # => NoMethodError: undefined method `bar' +Something.new.qux # => 'qux' ``` + +## Additional resources + +- [Learn Ruby by Example with Challenges](http://www.learneroo.com/modules/61/nodes/338) - A variant of this reference with in-browser challenges. +- [Official Documentation](http://www.ruby-doc.org/core-2.1.1/) +- [Ruby from other languages](https://www.ruby-lang.org/en/documentation/ruby-from-other-languages/) +- [Programming Ruby](http://www.amazon.com/Programming-Ruby-1-9-2-0-Programmers/dp/1937785491/) - An older [free addition](http://ruby-doc.com/docs/ProgrammingRuby/) is available online. + + |