Git Product home page Git Product logo

ruby_training's Introduction

Content:

  • History of Ruby
  • Comments
  • Kent Beck's rules of Simple Design:
  • Constants and vars
  • Operators and operations
  • Numbers
  • Printing
  • gets
  • if-else, unless
  • Loops
  • Case
  • Arrays
  • argv
  • Files
  • Hashes
  • Methods
  • Anonymous functions
  • Class
  • Modules
  • Symbols
  • Blocks
  • Procs

History of Ruby

Ruby was born in 1993, conceieved in a discussion between Yukihiro Matsumoto (“Matz”) and a colleague. They were discussing the possibility of an object-oriented scripting-language. Matz stated in ruby-talk:00382 that he knew Perl, but did not like it very much; that it had the smell of a “toy” language. He also discussed that he knew Python, but didn’t like it because it wasn’t a true object-oriented programming language.

Matz wanted a language perfect for his needs:

  • Syntactically Simple
  • Having Iterators and Closures
  • Exception Handling
  • Garbage Collection
  • Portable

Having looked around and not found a language suited for him, Yukihiro Matsumoto decided to create his own. After spending several months writing an interpreter, Matz finally published the first public version of Ruby (0.95) to various Japanese domestic newsgroups in December, 1995.

Ruby overview

Ruby is a dynamic, reflective, object-oriented, general-purpose programming language. It was designed and developed in the mid-1990s by Yukihiro "Matz" Matsumoto in Japan.

According to its creator, Ruby was influenced by Perl, Smalltalk, Eiffel, Ada, and Lisp.It supports multiple programming paradigms, including functional, object-oriented, and imperative. It also has a dynamic type system and automatic memory management.

Ruby has a wealth of other features, among which are the following:

  • Ruby has exception handling features, like Java or Python, to make it easy to handle errors.

  • Ruby features a true mark-and-sweep garbage collector for all Ruby objects. No need to maintain reference counts in extension libraries. As Matz says, “This is better for your health.”

  • Writing C extensions in Ruby is easier than in Perl or Python, with a very elegant API for calling Ruby from C. This includes calls for embedding Ruby in software, for use as a scripting language. A SWIG interface is also available.

  • Ruby can load extension libraries dynamically if an OS allows.

  • Ruby features OS independent threading. Thus, for all platforms on which Ruby runs, you also have multithreading, regardless of if the OS supports it or not, even on MS-DOS!

  • Ruby is highly portable: it is developed mostly on GNU/Linux, but works on many types of UNIX, Mac OS X, Windows, DOS, BeOS, OS/2, etc.

Comments

# one line comment
=begin

multi
line
comment

=end

Kent Beck's rules of Simple Design:

  • The code must first be correct (as defined by tests);
  • then it should be a clear statement of the design (what J.B.Rainsberger calls "no bad names");
  • then it should contain no duplication (of text, of ideas, or of responsibility);
  • and finally it must be the smallest code that meets all of the above.

  • It's time to stop refactoring when the code makes a reasonable stab at meeting those goals, and when any further changes would add no further benefit.

interpretator

irb --simple-prompt

Constants and vars

Vars must start with lowercase, consts must be named with an uppercase and can't change their value.

Global vars should start with $. Globals are bad.
Instance variables are preceded by a @.
Class variables are preceded by @@.

Recall that instance variables begin with an @. This isn't just a Ruby convention—it's part of the syntax! Always start your instance variables with @.

Class variables are like instance variables, but instead of belonging to an instance of a class, they belong to the class itself. Class variables always start with two @s, like so: @@files.

Global variables can be declared in two ways. The first is one that's already familiar to you: you just define the variable outside of any method or class, and voilà! It's global. If you want to make a variable global from inside a method or class, just start it with a $, like so: $matz.

variable = 1   # local
Variable = 1   # const
$variable = 1  # global

Operators and operations

= vs ==

== is greater than =
== -> checks if true = -> assigns value

dots

... operator includes a range's first num and excludes the last .. operator includes both the first and the last num in the range

PEMDAS = Parentheses Exponents Multiplication Division Addition Subtraction

conditional assignment operator

But what if we only want to assign a variable if it hasn't already been assigned? For this, we can use the conditional assignment operator: ||=.

ternary

An even more concise version of if/else is the ternary conditional expression. It's called "ternary" because it takes three arguments: a boolean, an expression to evaluate if the boolean is true, and an expression to evaluate if the boolean is false.

The syntax looks like this:

boolean ? Do this if true: Do this if false

combined comparison operator

The combined comparison operator looks like this: <=>. It returns 0 if the first operand (item to be compared) equals the second, 1 if first operand is greater than the second, and -1 if the first operand is less than the second

::

Math::PI and Circle::PI.

See that double colon we just used? That's called the scope resolution operator, which is a fancy way of saying it tells Ruby where you're looking for a specific bit of code. If we say Math::PI, Ruby knows to look inside the Math module to get that PI, not any other PI (such as the one we created in Circle).

note

Make sure to include the ! whe using some methods so that the user's string is modified in-place; otherwise, Ruby will create a copy of user_input.downcase and modify that instead.

Numbers

Int
Float
Bignum (core)
BigDecimal (stdlib)
Rational
Complex

Printing

puts

puts "String" + variable
puts string[0..4]     #prints first 5 chars
puts string.split      #every word on new line
puts string.capitalize
puts string.reverse
puts string.upcase
puts string.downcase
puts string.length
puts "This is a variable: #{variable}"
puts "\t \\t tabs."
puts "\\n goes on new line"
puts "%s stringer" % "string" #string stringer
puts "stringg".chop # removes one g
date = "6.10.2000"
puts date.split(".") # puts num on new line

print

print "Info" # same as puts, no new line entered

gets

variable = gets
name = gets.to_i     # makes it int
name = gets.chomp    # removes \n

if-else, unless

if something
	do something
elsif something
	do something
else
	do something
end
unless num > 5   # if num<5
		do something
else
		do something
end
puts "num is not 5" unless num == 5
puts "num is 5" if num == 5

Loops

While

Do is optional, always include it if the loop is in one line loop.

Normal while:

while count_while <= 100 do
	puts count_while
	count_while += 1
end

Post while:

begin
	num += 1
	puts num
end while num < 100

Until

until num > 100 do # again, do is optional
	puts num
	num += 1
end

begin.. until

begin
	sum += num
	num -= 1
end until num < 0

for loop

for i in 0..num
	puts i
end
The i in the for loop isn't in a local scope!!! ## each iterator The each iterator creates a local scope!!!
(0...n+1).each do |i|
	puts i
end

Case

case language
when "JS"
  puts "Websites!"
when "Python"
  puts "Science!"
when "Ruby"
  puts "Web apps!"
else
  puts "I don't know!"
end

# But you can fold it up like so:

case language
  when "JS" then puts "Websites!"
  when "Python" then puts "Science!"
  when "Ruby" then puts "Web apps!"
  else puts "I don't know!"
end
case degrees_unit
when  'C' then result = degrees
when  'K' then result = degrees - 273.15
when  'F' then result = (degrees-32)*(5/9)
end

Arrays

Saves references, not the elements.
The size of the array is dynamic.

array_families = ["KK","AA","SD"]
puts array_families
array_families.sort # returns a new array!!
array_families.reverse # return a new array!!
array_families.size
array_families.length
array_families.include? # returns true or false, linear search

Array mutating

numbers = [1, 2, 3]

numbers << 4
p numbers   # => [1, 2, 3, 4]

numbers.insert 0, :zero
p numbers   # => [:zero, 1, 2, 3, 4]

result = numbers.delete_at(0)
p result    # => :zero
p numbers   # => [1, 2, 3, 4]

Array stack

stack = [1, 2, 3]

stack.push 4
p stack         # => [1, 2, 3, 4]

top = stack.pop
p stack         # => [1, 2, 3]
p top           # => 4

More array methods

[1, 2, 3].join("-")        # => "1-2-3"
[1, 2, 3].permutation
[1, 2].product([3, 4])     # => [[1, 3], [1, 4], [2, 3], [2, 4]]
[[1, 2], [3, 4]].transpose # => [[1, 3], [2, 4]]
[1, 2, 3, 4].shuffle       # разбърква масива произволно

String arrays

%w(chunky bacon)     == ['chunky', 'bacon']
%w[a b c]            == ['a', 'b', 'c']
%w{cool stuff}       == ['cool', 'stuff']
%w<coffee tea water> == ['coffee', 'tea', 'water']
%w|foo bar|          == ['foo', 'bar']

iterations

primes = [2, 3, 5, 7, 11]

primes.each { |n| puts n }

primes.each do |n|
  puts n
end

sleep

sleep time

Stops the execution of the program for a certain number of seconds - time is a number in seconds.

argv

a_name = ARGV[0]
testy = ARGV[1]

ARGV is everything that is writen after running a script.
ruby main.rb argv1 argv2 ardvn where argv can be any data type

Files

file = open(filename) # default opens in read mode
file = open(filename, "w") # opens in write mode
puts file.read # prints content
file.close() # closes
file.truncate(0) # removes file text
puts file.readline # reads first line

ASCII

letter = 'a'.ord   # gives numeric ASCII value of a
number.chr         # gives the character from an ASCII number

Hashes

indexing

numbers = {:one => :edno, :two => :dve}

numbers[:one]     # => :edno
numbers[:three]   # => nil

numbers[:three] = :tri

numbers[:three]                     # => :tri
numbers.fetch(:four, :keine_ahnung) # => :keine_ahnung

Methods

numbers = {1 => 2, 3 => 4}

puts numbers.size             # => 2
puts numbers.invert           # => {2=>1, 4=>3}
puts numbers.merge({5 => 6})  # => {1=>2, 3=>4, 5=>6}

after 1.9

The second line is preffered after ruby v.1.9

{:one => 1, :two => 2}
{one: 1, two: 2}

The hash syntax you've seen so far (with the => symbol between keys and values) is sometimes nicknamed the hash rocket style.
However, the hash syntax has changed in Ruby 1.9. The new syntax is easier to type than the old hash rocket syntax:

new_hash = { one: 1,
  two: 2,
  three: 3,
}

The two changes are:

  • You put the colon at the end of the symbol, not at the beginning;
  • You don't need the hash rocket anymore.

It's important to note that even though these keys have colons at the end instead of the beginning, they're still symbols!
puts new_hash
# ==> {:one=>1, :two=>2, :three=>3}
## default hash value
my_hash = Hash.new("Trady Blix")

.object_id

The .object_id method gets the ID of an object—it's how Ruby knows whether two objects are the exact same object.

.each_key, .each_value

Ruby includes two hash methods, .each_key and .each_value, that do exactly what you'd expect:

my_hash = { one: 1, two: 2, three: 3 }

my_hash.each_key { |k| print k, " " }
# ==> one two three

my_hash.each_value { |v| print v, " " }
# ==> 1 2 3

methods

Ruby's methods will return the result of the last evaluated expression.

? vs !

When using a method we can use either ? or !. ? is obviously a question. It "asks" different things like defined? asks if a variable is defined.

i=0
if !defined? i #if i is not defined it becomes equal to 2
    i=2
end
puts i #prints 0 because i is already defined

When using a method, it performs itself but it doesn't remain after its end, e.g.:

name = 'peter'
puts name.capitalize #prints Peter
puts name #prints peter

If we want to keep the changes to the word, we should add a !, for ex.:

name = 'peter'
puts name.capitalize! #prints Peter and makes name ewual to it
puts name #prints Peter

Defining methods

def method_name(parametres)
	do something
end

method_name(var)

Methods with variability in parametres count

	def name(*names)
		# we can get 1,2,3 or more names
	end

N.B! There can be only one parametre with variable count!!!

default method parametres value

def name(name = 'default value')
	do sth
end

Methods with skiping parametres

def name(name = {})
	do sth
end

Predicati (methods)

A name of the method can end in ? if it return true or false. (by convention)

Anonymous functions

lambda

Defined with keyword lambda. Almost identical to the normal methods. They are of type proc but with a special flag.

pow = lambda {|a,b| a**b} # definition
# calling
pow.call 2,3
pow[2,3]
pow.(2,3)

proc

double = Proc.new {|x| x * 2}
double.call(2)
double[2]
double.(2)

Differences between lambda and procs:

  • In proc -> ArgumentError
  • return@ lambda -> return outside the body of the lambda
  • return@proc -> returns putside of the body of the method, in whic the proc is called

Class

A class is just a way of organizing and producing objects with similar attributes and methods.

A basic class consists only of the class keyword and the name of the class.
Check it out:

class NewClass
  # Class magic here
end
class Bacon
  def chunky?
    'yes, of course!'
  end
end

bacon = Bacon.new
bacon.chunky?      # => "yes, of course!

initialize

Instance variables are prefixed with @.If we call #methods,we will receive an array with symbols with the names of the methods.

You can think of initialize as the function that "boots up" each object the class creates.

class Person
    def initialize

    end

end
class Car
  def initialize(make, model)
    @make = make
    @model = model
  end
end

kitt = Car.new("Pontiac", "Trans Am")

.new

We can create an instance of a class just by calling .new on the class name, like so:

me = Person.new("Eric")

Inheritance

Inheritance is the process by which one class takes on the attributes and methods of another, and it's used to express an is-a relationship. For example, a cartoon fox is a cartoon mammal, so a CartoonFox class could inherit from a CartoonMammal class. However, a Wizard is not an Elf , so it shouldn't inherit from the Elf class (even if they have a lot of magical attributes and methods in common). Instead, both Wizard and Elf could ultimately inherit from the same MagicalBeing class.

In Ruby, inheritance works like this:

class DerivedClass < BaseClass
  # Some stuff!
end

where the derived class is the new class you're making and the base class is the class from which that new class inherits. You can read "<" as "inherits from."

Override!

Sometimes you'll want one class that inherits from another to not only take on the methods and attributes of its parent, but to override one or more of them.

For instance, you might have an Email class that inherits from Message. Both classes might have a send method that sends them, but the e-mail version may have to identify valid e-mail addresses and use a bunch of e-mail protocols that Message knows nothing about. Rather than add a send_email method to your derived class and inherit a send method you'll never use, you can instead just explicitly create a send method in the Email class and have it do all the email-sending work.

This new version of send will override (that is, replace) the inherited version for any object that is an instance of Email.

super

On the flip side, sometimes you'll be working with a derived class (or subclass) and realize that you've overwritten a method or attribute defined in that class' base class (also called a parent or superclass) that you actually need. Have no fear! You can directly access the attributes or methods of a superclass with Ruby's built-in super keyword.

The syntax looks like this:

class DerivedClass < Base
  def some_method
    super(optional args)
      # Some stuff
    end
  end
end

When you call super from inside a method, that tells Ruby to look in the superclass of the current class and find a method with the same name as the one from which super is called. If it finds it, Ruby will use the superclass' version of the method.

multiple inheritance

Any given Ruby class can have only one superclass. Some languages allow a class to have more than one parent, which is a model called multiple inheritance. This can get really ugly really fast, which is why Ruby disallows it.

However, there are instances where you want to incorporate data or behavior from several classes into a single class, and Ruby allows this through the use of mixins. We'll learn about mixins in a later lesson! For now, we'll demonstrate what happens if you try to do multiple inheritance in Ruby.

Modules

You can think of a module as a toolbox that contains a set methods and constants. There are lots and lots of Ruby tools you might want to use, but it would clutter the interpreter to keep them around all the time. For that reason, we keep a bunch of them in modules and only pull in those module toolboxes when we need the constants and methods inside!

You can think of modules as being very much like classes, only modules can't create instances and can't have subclasses. They're just used to store things!

module UselessStuff
  def almost_pi
    3.1415
  end
end

class Something
  include UselessStuff
end

Something.new.almost_pi # => 3.1415

You can pull in pre-existing modules, but you can also make your own. Modules are super easy to make! You just use the module keyword, like so:

module ModuleName
  # Bits 'n pieces
end

Like class names, module names are written in CapitalizedCamelCase , rather than lowercasewithunderscores.

It doesn't make sense to include variables in modules, since variables (by definition) change (or vary). Constants, however, are supposed to always stay the same, so including helpful constants in modules is a great idea.

Ruby doesn't make you keep the same value for a constant once it's initialized, but it will warn you if you try to change it. Ruby constants are written in ALL_CAPS and are separated with underscores if there's more than one word.

An example of a Ruby constant is PI, which lives in the Math module and is approximately equal to 3.141592653589793.

namespacing

One of the main purposes of modules is to separate methods and constants into named spaces. This is called (conveniently enough) namespacing, and it's how Ruby doesn't confuse Math::PI and Circle::PI.

See that double colon we just used? That's called the scope resolution operator, which is a fancy way of saying it tells Ruby where you're looking for a specific bit of code. If we say Math::PI, Ruby knows to look inside the Math module to get that PI, not any other PI (such as the one we created in Circle).

require

Some modules, like Math, are already present in the interpreter. Others need to be explicitly brought in, however, and we can do this using require. We can do this simply by typing

require 'module'

include

We can do more than just require a module, however. We can also include it!

Any class that includes a certain module can use those module's methods!

A nice effect of this is that you no longer have to prepend your constants and methods with the module name. Since everything has been pulled in, you can simply write PI instead of Math::PI.

class Angle
  include Math
  attr_accessor :radians

  def initialize(radians)
    @radians = radians
  end

  def cosine
    cos(@radians)
  end
end

acute = Angle.new(1)
acute.cosine

mixins

What we did in the last exercise might not have seemed strange to you, but think about it: we mixed together the behaviors of a class and a module!

When a module is used to mix additional behavior and information into a class, it's called a mixin. Mixins allow us to customize a class without having to rewrite code!

module Action
  def jump
    @distance = rand(4) + 2
    puts "I jumped forward #{@distance} feet!"
  end
end

class Rabbit
  include Action
  attr_reader :name
  def initialize(name)
    @name = name
  end
end

class Cricket
  include Action
  attr_reader :name
  def initialize(name)
    @name = name
  end
end

peter = Rabbit.new("Peter")
jiminy = Cricket.new("Jiminy")

peter.jump
jiminy.jump

extend

Whereas include mixes a module's methods in at the instance level (allowing instances of a particular class to use the methods), the extend keyword mixes a module's methods at the class level. This means that class itself can use the methods, as opposed to instances of the class.

all and any

[1, 2, 3, nil].all?     # => false
[1, 2, 3, :nil].all?    # => true
[1, 2, 3, false].any?   # => true

Symbols

Symbols always start with a colon (:). They must be valid Ruby variable names, so the first character after the colon has to be a letter or underscore (_); after that, any combination of letters, numbers, and underscores is allowed.

Make sure you don't put any spaces in your symbol name—if you do, Ruby will get confused.

my_first_symbol = :a

converting symbols <-> strings

Converting between strings and symbols is a snap.

:sasquatch.to_s
# ==> "sasquatch"

"sasquatch".to_sym
# ==> :sasquatch

Besides using .to_sym, you can also use .intern. This will internalize the string into a symbol and works just like .to_sym.

upto, downto

If we know the range of numbers we'd like to include, we can use .upto and .downto. This is a much more Rubyist solution than trying to use a for loop that stops when a counter variable hits a certain value.

We might use .upto to print out a specific range of values:

95.upto(100) { |num| print num, " " }
# Prints 95 96 97 98 99 100

and we can use .downto to do the same thing with descending values.

Blocks

A Ruby block is just a bit of code that can be executed. Block syntax uses either do..end or curly braces ({}), like so:

[1, 2, 3].each do |num|
  puts num
end
# ==> Prints 1, 2, 3 on separate lines

[1, 2, 3].each { |num| puts num }
# ==> Prints 1, 2, 3 on separate lines

Blocks can be combined with methods like .each and .times to execute an instruction for each element in a collection (like a hash or array). Blocks are not objects, and this is one of the very few exceptions to the "everything is an object" rule in Ruby.

Because of this, blocks can't be saved to variables and don't have all the powers and abilities of a real object. For that, we'll need... procs!

Procs

You can think of a proc as a "saved" block: just like you can give a bit of code a name and turn it into a method, you can name a block and turn it into a proc. Procs are great for keeping your code DRY, which stands for Don't Repeat Yourself. With blocks, you have to write your code out each time you need it; with a proc, you write your code once and can use it many times!

multiples_of_3 = Proc.new do |n|
  n % 3 == 0
end

(1..100).to_a.select(&multiples_of_3)

Procs are easy to define! You just call Proc.new and pass in the block you want to save. Here's how we'd create a proc called cube that cubes a number (raises it to the third power):

cube = Proc.new { |x| x ** 3 }
# We can then pass the proc to a method that would otherwise take a block, and we don't have to rewrite the block over and over!

[1, 2, 3].collect!(&cube)
# ==> [1, 8, 27]
[4, 5, 6].map!(&cube)
# ==> [64, 125, 216]

(The .collect! and .map! methods do the exact same thing.)

The & is used to convert the cube proc into a block (since .collect! and .map! normally take a block). We'll do this any time we pass a proc to a method that expects a block.

Why bother saving our blocks as procs? There are two main advantages:

Procs are full-fledged objects, so they have all the powers and abilities of objects. (Blocks do not.) Unlike blocks, procs can be called over and over without rewriting them. This prevents you from having to retype the contents of your block every time you need to execute a particular bit of code.

ruby_training's People

Contributors

karinakozarova avatar

Watchers

 avatar

ruby_training's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.