diff options
| author | Zachary Ferguson <zfergus2@users.noreply.github.com> | 2015-10-07 23:53:53 -0400 | 
|---|---|---|
| committer | Zachary Ferguson <zfergus2@users.noreply.github.com> | 2015-10-07 23:53:53 -0400 | 
| commit | 342488f6a8de5ab91f555a6463f5d9dc85a3079a (patch) | |
| tree | 1afa96957269a218ef2a84d9c9a2d4ab462e8fef /ruby.html.markdown | |
| parent | 4e4072f2528bdbc69cbcee72951e4c3c7644a745 (diff) | |
| parent | abd7444f9e5343f597b561a69297122142881fc8 (diff) | |
Merge remote-tracking branch 'adambard/master' into adambard/master-cn
Diffstat (limited to 'ruby.html.markdown')
| -rw-r--r-- | ruby.html.markdown | 366 | 
1 files changed, 300 insertions, 66 deletions
| diff --git a/ruby.html.markdown b/ruby.html.markdown index 38d060a3..8f23b2e6 100644 --- a/ruby.html.markdown +++ b/ruby.html.markdown @@ -4,6 +4,15 @@ filename: learnruby.rb  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"] +  - ["Dzianis Dashkevich", "https://github.com/dskecse"] +  - ["Levi Bostian", "https://github.com/levibostian"] +  - ["Rahil Momin", "https://github.com/iamrahil"] +  ---  ```ruby @@ -29,6 +38,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  # Special values are objects  nil # Nothing to see here @@ -46,8 +61,6 @@ false.class #=> FalseClass  # Inequality  1 != 1 #=> false  2 != 1 #=> true -!true  #=> false -!false #=> true  # apart from false itself, nil is the only other 'falsey' value @@ -61,15 +74,37 @@ false.class #=> FalseClass  2 <= 2 #=> true  2 >= 2 #=> true +# Logical operators +true && false #=> false +true || false #=> true +!true #=> false + +# There are alternate versions of the logical operators with much lower +# precedence. These are meant to be used as flow-control constructs to chain +# statements together until one of them returns true or false. + +# `do_something_else` only called if `do_something` succeeds. +do_something() and do_something_else() +# `log_error` only called if `do_something` fails. +do_something() or log_error() + +  # Strings are objects  'I am a string'.class #=> String  "I am a string too".class #=> String -placeholder = "use string interpolation" +placeholder = 'use string interpolation'  "I can #{placeholder} when using double quoted strings"  #=> "I can use string interpolation when using double quoted strings" +# Prefer single quoted strings to double quoted ones where possible +# Double quoted strings perform additional inner calculations + +# 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!" @@ -110,32 +145,47 @@ 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  array[0] #=> 1  array[12] #=> nil +# Like arithmetic, [var] access +# is just syntactic sugar +# for calling a method [] on an object +array.[] 0 #=> 1 +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] + +# Reverse an Array +a=[1,2,3] +a.reverse! #=> [3,2,1]  # Or with a range  array[1..3] #=> [2, 3, 4]  # Add to an array like this  array << 6 #=> [1, 2, 3, 4, 5, 6] +# Or like this +array.push(6) #=> [1, 2, 3, 4, 5, 6] + +# Check if an item exists in an array +array.include?(1) #=> true  # Hashes are Ruby's primary dictionary with keys/value pairs.  # Hashes are denoted with curly braces: -hash = {'color' => 'green', 'number' => 5} +hash = { 'color' => 'green', 'number' => 5 }  hash.keys #=> ['color', 'number'] @@ -146,28 +196,27 @@ 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} +new_hash = { defcon: 3, action: true }  new_hash.keys #=> [:defcon, :action] +# Check existence of keys and values in hash +new_hash.has_key?(:defcon) #=> true +new_hash.has_value?(3) #=> true +  # Tip: Both Arrays and Hashes are Enumerable  # They share a lot of useful methods such as each, map, count, and more  # Control structures  if true -  "if statement" +  'if statement'  elsif false - "else if, optional" +  'else if, optional'  else - "else, also optional" +  'else, also optional'  end  for counter in 1..5 @@ -179,9 +228,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}" @@ -192,6 +247,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}" @@ -207,17 +273,44 @@ grade = 'B'  case grade  when 'A' -  puts "Way to go kiddo" +  puts 'Way to go kiddo'  when 'B' -  puts "Better luck next time" +  puts 'Better luck next time'  when 'C' -  puts "You can do better" +  puts 'You can do better'  when 'D' -  puts "Scraping through" +  puts 'Scraping through'  when 'F' -  puts "You failed!" -else  -  puts "Alternative grading system, eh?" +  puts 'You failed!' +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" + +# exception handling: +begin +  # code here that might raise an exception +  raise NoMemoryError, 'You ran out of memory.' +rescue NoMemoryError => exception_variable +  puts 'NoMemoryError was raised', exception_variable +rescue RuntimeError => other_exception_variable +  puts 'RuntimeError was raised now' +else +  puts 'This runs if no exceptions were thrown at all' +ensure +  puts 'This code always runs no matter what'  end  # Functions @@ -226,7 +319,7 @@ 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 @@ -234,23 +327,23 @@ double 3 #=> 6  double double 3 #=> 12 -def sum(x,y) +def sum(x, y)    x + y  end  # Method arguments are separated by a comma  sum 3, 4 #=> 7 -sum sum(3,4), 5 #=> 12 +sum sum(3, 4), 5 #=> 12  # yield  # All methods have an implicit, optional block parameter  # it can be called with the 'yield' keyword  def surround -  puts "{" +  puts '{'    yield -  puts "}" +  puts '}'  end  surround { puts 'hello world' } @@ -260,47 +353,65 @@ surround { puts 'hello world' }  # } -# Define a class with the class keyword -class Human - -     # A class variable. It is shared by all instances of this class. -    @@species = "H. sapiens" - -    # Basic initializer -    def initialize(name, age=0) -        # Assign the argument to the "name" instance variable for the instance -        @name = name -        # If no age given, we will fall back to the default in the arguments list. -        @age = age -    end - -    # Basic setter method -    def name=(name) -        @name = name -    end - -    # Basic getter method -    def name -        @name -    end +# You can pass a block to a function +# "&" marks a reference to a passed block +def guests(&block) +  block.call 'some_argument' +end -    # 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) -       puts "#{msg}" -    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 -    def species -        @@species -    end +# Define a class with the class keyword +class Human +  # A class variable. It is shared by all instances of this class. +  @@species = 'H. sapiens' + +  # Basic initializer +  def initialize(name, age = 0) +    # Assign the argument to the "name" instance variable for the instance +    @name = name +    # If no age given, we will fall back to the default in the arguments list. +    @age = age +  end + +  # Basic setter method +  def name=(name) +    @name = name +  end + +  # Basic getter method +  def name +    @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) +    puts msg +  end + +  def species +    @@species +  end  end  # Instantiate a class -jim = Human.new("Jim Halpert") +jim = Human.new('Jim Halpert') -dwight = Human.new("Dwight K. Schrute") +dwight = Human.new('Dwight K. Schrute')  # Let's call a couple of methods  jim.species #=> "H. sapiens" @@ -311,5 +422,128 @@ dwight.species #=> "H. sapiens"  dwight.name #=> "Dwight K. Schrute"  # Call the class method -Human.say("Hi") #=> "Hi" +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 is also an object in ruby. So class can have instance variables. +# Class variable is shared among the class and all of its descendants. + +# base class +class Human +  @@foo = 0 + +  def self.foo +    @@foo +  end + +  def self.foo=(value) +    @@foo = value +  end +end + +# derived class +class Worker < Human +end + +Human.foo # 0 +Worker.foo # 0 + +Human.foo = 2 # 2 +Worker.foo # 2 + +# Class instance variable is not shared by the class's descendants. + +class Human +  @bar = 0 + +  def self.bar +    @bar +  end + +  def self.bar=(value) +    @bar = value +  end +end + +class Doctor < Human +end + +Human.bar # 0 +Doctor.bar # nil + +module ModuleExample +  def foo +    'foo' +  end +end + +# Including modules binds their methods to the class instances +# Extending modules binds their methods to the class itself + +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 are executed when including and extending a module + +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 edition](http://ruby-doc.com/docs/ProgrammingRuby/) is available online. +- [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide) - A community-driven Ruby coding style guide. | 
