{"id":22019335,"url":"https://github.com/karinakozarova/ruby_training","last_synced_at":"2025-08-17T18:36:41.775Z","repository":{"id":101414771,"uuid":"95889591","full_name":"karinakozarova/Ruby_training","owner":"karinakozarova","description":null,"archived":false,"fork":false,"pushed_at":"2017-09-20T16:10:27.000Z","size":241,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-03-23T09:48:56.128Z","etag":null,"topics":["exercises","ruby","school-stuff","training"],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/karinakozarova.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-06-30T13:11:26.000Z","updated_at":"2023-01-06T14:35:37.000Z","dependencies_parsed_at":null,"dependency_job_id":"bf87f2c5-b726-498a-88c4-2f32d25fc20b","html_url":"https://github.com/karinakozarova/Ruby_training","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/karinakozarova/Ruby_training","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karinakozarova%2FRuby_training","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karinakozarova%2FRuby_training/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karinakozarova%2FRuby_training/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karinakozarova%2FRuby_training/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/karinakozarova","download_url":"https://codeload.github.com/karinakozarova/Ruby_training/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karinakozarova%2FRuby_training/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265277637,"owners_count":23739426,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["exercises","ruby","school-stuff","training"],"created_at":"2024-11-30T05:16:43.310Z","updated_at":"2025-07-14T10:08:03.100Z","avatar_url":"https://github.com/karinakozarova.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":" # Content:\n \u003cul\u003e\n\u003cli\u003e History of Ruby\u003c/li\u003e\n\u003cli\u003e Comments\u003c/li\u003e\n\u003cli\u003e Kent Beck's rules of Simple Design: \u003c/li\u003e\n\u003cli\u003e Constants and vars \u003c/li\u003e\n\u003cli\u003e Operators and operations \u003c/li\u003e\n\u003cli\u003e Numbers\u003c/li\u003e\n\u003cli\u003e Printing\u003c/li\u003e\n\u003cli\u003e gets\u003c/li\u003e\n\u003cli\u003e if-else, unless\u003c/li\u003e\n\u003cli\u003e Loops\u003c/li\u003e\n\u003cli\u003e Case\u003c/li\u003e\n\u003cli\u003e Arrays\u003c/li\u003e\n\u003cli\u003e argv\u003c/li\u003e\n\u003cli\u003e Files\u003c/li\u003e\n\u003cli\u003e Hashes\u003c/li\u003e\n\u003cli\u003e Methods\u003c/li\u003e\n\u003cli\u003e Anonymous functions\u003c/li\u003e\n\u003cli\u003e Class\u003c/li\u003e\n\u003cli\u003e Modules\u003c/li\u003e\n\u003cli\u003e Symbols\u003c/li\u003e\n\u003cli\u003e Blocks\u003c/li\u003e\n\u003cli\u003e Procs\u003c/li\u003e\n\u003c/ul\u003e\n\n# History of Ruby\n\nRuby 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. \u003cbr\u003e\n\nMatz wanted a language perfect for his needs: \u003cbr\u003e\n\u003cul\u003e\n\u003cli\u003e Syntactically Simple  \u003c/li\u003e\n\u003cli\u003e Having Iterators and Closures \u003c/li\u003e\n\u003cli\u003e Exception Handling \u003c/li\u003e\n\u003cli\u003e Garbage Collection \u003c/li\u003e\n\u003cli\u003e Portable \u003c/li\u003e\n\u003c/ul\u003e \u003cbr\u003e\nHaving 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. \u003cbr\u003e\n\n## Ruby overview\nRuby 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. \u003cbr\u003e\n\nAccording 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. \u003cbr\u003e\n\nRuby has a wealth of other features, among which are the following:\n\n+ Ruby has exception handling features, like Java or Python, to make it easy to handle errors.\n\n+ 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.”\n\n+ 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.\n\n+ Ruby can load extension libraries dynamically if an OS allows.\n\n+ 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!\n\n+ 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.\n\n\n# Comments\n```` ruby\n# one line comment\n=begin\n\nmulti\nline\ncomment\n\n=end\n\n````\n\n# Kent Beck's rules of Simple Design:\n\u003cul\u003e\n\u003cli\u003eThe code must first be correct (as defined by tests); \u003c/li\u003e \n\u003cli\u003ethen it should be a clear statement of the design (what J.B.Rainsberger calls \"no bad names\"); \u003c/li\u003e \n\u003cli\u003ethen it should contain no duplication (of text, of ideas, or of responsibility);\u003c/li\u003e \n\u003cli\u003eand finally it must be the smallest code that meets all of the above.\u003c/li\u003e \n\u003cbr\u003e\nIt'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.\n\u003c/li\u003e\n\u003c/ul\u003e\n\n# interpretator\n\tirb --simple-prompt\n\n# Constants and vars\nVars must start with lowercase, consts must be named with an uppercase and can't change their value.\n\nGlobal vars should start with $. __Globals are bad.__ \u003cbr\u003e\nInstance variables are preceded by a @.\u003cbr\u003e\nClass variables are preceded by @@.\u003cbr\u003e\n\n\u003cblockquote\u003e\nRecall 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 @.\n\nClass 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.\n\nGlobal 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.\n\n\u003c/blockquote\u003e\n\n````ruby\nvariable = 1   # local\nVariable = 1   # const\n$variable = 1  # global\n````\n\n# Operators and operations\n## = vs ==\n== is greater than =\t\u003cbr\u003e\n== -\u003e checks if true\n= -\u003e assigns value\n\n## dots\n... operator includes a range's first num and excludes the last\n.. operator includes both the first and the last num in the range\n\u003cblockquote\u003e\nPEMDAS =  Parentheses Exponents Multiplication Division Addition Subtraction\n\u003c/blockquote\u003e\n\n## conditional assignment operator\nBut 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: ||=.\n\n## ternary\nAn 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.\n\nThe syntax looks like this:\n\nboolean ? Do this if true: Do this if false\n## combined comparison operator\nThe combined comparison operator looks like this: \u003c=\u003e. 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\n\n# ::\nMath::PI and Circle::PI.\n\nSee 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).\n\n\n##  note\nMake 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.\n\n\n# Numbers\nInt \u003cbr\u003e\nFloat \u003cbr\u003e\nBignum (core) \u003cbr\u003e\nBigDecimal (stdlib) \u003cbr\u003e\nRational \u003cbr\u003e\nComplex \u003cbr\u003e\n\n# Printing\n\n## puts\n```` ruby\nputs \"String\" + variable\nputs string[0..4]     #prints first 5 chars\nputs string.split      #every word on new line\nputs string.capitalize\nputs string.reverse\nputs string.upcase\nputs string.downcase\nputs string.length\nputs \"This is a variable: #{variable}\"\nputs \"\\t \\\\t tabs.\"\nputs \"\\\\n goes on new line\"\nputs \"%s stringer\" % \"string\" #string stringer\nputs \"stringg\".chop # removes one g\n\n````\n\n````ruby\ndate = \"6.10.2000\"\nputs date.split(\".\") # puts num on new line\n````\n\n## print\n```` ruby\nprint \"Info\" # same as puts, no new line entered\n````\n# gets\n\n```` ruby\nvariable = gets\nname = gets.to_i     # makes it int\nname = gets.chomp    # removes \\n\n\n````\n\n# if-else, unless\n```` ruby\nif something\n\tdo something\nelsif something\n\tdo something\nelse\n\tdo something\nend\n\n````\n\n```` ruby\n\nunless num \u003e 5   # if num\u003c5\n\t\tdo something\nelse\n\t\tdo something\nend\n````\n\n````ruby\nputs \"num is not 5\" unless num == 5\nputs \"num is 5\" if num == 5\n````\n\n# Loops\n\n## While\nDo is optional, always include it if the loop is in one line loop. \u003cbr\u003e\n### Normal while:\n```` ruby\nwhile count_while \u003c= 100 do\n\tputs count_while\n\tcount_while += 1\nend\n````\n### Post while:\n```` ruby\nbegin\n\tnum += 1\n\tputs num\nend while num \u003c 100\n````\n## Until\n```` ruby\nuntil num \u003e 100 do # again, do is optional\n\tputs num\n\tnum += 1\nend\n````\n\n# begin.. until\n```` ruby\nbegin\n\tsum += num\n\tnum -= 1\nend until num \u003c 0\n````\n\n## for loop\n\n```` ruby\nfor i in 0..num\n\tputs i\nend\n````\n\n\u003cb\u003e\nThe i in the for loop isn't in a local scope!!!\n\u003c/b\u003e\n## each iterator\nThe each iterator creates a local scope!!!\n\n````ruby\n(0...n+1).each do |i|\n\tputs i\nend\n````\n\n# Case\n\n````ruby\ncase language\nwhen \"JS\"\n  puts \"Websites!\"\nwhen \"Python\"\n  puts \"Science!\"\nwhen \"Ruby\"\n  puts \"Web apps!\"\nelse\n  puts \"I don't know!\"\nend\n\n# But you can fold it up like so:\n\ncase language\n  when \"JS\" then puts \"Websites!\"\n  when \"Python\" then puts \"Science!\"\n  when \"Ruby\" then puts \"Web apps!\"\n  else puts \"I don't know!\"\nend\n````\n````ruby\ncase degrees_unit\nwhen  'C' then result = degrees\nwhen  'K' then result = degrees - 273.15\nwhen  'F' then result = (degrees-32)*(5/9)\nend\n````\n\n# Arrays\n\nSaves references, not the elements. \u003cbr\u003e\n__The size of the array is dynamic.__ \u003cbr\u003e\n\n```` ruby\narray_families = [\"KK\",\"AA\",\"SD\"]\nputs array_families\narray_families.sort # returns a new array!!\narray_families.reverse # return a new array!!\narray_families.size\narray_families.length\narray_families.include? # returns true or false, linear search\n````\n## Array mutating\n````ruby\nnumbers = [1, 2, 3]\n\nnumbers \u003c\u003c 4\np numbers   # =\u003e [1, 2, 3, 4]\n\nnumbers.insert 0, :zero\np numbers   # =\u003e [:zero, 1, 2, 3, 4]\n\nresult = numbers.delete_at(0)\np result    # =\u003e :zero\np numbers   # =\u003e [1, 2, 3, 4]\n````\n## Array stack\n````ruby\nstack = [1, 2, 3]\n\nstack.push 4\np stack         # =\u003e [1, 2, 3, 4]\n\ntop = stack.pop\np stack         # =\u003e [1, 2, 3]\np top           # =\u003e 4\n````\n\n## More array methods\n````ruby\n[1, 2, 3].join(\"-\")        # =\u003e \"1-2-3\"\n[1, 2, 3].permutation\n[1, 2].product([3, 4])     # =\u003e [[1, 3], [1, 4], [2, 3], [2, 4]]\n[[1, 2], [3, 4]].transpose # =\u003e [[1, 3], [2, 4]]\n[1, 2, 3, 4].shuffle       # разбърква масива произволно\n````\n## String arrays\n\n````ruby\n%w(chunky bacon)     == ['chunky', 'bacon']\n%w[a b c]            == ['a', 'b', 'c']\n%w{cool stuff}       == ['cool', 'stuff']\n%w\u003ccoffee tea water\u003e == ['coffee', 'tea', 'water']\n%w|foo bar|          == ['foo', 'bar']\n````\n\n## iterations\n````ruby\nprimes = [2, 3, 5, 7, 11]\n\nprimes.each { |n| puts n }\n\nprimes.each do |n|\n  puts n\nend\n````\n\n# sleep\n```` ruby\nsleep time\n````\nStops the execution of the program for a certain number of seconds - time is a number in seconds.\n\n# argv\n\n```` ruby\na_name = ARGV[0]\ntesty = ARGV[1]\n````\nARGV is everything that is writen after running a script. \u003cbr\u003e\n\truby main.rb argv1 argv2 ardvn\nwhere argv can be any data type\n\n# Files\n````ruby\nfile = open(filename) # default opens in read mode\nfile = open(filename, \"w\") # opens in write mode\nputs file.read # prints content\nfile.close() # closes\nfile.truncate(0) # removes file text\nputs file.readline # reads first line\n````\n\n# ASCII\n\n```` ruby\nletter = 'a'.ord   # gives numeric ASCII value of a\nnumber.chr         # gives the character from an ASCII number\n````\n\n# Hashes\n\n## indexing\n````ruby\nnumbers = {:one =\u003e :edno, :two =\u003e :dve}\n\nnumbers[:one]     # =\u003e :edno\nnumbers[:three]   # =\u003e nil\n\nnumbers[:three] = :tri\n\nnumbers[:three]                     # =\u003e :tri\nnumbers.fetch(:four, :keine_ahnung) # =\u003e :keine_ahnung\n````\n\n## Methods\n````ruby\nnumbers = {1 =\u003e 2, 3 =\u003e 4}\n\nputs numbers.size             # =\u003e 2\nputs numbers.invert           # =\u003e {2=\u003e1, 4=\u003e3}\nputs numbers.merge({5 =\u003e 6})  # =\u003e {1=\u003e2, 3=\u003e4, 5=\u003e6}\n````\n\n## after 1.9\n\nThe second line is preffered after ruby v.1.9\n````ruby\n{:one =\u003e 1, :two =\u003e 2}\n{one: 1, two: 2}\n````\nThe hash syntax you've seen so far (with the =\u003e symbol between keys and values) is sometimes nicknamed __the hash rocket style.__ \u003cbr\u003e\nHowever, the hash syntax has changed in Ruby 1.9. The new syntax is easier to type than the old hash rocket syntax:\n\n````ruby\nnew_hash = { one: 1,\n  two: 2,\n  three: 3,\n}\n````\n#### The two changes are:\n\u003cul\u003e\n\u003cli\u003eYou put the colon at the end of the symbol, not at the beginning; \u003c/li\u003e\n\u003cli\u003eYou don't need the hash rocket anymore. \u003c/li\u003e \u003c/ul\u003e \u003cbr\u003e\nIt's important to note that even though these keys have colons at the end instead of the beginning, they're still symbols!\n\n````ruby\nputs new_hash\n# ==\u003e {:one=\u003e1, :two=\u003e2, :three=\u003e3}\n## default hash value\nmy_hash = Hash.new(\"Trady Blix\")\n````\n## .object_id\nThe .object_id method gets the ID of an object—it's how Ruby knows whether two objects are the exact same object.\n## .each_key, .each_value\n\nRuby includes two hash methods, .each_key and .each_value, that do exactly what you'd expect:\n````ruby\nmy_hash = { one: 1, two: 2, three: 3 }\n\nmy_hash.each_key { |k| print k, \" \" }\n# ==\u003e one two three\n\nmy_hash.each_value { |v| print v, \" \" }\n# ==\u003e 1 2 3\n````\n\n# methods\nRuby's methods will return the result of the last evaluated expression.\n\n\n## ? vs !\nWhen using a method we can use either **?** or **!**. **?** is obviously a question. It \"asks\" different things like __*defined?*__ asks if a variable is defined.\n\n```ruby\ni=0\nif !defined? i #if i is not defined it becomes equal to 2\n    i=2\nend\nputs i #prints 0 because i is already defined\n```\nWhen using a method, it performs itself but it doesn't remain after its end, e.g.:\n```ruby\nname = 'peter'\nputs name.capitalize #prints Peter\nputs name #prints peter\n```\n\nIf we want to keep the changes to the word, we should add a **!**, for ex.:\n```ruby\nname = 'peter'\nputs name.capitalize! #prints Peter and makes name ewual to it\nputs name #prints Peter\n```\n\n## Defining methods\n````ruby\ndef method_name(parametres)\n\tdo something\nend\n\nmethod_name(var)\n````\n\n## Methods with variability in parametres count\n````ruby\n\tdef name(*names)\n\t\t# we can get 1,2,3 or more names\n\tend\n````\n__N.B! There can be only one parametre with variable count!!!__\n\n## default method parametres value\n````ruby\ndef name(name = 'default value')\n\tdo sth\nend\n````\n## Methods with skiping parametres\n````ruby\ndef name(name = {})\n\tdo sth\nend\n````\n\n## Predicati (methods)\nA name of the method can end in ? if it return true or false. (by convention)\n\n## Anonymous functions\n### lambda\nDefined with keyword lambda. Almost identical to the normal methods. They are of type proc but with a special flag.\n````ruby\npow = lambda {|a,b| a**b} # definition\n# calling\npow.call 2,3\npow[2,3]\npow.(2,3)\n````\n### proc\n````ruby\ndouble = Proc.new {|x| x * 2}\ndouble.call(2)\ndouble[2]\ndouble.(2)\n````\n#### Differences between lambda and procs:\n\u003cul\u003e\n\u003cli\u003e In proc -\u003e ArgumentError \u003cbr\u003e \u003c/li\u003e\n\u003cli\u003e return@ lambda -\u003e return outside the body of the lambda \u003cbr\u003e \u003c/li\u003e\n\u003cli\u003ereturn@proc -\u003e returns putside of the body of the method, in whic the proc is called \u003c/li\u003e\n\u003c/ul\u003e\n\n# Class\nA class is just a way of organizing and producing objects with similar attributes and methods. \u003cbr\u003e\n\nA basic class consists only of the class keyword and the name of the class.\n\u003cbr\u003e\nCheck it out:\n````ruby\nclass NewClass\n  # Class magic here\nend\n````\n\n````ruby\nclass Bacon\n  def chunky?\n    'yes, of course!'\n  end\nend\n\nbacon = Bacon.new\nbacon.chunky?      # =\u003e \"yes, of course!\n````\n## initialize\nInstance variables are prefixed with @.If we call #methods,we will receive an array with symbols with the names of the methods.\n\nYou can think of initialize as the function that \"boots up\" each object the class creates.\n\n````ruby\nclass Person\n    def initialize\n\n    end\n\nend\n````\n\n````ruby\nclass Car\n  def initialize(make, model)\n    @make = make\n    @model = model\n  end\nend\n\nkitt = Car.new(\"Pontiac\", \"Trans Am\")\n````\n\n## .new\nWe can create an instance of a class just by calling .new on the class name, like so:\n````ruby\nme = Person.new(\"Eric\")\n````\n\n## Inheritance\n\nInheritance 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.\n\n\nIn Ruby, inheritance works like this:\n````ruby\nclass DerivedClass \u003c BaseClass\n  # Some stuff!\nend\n````\nwhere 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 \"\u003c\" as \"inherits from.\"\n\n### Override!\nSometimes 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.\n\nFor 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.\n\nThis new version of send will override (that is, replace) the inherited version for any object that is an instance of Email.\n\n## super\n\nOn 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.\n\nThe syntax looks like this:\n````ruby\nclass DerivedClass \u003c Base\n  def some_method\n    super(optional args)\n      # Some stuff\n    end\n  end\nend\n````\n\nWhen 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.\n\n## multiple inheritance\n\nAny 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.\n\nHowever, 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.\n\n# Modules\n\nYou 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!\n\nYou 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!\n\n````ruby\nmodule UselessStuff\n  def almost_pi\n    3.1415\n  end\nend\n\nclass Something\n  include UselessStuff\nend\n\nSomething.new.almost_pi # =\u003e 3.1415\n````\n\nYou 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:\n````ruby\nmodule ModuleName\n  # Bits 'n pieces\nend\n````\n\nLike class names, module names are written in \u003cb\u003eCapitalizedCamelCase \u003c/b\u003e, rather than lowercasewithunderscores.\n\nIt 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.\n\nRuby 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.\n\nAn example of a Ruby constant is PI, which lives in the Math module and is approximately equal to 3.141592653589793.\n\n## namespacing\nOne 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.\n\nSee 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).\n\n## require\n\nSome 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\n\n````ruby\nrequire 'module'\n````\n## include\n\nWe can do more than just require a module, however. We can also include it!\n\nAny class that includes a certain module can use those module's methods!\n\nA 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.\n\n````ruby\nclass Angle\n  include Math\n  attr_accessor :radians\n\n  def initialize(radians)\n    @radians = radians\n  end\n\n  def cosine\n    cos(@radians)\n  end\nend\n\nacute = Angle.new(1)\nacute.cosine\n````\n\n## mixins\n\nWhat 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!\n\nWhen 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!\n\n````ruby\n\nmodule Action\n  def jump\n    @distance = rand(4) + 2\n    puts \"I jumped forward #{@distance} feet!\"\n  end\nend\n\nclass Rabbit\n  include Action\n  attr_reader :name\n  def initialize(name)\n    @name = name\n  end\nend\n\nclass Cricket\n  include Action\n  attr_reader :name\n  def initialize(name)\n    @name = name\n  end\nend\n\npeter = Rabbit.new(\"Peter\")\njiminy = Cricket.new(\"Jiminy\")\n\npeter.jump\njiminy.jump\n````\n\n## extend\n\nWhereas 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.\n\n## all and any\n````ruby\n[1, 2, 3, nil].all?     # =\u003e false\n[1, 2, 3, :nil].all?    # =\u003e true\n[1, 2, 3, false].any?   # =\u003e true\n````\n\n# Symbols\nSymbols 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. \u003cbr\u003e\n\nMake sure you don't put any spaces in your symbol name—if you do, Ruby will get confused.\n````ruby\nmy_first_symbol = :a\n````\n\n## converting symbols \u003c-\u003e strings\n\n````ruby\nConverting between strings and symbols is a snap.\n\n:sasquatch.to_s\n# ==\u003e \"sasquatch\"\n\n\"sasquatch\".to_sym\n# ==\u003e :sasquatch\n````\nBesides using .to_sym, you can also use .intern. This will internalize the string into a symbol and works just like .to_sym.\n\n# upto, downto\nIf 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.\n\nWe might use .upto to print out a specific range of values:\n\n````ruby\n95.upto(100) { |num| print num, \" \" }\n# Prints 95 96 97 98 99 100\n````\n\nand we can use .downto to do the same thing with descending values.\n\n# Blocks\n\nA Ruby block is just a bit of code that can be executed. Block syntax uses either do..end or curly braces ({}), like so:\n````ruby\n[1, 2, 3].each do |num|\n  puts num\nend\n# ==\u003e Prints 1, 2, 3 on separate lines\n\n[1, 2, 3].each { |num| puts num }\n# ==\u003e Prints 1, 2, 3 on separate lines\n````\nBlocks can be combined with methods like .each and .times to execute an instruction for each element in a collection (like a hash or array).\nBlocks are not objects, and this is one of the very few exceptions to the \"everything is an object\" rule in Ruby.\n\nBecause 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!\n\n# Procs\nYou 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!\n\n````ruby\nmultiples_of_3 = Proc.new do |n|\n  n % 3 == 0\nend\n\n(1..100).to_a.select(\u0026multiples_of_3)\n````\nProcs 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):\n````ruby\ncube = Proc.new { |x| x ** 3 }\n# 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!\n\n[1, 2, 3].collect!(\u0026cube)\n# ==\u003e [1, 8, 27]\n[4, 5, 6].map!(\u0026cube)\n# ==\u003e [64, 125, 216]\n```` \n(The .collect! and .map! methods do the exact same thing.)\n\nThe \u0026 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.\n\n## Why bother saving our blocks as procs? There are two main advantages:\n\nProcs are full-fledged objects, so they have all the powers and abilities of objects. (Blocks do not.)\nUnlike 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.\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkarinakozarova%2Fruby_training","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkarinakozarova%2Fruby_training","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkarinakozarova%2Fruby_training/lists"}