├── README.md ├── coding_conventions.md ├── looping_and_control_statements.md ├── rails_introduction.md ├── primitives_and_other_basics.md ├── functions.md └── ruby_oop_design.md /README.md: -------------------------------------------------------------------------------- 1 | # Learning Ruby from a JavaScript background 2 | 3 | This is purely a compilation of helpful notes for devs who are coming in to Ruby from **_JavaScript_**. Although the notes are tailored for a JavaScript developer, it could be useful for others. 4 | 5 | Please file an issue or a pull request if you see any inconsistencies or errors! 6 | 7 | 8 | ## Topics: 9 | 10 | It is **highly** recommended that beginners move through these in the proposed order. 11 | 12 | 1. [Pure Basics and Primitive Types](primitives_and_other_basics.md) 13 | 2. [Blocks, Procs, Lambdas and Functions](functions.md) - Everything to do with introducing Blocks, Procs, Lambdas and Functions and some techniques to pass data and control between them. 14 | 2. [Control Statements and Looping](looping_and_control_statements.md) - Looping is introduced along with control statements like `if` and `unless` 15 | 3. [OOP in Ruby](ruby_oop_design.md) - Inheritence and Classes, Modules and information hiding 16 | 4. [Some basic coding conventions](coding_conventions.md) - Some very basic practices to keep in mind when coding in Ruby. 17 | 18 | 19 | *More to come soon!* 20 | -------------------------------------------------------------------------------- /coding_conventions.md: -------------------------------------------------------------------------------- 1 | # Coding Conventions 2 | 3 | **THIS IS NOT A FULL GUIDE. JUST A GENERAL GUIDE FOR PURE BEGINNERS** 4 | 5 | A full set of coding conventions can be found at [bbatsov's writeup on Github here](https://github.com/bbatsov/ruby-style-guide) 6 | 7 | 8 | ## Curly Braces vs do...end 9 | 10 | Most style guides and best practices state that: 11 | 12 | * curly braces {} should be used for one liners 13 | * and do...end should be used for multiline statements 14 | 15 | There is also a subtle difference between the two: 16 | 17 | **Braces have a high precedence; do has a low precedence. If the method invocation has parameters that are not enclosed in parentheses, the brace form of a block will bind to the last parameter, not to the overall invocation. The do form will bind to the invocation** 18 | 19 | The examples below make it more clear: 20 | 21 | This: 22 | 23 | ```ruby 24 | task :rake => pre_rake_task do 25 | something 26 | end 27 | ``` 28 | Really means: 29 | 30 | ```ruby 31 | task(:rake => pre_rake_task){ something } 32 | ``` 33 | 34 | And this with curly braces: 35 | 36 | ```ruby 37 | task :rake => pre_rake_task { 38 | something 39 | } 40 | ``` 41 | 42 | really means: 43 | 44 | ```ruby 45 | task :rake => (pre_rake_task { something }) 46 | ``` 47 | 48 | See [Stackoverflow](http://stackoverflow.com/questions/5587264/do-end-vs-curly-braces-for-blocks-in-ruby) here for more details 49 | 50 | 51 | ## Naming convention 52 | Unlike JS where many developers use ```camelCase``` for their variable naming conventions, in Ruby: 53 | 54 | * For plain variable names: use the ```snake_case``` convention. 55 | * For file and directory names, use the ```snake_case``` convention as well. 56 | * For constants, use the ```SCREAMING_SNAKE_CASE``` convention. 57 | * For Classes and Modules, use the ```CamelCase``` convention. 58 | 59 | ### Naming functions 60 | 61 | #### Functions that return booleans 62 | For functions that return a boolean value, the name should be suffixed with a ```?```. For example: 63 | 64 | ```ruby 65 | str.include? "substring" 66 | ``` 67 | 68 | #### Functions that are setters 69 | In other languages like Java or C#, if we have an attribute ```name```, and we have to set the value of that attribute, then the setter function would be named ```setName```. 70 | 71 | Ruby allows ```=``` in method names so the convention is to suffix the ```=``` with the attribute. So in this case, it would be: 72 | 73 | ```ruby 74 | def name=(value) 75 | @name = value 76 | end 77 | ``` 78 | 79 | Terse-tastic! 80 | 81 | For future reference, getter and setter functions are called _reader_ and _writer_ functions 82 | respectively in Ruby. 83 | 84 | ##### USE ```attr_accessor```/```attr_writer``` INSTEAD OF MANUALLY HAVING A SETTER 85 | 86 | Most of the time, if this is a common instance variable, you do not need to set up your ... 87 | 88 | 89 | ## Strings 90 | 91 | ### String Concatenation vs String Formatting and Interpolation 92 | 93 | ```ruby 94 | #bad 95 | email_with_name = user.name + ' <' + user.email + '> ' 96 | ``` 97 | ```ruby 98 | #good (with string interpolation) 99 | email_with_name = "#{user.name} <#{user.email}>" 100 | ``` 101 | ```ruby 102 | #good (with string formatting) 103 | email_with_name = format('%s <%s>', user.name, user.email) 104 | ``` 105 | 106 | ## Parentheses 107 | 108 | In Ruby, parentheses are technically optional but there are times when it should be used to make the code more readable. 109 | 110 | According to the [unofficial Ruby style guide](https://github.com/bbatsov/ruby-style-guide), you **do NOT** use parentheses when: 111 | 112 | * It involves control flow statements (if-then, unless etc.) 113 | * It's a class, function or uses any language specific "keywords" words like ```puts``` or ```attr_reader```. 114 | 115 | **You use parentheses for all other method invocations.** 116 | 117 | From the aforementioned style guide: 118 | 119 | ```ruby 120 | class Person 121 | attr_reader :name, :age 122 | 123 | # omitted 124 | end 125 | 126 | temperance = Person.new('Temperance', 30) 127 | temperance.name 128 | 129 | puts temperance.age 130 | 131 | x = Math.sin(y) 132 | array.delete(e) 133 | 134 | bowling.score.should == 0 135 | ``` 136 | 137 | ## Hashes 138 | 139 | Omit the ```{}``` when being called as the last parameter of a function: 140 | 141 | ```ruby 142 | foo({ :key => 'value' }) # bad. Its unnecessary. 143 | foo(:key => 'value') # good. 144 | bar(32, :key => 'value') # good 145 | baz({ :key => 'value' }, 32) # good. The hash is not the last parameter so {} is needed 146 | 147 | ``` 148 | 149 | 150 | ## Chaining functions 151 | 152 | Functions can easily be chained as long as the reference to the class using ```self``` is returned from the functions 153 | 154 | [See here:](http://tjackiw.tumblr.com/post/23155838377/interview-challenge-ruby-method-chaining) 155 | 156 | -------------------------------------------------------------------------------- /looping_and_control_statements.md: -------------------------------------------------------------------------------- 1 | # Looping and control statements 2 | 3 | ### Conditional assignment 4 | 5 | In JS, we sometimes want to only set the value of a variable if it's not already defined. To do that in JS, we would do something like this: 6 | 7 | ```js 8 | some_var = some_var || {} 9 | ``` 10 | 11 | In Ruby, there is an even cooler and more terse way (Yey for terseness!). Here is how to write the aforementioned statement in Ruby: 12 | 13 | ```ruby 14 | some_var ||= {} #This is similar to a += or /= operator 15 | ``` 16 | 17 | ### ```if``` keyword 18 | 19 | This works just like the JavaScript version but with one small enhancement: it can be used inline with other statements (in a very cool readable way). See below: 20 | 21 | ```ruby 22 | puts "Hello Bruce" if name == 'Bruce' 23 | ``` 24 | 25 | ### ```unless``` keyword 26 | 27 | This is similar to the if condition except it will execute the statement if the result is **false** 28 | 29 | ```ruby 30 | i = 0 31 | unless i == 3 32 | print "Hooray it's not 3!" #will execute if the i == 3 is false which it is. 33 | end 34 | # => "Hooray it's not 3!" 35 | ``` 36 | 37 | You could also use the unless statement inline with other statements (in an almost backwards `if` statement). See below: 38 | 39 | ```ruby 40 | #Doing a type check to see if it's an integer. The `?` is just a naming convention to indicate it returns a boolean 41 | puts "That's not an integer bro!" unless some_int.is_a? Integer 42 | ``` 43 | 44 | ### ```switch```/```case``` statements 45 | What is called Switch statements in JS and Java and other languages is called simply case statements in Ruby. 46 | 47 | This in Ruby: 48 | 49 | ```ruby 50 | case language 51 | when "JS" 52 | puts "Dat frontend scripting language!" 53 | when "Java" 54 | puts "Aw man. The kingdom of nouns!" 55 | else 56 | puts "Some cool language I don't know!" 57 | end 58 | ``` 59 | 60 | or a more terse way to write it using ```when...then```: 61 | 62 | ```ruby 63 | case language 64 | when "JS" then puts "Dat frontend scripting language!" 65 | when "Java" then puts "Aw man. The kingdom of nouns!" 66 | else puts "Some cool language I don't know!" 67 | end 68 | ``` 69 | 70 | is equivalent to in JS: 71 | 72 | ```js 73 | switch (language) { 74 | case "JS": 75 | console.log("Dat frotnend scripting language"); 76 | break; 77 | case "Java": 78 | console.log("Aw man. The kingdom of nouns!"); 79 | break; 80 | default: 81 | console.log("Some cool language I don't know!"); 82 | } 83 | ``` 84 | 85 | So **switch** keyword in JS translates to **case** in Ruby 86 | **case** keyword in JS translates to **when** in Ruby 87 | **default** keyword in JS translates to **else** in Ruby 88 | 89 | 90 | ### ```for``` loops 91 | 92 | unlike JS, Ruby has a different ```for``` syntax where it defines the range: 93 | 94 | There are two forms for this: 95 | 96 | * with two dots used in between the range (to be max bound inclusive) 97 | * with three dots used in between the range (to be max bound exclusive) 98 | 99 | See example below: 100 | 101 | 102 | ```ruby 103 | for i in 0..10 # same as "for(var i = 0; i <= 10; i++)" in JS. NOTE THE TWO DOTS FOR 10 inclusive 104 | #some code 105 | end 106 | for i in 0...10 # same as "for(var i = 0; i < 10; i++)" in JS. NOTE THE THREE DOTS FOR 10 exclusive 107 | #some code 108 | end 109 | ``` 110 | 111 | **CAVEAT**: You cannot increment the variable in the for loop delcaration manually. 112 | 113 | In other words, 114 | 115 | ```javascript 116 | // javascript 117 | for (let i = 0; i < 100; i++) { 118 | console.log(i) 119 | i += 3 120 | } 121 | // => prints 0, 4, 8, 12... 122 | ``` 123 | 124 | ```ruby 125 | # ruby 126 | for i in (0..100) 127 | puts i 128 | i += 3 129 | end 130 | # => prints 0, 1, 2, 3, ... to 100 131 | ``` 132 | 133 | ### Using the ```loop``` keyword (i.e do..while statement in JS) 134 | 135 | In Ruby, there is another way to loop through code called the ```loop``` statement. It takes in a code block and asks for a condition to exit out of the loop if the condition is met with the ```break``` keyword. 136 | 137 | **Like the do..while loop in other languages, the loop keyword always executes at least once** 138 | 139 | For example: 140 | 141 | ```ruby 142 | #Ruby way to do it 143 | i = 0 144 | loop do 145 | i += 1 146 | puts 'Hello Person #{i}' 147 | break if i > 9 148 | end 149 | ``` 150 | 151 | This is equivalent to this `do..while` in JS: 152 | 153 | ```js 154 | var i = 0; 155 | do { 156 | i += 1; 157 | console.log('Hello Person ' + i); 158 | } while (i > 9); 159 | ``` 160 | 161 | ### Using ```until``` keyword in a ```while``` loop 162 | 163 | Just like how the ```unless``` keyword is the opposite of the ```if``` statement, the ```while``` also has its opposite: ```until```. It is used in a similar way to ```unless```. 164 | 165 | ```ruby 166 | #The following code loops until j = 0 and then breaks out of the loop. 167 | j = 3 168 | until j == 0 do 169 | puts j 170 | j -= 1 171 | end 172 | ``` 173 | 174 | 175 | #### Using the ```next``` keyword in loop 176 | 177 | You can use the 'next' keyword to skip the loop if a condition is met. It is equivalent to the ```continue``` keyword used in combination with an if. 178 | 179 | For example: 180 | 181 | ```ruby 182 | for i in 1..5 183 | next if i % 2 == 0 #skip if its an even number 184 | puts i 185 | end 186 | ``` 187 | 188 | Equivalent to JS's continue used with an if statement: 189 | 190 | ```js 191 | for (var i = 0; i <= 5; i++) { 192 | if (i % 2 == 0) { 193 | continue; 194 | } 195 | console.log(i); 196 | } 197 | ``` 198 | 199 | ### Using the ```each``` iterator for looping 200 | 201 | The each iterator is similar to the Array's `.forEach()` or Underscore/Lodash's `_.each` function. 202 | 203 | You specify an object to loop through and then specify a code block to run for each item in the object. 204 | 205 | For example, the following in Ruby: 206 | 207 | ```ruby 208 | object = ['hello', 'goodbye'] 209 | object.each { |str| puts str } 210 | 211 | #or written with do..end instead of {} 212 | object.each do |str| 213 | puts str 214 | end 215 | ``` 216 | is equivalent to in JS: 217 | 218 | ```javascript 219 | var object = ['hello', 'goodbye']; 220 | object.forEach(function(str) { 221 | console.log(str); 222 | }); 223 | ``` 224 | 225 | To iterate over hashes (i.e JS objects), you can specify 1 parameter (where the parameter can be both the key and value) or 2 parameters (one for key and one for value): 226 | 227 | ```ruby 228 | person = { 229 | 'name' => 'Goku', 230 | 'power_level' => 9000000000 231 | } 232 | # 233 | #Using 2 parameter prints: 234 | # name => Goku 235 | # power_level => 9000000000 236 | person.each { |key,val| puts "#{key} => #{val}" } 237 | # 238 | # Using 1 parameter prints: 239 | # name 240 | # Goku 241 | # power_level 242 | # 9000000000 243 | person.each { |key_or_val| puts |key_or_val| } 244 | ``` 245 | 246 | The reason for this is due to the way the iterator is setup for the each. 247 | 248 | 249 | ### Using ```times``` iterator for simple looping 250 | 251 | If you want to make a block of code execute a fixed number of times, the best way to do it would be through a "times" loop 252 | 253 | ```ruby 254 | 3.times { puts "Hello!" } #Prints "Hello!" 3 times. 255 | ``` 256 | 257 | -------------------------------------------------------------------------------- /rails_introduction.md: -------------------------------------------------------------------------------- 1 | # Rails introduction 2 | 3 | Rails is a great MVC framework written on top of Ruby. 4 | 5 | This is not an exhaustive guide. Not even close. For full docs, go [here](http://api.rubyonrails.org/) 6 | 7 | Right now, this guide is wholly unfinished. 8 | 9 | ## Basic Terminal Commands 10 | 11 | All commands can be run with ```-h``` or ```---help``` to list more information. 12 | 13 | For a full guide, see [Rails Official Commandline Guide](http://guides.rubyonrails.org/command_line.html) 14 | 15 | ### Rails commands 16 | 17 | To create a new app, use the command 18 | 19 | ```rails new ``` 20 | 21 | To open up the Ruby WEBrick server to host your rails app, run: 22 | 23 | ```rails server``` 24 | 25 | To generate specific scaffolding or use specific generators to get models, views, routes, etc., run: 26 | 27 | ```rails generate ``` 28 | 29 | To interact with the rails app from command line, you can use the rails console via: 30 | 31 | ```rails console``` 32 | 33 | 34 | #### Generating Models 35 | 36 | To generate a new model, the command is: 37 | 38 | ```rails generate model : ...``` 39 | 40 | This generates the model file as well as the database table with the specified columns. 41 | 42 | An example would be: 43 | 44 | ```rails generate model Article title:string text:text``` 45 | 46 | The above statement is telling rails to create: 47 | 48 | * an ```app/models/article.rb``` file containing a model ```Article``` 49 | * a ```db/migate/_create_articles.rb``` file needed for making changes, updates, etc. to the DB. 50 | 51 | When the database migration file is created, it will look something like this: 52 | 53 | ``` 54 | class CreateArticles < ActiveRecord::Migration 55 | def change 56 | create_table :articles do |t| 57 | t.string :title 58 | t.text :text 59 | 60 | t.timestamps null: false 61 | end 62 | end 63 | end 64 | ``` 65 | 66 | This file is used for database migrations and updates and is totally reversible. Rails prefixes the file with a timestamp to make sure they are processed in the order they are created. 67 | 68 | Now to create the table, run the command: 69 | 70 | ```rake db:migrate``` 71 | 72 | 73 | ### Rake commands 74 | 75 | What is Rake? Rake is simply a build tool. It can be thought of as a Makefile with Ruby code. Rake is a superset of Ruby. It allows developers to define build tasks via the `task` keyword. 76 | 77 | Rake automatically picks up on any 'task' defined in a file ending in the `.rake` extension inside the current subdirectory. 78 | 79 | To get a list of all tasks 80 | 81 | `rake -T` 82 | 83 | Rails relies heavily on Rake by adding some default tasks. 84 | 85 | One of which is: 86 | 87 | ```rake routes``` 88 | 89 | This is used to get a list of all routes in the app. 90 | 91 | Example result of command: 92 | 93 | ``` 94 | $ rake routes 95 | Prefix Verb URI Pattern Controller#Action 96 | articles GET /articles(.:format) articles#index 97 | POST /articles(.:format) articles#create 98 | new_article GET /articles/new(.:format) articles#new 99 | edit_article GET /articles/:id/edit(.:format) articles#edit 100 | article GET /articles/:id(.:format) articles#show 101 | PATCH /articles/:id(.:format) articles#update 102 | PUT /articles/:id(.:format) articles#update 103 | DELETE /articles/:id(.:format) articles#destroy 104 | welcome_index GET /welcome/index(.:format) welcome#index 105 | root GET / welcome#index 106 | ``` 107 | 108 | 109 | ## Basic Structure of a Rails app 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 |
Folder/FilePurpose
app/Contains the models, controllers, helpers, views, assets and mailers for your application. Our focus will be on this folder in this guide.
bin/Includes the rails script will start up your app and may contain other types of scripts used by you to deploy/ run your application.
config/Configure your application's database, routes, and more. This is will covered in detail later on in this book.
config.ruContains the Rack configuration for servers that are Rack-based and are used to start an app.
db/Includes your current database schema along with the database migrations.
Gemfile,
Gemfile.lock
Using these files, you can specify the gem dependencies that your application needs. The Bundler gem uses these files.
lib/Contains extended modules for applications
log/Contains application log files.
public/The only folder that can be viewed by the world. Includes compiled assets and static files.
RakefileThis particular file locates & loads tasks that are able to run from the command line. Throughout components of Rails, the task definitions are defined. Instead of making any changes to the Rakefile, you should consider adding your own tasks by adding files to the "lib/tasks" directory of your app.
test/Contains fixtures, tests, and numerous other types of test apparatus
tmp/Temporary files such as pid, cache, and session files.
vendor/A folder that contains all third-party code. This includes vendored gems in a typical Rails application.
173 | 174 | 175 | ## Routing 176 | 177 | ### Configuring Routes 178 | 179 | A list of all routes in an application can be found in ```config/routes.rb``` 180 | 181 | To specify a general route, you can just use: 182 | 183 | ```get '/'``` 184 | 185 | If it needs to map to a specific controller and action then we can use: 186 | 187 | ```get '' '#'``` 188 | 189 | To specify the root (i.e default controller and action for route: ```/```), then use: 190 | 191 | ```root '#``` 192 | 193 | 194 | ### Configuring resources 195 | 196 | For data to be queried back and forth by your application to serve the user, there need to be REST endpoints set up for the resources. 197 | 198 | We need to do 2 things: 199 | 200 | 1. Define the resource in ```config/routes.rb``` 201 | 2. Check to see if exists via the ```rake routes``` command 202 | 203 | 204 | To define the resource, we add an entry and use the following notation: 205 | 206 | ```resources :``` 207 | 208 | For Example: 209 | 210 | ``` 211 | Rails.application.routes.draw do 212 | #Define a resource called articles 213 | resources :articles 214 | root 'welcome#index' 215 | end 216 | ``` 217 | 218 | This will have rails setup the appropriate endpoints when the app is run next time. 219 | 220 | Running ```rake routes``` yields: 221 | 222 | ``` 223 | $ rake routes 224 | Prefix Verb URI Pattern Controller#Action 225 | articles GET /articles(.:format) articles#index 226 | POST /articles(.:format) articles#create 227 | new_article GET /articles/new(.:format) articles#new 228 | edit_article GET /articles/:id/edit(.:format) articles#edit 229 | article GET /articles/:id(.:format) articles#show 230 | PATCH /articles/:id(.:format) articles#update 231 | PUT /articles/:id(.:format) articles#update 232 | DELETE /articles/:id(.:format) articles#destroy 233 | welcome_index GET /welcome/index(.:format) welcome#index 234 | root GET / welcome#index 235 | ``` 236 | 237 | 238 | 239 | 240 | ## Naming Convention 241 | 242 | Given the database table name ```tweets``` with the data below: 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 |
idstatusname
1Where can I get a good bite to eat?Ash
2I just ate some serious brainsJim
265 | 266 | To access it, the naming convention would be an uppercase and singular class```Tweet.find(1)```. 267 | 268 | In other words, the models in rails use a singular name while the actual corresponding databases tables use a plural name. 269 | 270 | 271 | 272 | ## Glossary 273 | 274 | * ```DSL``` - Domain Specific Language 275 | * ```resource```- an object/collection of objects that can be queried by the user via REST. 276 | * ```controller action``` - the method in the controller that does some operation 277 | * ```migrations``` - ruby classes designed to make it simple to create and modify database tables. They are used for database migrations and updates and all changes they do are reversible. 278 | 279 | -------------------------------------------------------------------------------- /primitives_and_other_basics.md: -------------------------------------------------------------------------------- 1 | # Basic Primitive Types and Reading/Writing to Screen 2 | 3 | **Disclaimer**: This doesn't go through every single primitive type and explain what it is. It just explains the differences between how it is implemented and used in JS vs Ruby. 4 | 5 | ## Comments 6 | 7 | Single line comments in Ruby are defined via: 8 | 9 | ```ruby 10 | # This is a comment 11 | ``` 12 | 13 | Multiline comments are enclosed via ```=begin``` and ```=end``` 14 | 15 | ```ruby 16 | =begin 17 | Hello World 18 | This is a multiline 19 | comment 20 | =end 21 | ``` 22 | 23 | ## Semicolons 24 | 25 | Semicolons are not necessary and not recommended to be used unless you have multiple statements of code onto one line. 26 | 27 | ```ruby 28 | #bad use of semicolons! 29 | puts 'hello world'; 30 | puts 'goodbye cruel world'; 31 | ``` 32 | 33 | ```ruby 34 | #good use of semicolons 35 | puts 'hello world'; puts 'goodbye cruel world'; 36 | ``` 37 | 38 | ## Reading and Writing to the Screen/Console 39 | 40 | ### Print vs puts 41 | In JavaScript, to print something to the console, you can use the ```Console``` object via ```console.log``` but in Ruby, it is differentiated to two different functions: ```puts``` and ```print``` 42 | 43 | The differences are **exactly the same as** Java's ```System.out.println``` and ```System.out.print``` respectively in that: 44 | 45 | ```ruby 46 | puts 'Hello' # prints and adds a newline at the end (Similar to Java's System.out.println()) 47 | print 'Hello' # prints but no newline is added (Similar to Java's System.out.print()) 48 | 49 | =begin 50 | The following yields: 51 | Hello 52 | Hello 53 | =end 54 | puts 'Hello' 55 | puts 'Hello' 56 | 57 | =begin 58 | The following yields: 59 | HelloHello 60 | =end 61 | print 'Hello' 62 | puts 'Hello' 63 | ``` 64 | 65 | ### Getting User Input from console 66 | In Ruby, reading input from the user is done with the ```gets``` keyword (puts for output, gets for input). 67 | 68 | There is one caveat to the ```gets``` keyword and that it returns the User's input WITH a newline character. 69 | 70 | ```ruby 71 | puts "Hello. What is your name?" 72 | name = gets # If you entered 'Jake', then name='Jake\n' 73 | ``` 74 | 75 | #### Removing the newline character from ```gets``` 76 | To remove the newline character added from ```gets```, use the ```chomp``` function. 77 | 78 | ```ruby 79 | name = gets.chomp # With chomp, it strips the '\n' and so name='Jake' 80 | ``` 81 | 82 | 83 | ## Hashes (i.e JS-y objects) 84 | 85 | Objects in JavaScript are called hashes in Ruby. 86 | 87 | ### Traditional/JS-y way to define it: 88 | 89 | In JS and Ruby, an empty hash can be defined like so: 90 | 91 | ```javascript 92 | stuff = {} 93 | ``` 94 | 95 | JS and Ruby both can use ```:``` to seperate key value pairs in hashes like so: 96 | 97 | ```ruby 98 | #the same in both JS and Ruby 99 | a = { status: 'zombie', name:'Katie', id: 5 } 100 | ``` 101 | 102 | **Every key in a hash is a [symbol](#symbols) and can be accessed as such:** 103 | 104 | ``` 105 | a[:status] #Same as a['status'] 106 | ``` 107 | 108 | #### Alternate notation for key value seperators using the hashrocket: ```=>``` 109 | 110 | Instead of using ```:``` to seperate key value pairs, In Ruby, one can also use ```=>``` instead. 111 | 112 | **NOTE:** notice that the property names are in quotes. Ruby requires that they either be in quotes or be a [symbol](#symbols). Otherwise, Ruby assumes it is a variable or a function and would return an error. 113 | 114 | ```ruby 115 | stuff = { 116 | 'name' => 'Bilbo Baggins', 117 | 'survives' => true 118 | } 119 | ``` 120 | 121 | Equivalent JS: 122 | 123 | ```javascript 124 | stuff = { 125 | name: 'Bilbo Baggins', 126 | survives: true 127 | }; 128 | ``` 129 | 130 | #### Ommitting the ```{}``` 131 | 132 | When passing a hash to a function, if the hash is the last parameter, the ```{}``` can be ommitted. 133 | 134 | So if there is a method ```foo``` that takes in 1 hash as a parameter: 135 | 136 | ``` 137 | foo({ 'status' => 'zombie' }) # This... 138 | foo('status' => 'zombie') # is the same as this 139 | ``` 140 | 141 | ### Via Hash.new: 142 | 143 | Hash.new takes in an optional parameter for the default value. If set, anytime a non-existent key is accessed or an operation is done on a key that has no value, this default value is returned instead. 144 | 145 | ```ruby 146 | x = Hash.new #Creating a blank hash with the default value as nil 147 | stuff = Hash.new(0) #Creating a new object and setting the default value to 0. 148 | stuff[a] = 3; # => 3 149 | 150 | puts stuff[a] # prints out "3" 151 | puts stuff[b] # prints out "0" 152 | ``` 153 | 154 | #### Dot notation and Ruby 155 | 156 | Unlike JavaScript where objects (i.e Ruby hashes) can be accessed by dot notation, Ruby forces hash properties to be accessed via *array notation*. 157 | 158 | This is because dot notation indicates to Ruby that its a function: 159 | 160 | ```javascript 161 | //in javascript 162 | var foo = { 163 | bar: 3 164 | }; 165 | 166 | foo.bar //completely valid. => 3 167 | ``` 168 | 169 | ```ruby 170 | foo = { 171 | 'bar' => 3 172 | }; 173 | 174 | foo['bar'] # Valid. => 3 175 | foo.bar # Invalid. Looks for a function named bar that belongs to foo and throws an error. 176 | ``` 177 | 178 | 179 | ## Strings 180 | 181 | Strings works pretty much the same way in JS as it does in Ruby with a few nice enhancements. 182 | 183 | ### String Interpolation 184 | Aside from standard string concatenation, Ruby allows String interpolation. This allows you to refer to variables from inside a string using the ```#{}``` syntax **as long as you use double quotes**: 185 | 186 | ```ruby 187 | name = 'Batman' 188 | puts "#{name}" # => Batman 189 | ``` 190 | 191 | You can even execute functions from inside the ```#{}``` 192 | 193 | ```ruby 194 | puts "#{name.upcase}" # => BATMAN 195 | ``` 196 | 197 | ES2015 has introduced Template literals (aka template strings) which are the equivalent to Ruby's String interpolation: 198 | 199 | ```javascript 200 | name = 'Batman' 201 | console.log(`${name}`) // => Batman 202 | 203 | console.log(`${name.toUpperCase()}`) // => BATMAN 204 | ``` 205 | 206 | ### String Interpolation and Single Quotes 207 | String interpolation is not possible with single quotes. If single quotes are specified, Ruby will take the input **literally**. 208 | 209 | **You MUST use double quotes for string interpolation to be done** 210 | 211 | ```ruby 212 | name = 'Batman' 213 | puts 'I am #{name}' # => 'I am #{name}' 214 | puts "I am #{name}" # => 'I am Batman' 215 | ``` 216 | 217 | ## Arrays 218 | 219 | Arrays work the same as in JS with one or two small tweaks. 220 | 221 | In Ruby, there is an alias for the push function using the ```<<``` operator. It can be used like so: 222 | 223 | ```ruby 224 | [3,2] << 5 # => [3,2,5] 225 | [3,2].push(5) # same as above statement and the JS-y way to do it but NOT conventional 226 | ``` 227 | 228 | 229 | ## Comparing/Converting/Checking different objects 230 | 231 | ### Comparing two different objects 232 | 233 | ### ```==``` operator 234 | The JS ```===``` is the same as Ruby's ```==``` in that it checks **both** the type and the **value** **BUT does not care if they are in two different locations in memory (unlike Java's ==)**. 235 | 236 | ### ```===``` operator 237 | 238 | This is the same as ```==``` except it can be overriden by objects for their own custom equals logic. It would be the equivalent to overriding the equals function in Java. 239 | 240 | ### Combined Comparison Operator 241 | 242 | Aside from the usual ```==```, ```>=```, ```<=```, ```!=```, Ruby has another comparison operator called the **Combined Comparison Operator** designated by ```<=>```. 243 | 244 | This returns, 245 | 246 | * 0 if the two objects are equal 247 | * 1 if the 1st object is greater 248 | * -1 if the 2nd object is greater 249 | 250 | In this regard, you can think of the combined comparison operator as a glorified shorthand for the ```compareTo``` function in JS and Java 251 | 252 | ```ruby 253 | 'Hello' <=> 'Hello' # => 0 254 | 3 <=> 2 # => 1 255 | 3 <=> 9 # => -1 256 | ``` 257 | 258 | ### ```equal?``` function 259 | 260 | To check to make sure that the two objects point to the same point in memory, you need to use the ```equal?``` 261 | 262 | **See this [StackOverflow answer on == vs === vs equal? vs eql?](http://stackoverflow.com/a/7157051)** 263 | 264 | 265 | ### Checking Types 266 | To check the type of an object, use ```is_a?``` function 267 | 268 | ```ruby 269 | greeting = 'Hello' 270 | greeting.is_a? Integer # Checking if greeting is an Integer. => false 271 | greeting.is_a? String # Checking if greeting is a String. => true 272 | ``` 273 | 274 | ### Converting 275 | 276 | #### To a string 277 | Converting to a String involves using the ```to_s``` function 278 | 279 | ```ruby 280 | 3.to_s # => "3" 281 | ``` 282 | 283 | #### To an integer 284 | Involves using the ```to_i``` function 285 | 286 | ```ruby 287 | 'Hello'.to_i # => 0 288 | ``` 289 | 290 | #### To a proc 291 | Involves using the ```to_proc``` function 292 | 293 | Procs are covered [here](functions.md#blocks-procs-and-lambdas). 294 | 295 | 296 | ## Symbols 297 | **Symbols are a special object that contains names and strings inside the Ruby Interpreter.** 298 | 299 | ~~There is no standard JS equivalent to Symbols~~. Symbols were introduced to JavaScript in ES2015. 300 | The closest Java equivalent to this would probably be interned Strings. This is because symbols are defined as static things which are used once and are immutable. Referencing them again will refer to the same copy in memory. 301 | 302 | Symbols can only be values set to other objects. 303 | 304 | They are defined via ":". Here are some examples: 305 | 306 | ```ruby 307 | :hello 308 | :'Hello World' # If you want to use symbol names with spaces 309 | :"Hello World" # Ruby doesn't care whether you use single or double quotes like JS 310 | :'Hello World'.to_s # => 'Hello World' 311 | books['some-book'] = :hello # Sets the object's value at that key to the symbol ':hello' 312 | books['some-other-book'] = :hello # Refers to the SAME object as books['some-book'] 313 | ``` 314 | 315 | **WARNING: *For Ruby versions < 2.2*, SYMBOLS TAKE UP MEMORY AND CANNOT BE GARBAGE COLLECTED. YOU CAN CAUSE DoS PROBLEMS IF YOU AREN'T CAREFUL** 316 | 317 | 318 | ## Incrementing and Decrementing 319 | 320 | Unlike JS, Ruby has no preincrement ```++i```, postincrement ```i++```, predecrement ```--i``` and postdecrement ```i--``` for the same reasons as python: 321 | 322 | * Makes implementation simpler 323 | * ++ and -- are NOT reserved operators in Ruby. 324 | * C's increment/decrement operators are in fact hidden assignment. They affect variables, not objects. You cannot accomplish assignment via method. 325 | 326 | So instead, Ruby uses += and -= operators 327 | 328 | ```ruby 329 | i++ # throws an error in Ruby 330 | i += 1 # Right way 331 | ``` 332 | -------------------------------------------------------------------------------- /functions.md: -------------------------------------------------------------------------------- 1 | # Blocks, Procs, Lambdas and Functions 2 | 3 | ## Blocks, ```proc``` and ```lambda``` 4 | 5 | In Ruby, there is a reusable piece of code called a block. It is designated by curly braces: ```{}``` 6 | 7 | Many functions such as `sort`, `each` and `times` allow you to specify a code block to execute. 8 | 9 | For example, in Ruby, if you wanted to print "Hello" 5 times, you could do: 10 | 11 | ```ruby 12 | # The code inside the curly braces is a block that is passed to the function 'times' 13 | 5.times { puts "Hello" } 14 | ``` 15 | 16 | ### Passing in code blocks as parameters to functions 17 | If you want to pass in a code block as a valid parameter to a function, you need to specify to Ruby that it is a function/code block by using the ```&``` prefix. See below: 18 | 19 | **IMPORTANT:** Like the [splat arguments](#splat-arguments), this needs to be defined as a parameter of the function **last** 20 | 21 | ```ruby 22 | # Note the '&' before the 'func' argument in the method definition 23 | def foo(&func) 24 | func.call 25 | end 26 | foo { puts "Hello World" } 27 | ``` 28 | 29 | ### Isn't a block just an anonymous function? 30 | Not exactly. Blocks look VERY similar at a first glance but an anonymous function is more like a Ruby [lambda function](#lambda-functions) 31 | 32 | ### So...what is a ```proc```? 33 | Ruby is built on an "everything is an object" philosophy and that ironically has a few exceptions, one of which is that **a block is NOT an object**. 34 | 35 | So how do we reuse blocks? We give it a name but a name can only be given to an object. This is where ```proc``` comes in. It is a container object that holds blocks. 36 | 37 | To declare a ```proc```, you can use ```Proc.new```. 38 | 39 | To reference a proc inside a function, you use the ```&``` prefix with the name of the proc. When the prefix is attached, Ruby essentially unpacks/unwraps the block and passes it to the function. 40 | 41 | See below: 42 | 43 | ```ruby 44 | times_2 = Proc.new { |num| num * 2 } #define the proc 45 | [1,2,3].map(×_2) #note how the proc is prefixed with the '&' 46 | # => [2,4,6] 47 | ``` 48 | 49 | ### Calling Procs directly with ```call``` 50 | 51 | To call procs directly, use the ```call``` method like so: 52 | 53 | ```ruby 54 | hello = Proc.new { puts 'Hello World' } 55 | hello.call # => Hello World 56 | ``` 57 | 58 | **WARNING:** using ```return``` inside a proc will cause it to not only exit out of the proc but return outside of the calling function. See below: 59 | 60 | ```ruby 61 | def foo 62 | some_proc.call #The return in this proc will kick us out of function foo 63 | return 'Goodbye' #This never gets executed :'( 64 | end 65 | 66 | some_proc = Proc.new { return 'Hello' } 67 | 68 | foo 69 | ``` 70 | 71 | So: 72 | 73 | ```ruby 74 | 'Goodbye' #Expected 75 | 'Hello' #Actual :( 76 | ``` 77 | 78 | 79 | ### Converting Symbols to Procs for shorthand blocks 80 | In Ruby, there is a bit of shorthand notations which will, for most JS developers not familair with Ruby, look like black magic. 81 | 82 | Converting symbols to Procs is one such example. See this example below: 83 | 84 | ```ruby 85 | ["1", "2", "3"].map(&:to_i) # => [1,2,3] 86 | ``` 87 | 88 | Most devs will probably be like... 89 | 90 | ![](http://replygif.net/i/311.gif) 91 | 92 | Everything is fairly normal until we hit the ```&:to_i``` 93 | 94 | 95 | What is happening is: 96 | 97 | * ```to_i``` is a function and when combined with ```:``` gets turned into a symbol referencing the ```to_i``` function (which just converts the object to an integer). 98 | * Recall that the ```&``` prefix for a proc usually unwraps/unpacks the block for a function to consume. In this case, since it's a symbol and not a block, Ruby calls the ```to_proc``` function to convert it to a block. 99 | * This newly formed block is fed into the map function. 100 | 101 | So...: 102 | 103 | ```ruby 104 | ["1", "2", "3"].map(&:to_i) # => [1,2,3] 105 | ["1", "2", "3"].map { |arg| arg.to_i } # same as the above statement 106 | ``` 107 | 108 | **NOTE: This notation and referencing the method via ```&``` works with ```lambda``` (see next section) too.** 109 | 110 | ### What are lambdas? 111 | A lambda is a ```proc``` but with a few small additions. It is declared almost the same way as a proc. 112 | 113 | ```ruby 114 | foo = Proc.new { puts "Hello World" } 115 | bar = lambda { puts "Goodbye Cruel World" } 116 | ``` 117 | 118 | #### Then aren't lambdas and procs the same? 119 | 120 | Nope. Lambdas and procs have 2 major differences: 121 | 122 | 1. Lambdas check the number of arguments passed to it while procs do not. This means if a lambda has 3 arguments and is passed 2, it throws an error. Procs on the other hand just assign ```nil``` to any missing arguments. 123 | 2. Unlike procs, when a return statement is hit inside a lambda, it only exits out of the lambda and not out of the calling method. 124 | 125 | ```ruby 126 | foo = lambda { |x, y| x + y } 127 | 128 | def bar 129 | foo.call(5) #Insufficient args so Ruby throws an 'ArgumentError' 130 | return 'Hello' 131 | end 132 | 133 | bar 134 | ``` 135 | 136 | ```ruby 137 | foo = lambda { |x,y| return x + y } #The return only exits out of lambda, not calling method 138 | 139 | def bar 140 | foo.call(5, 6) 141 | return 'Hello' 142 | end 143 | 144 | bar # Returns 'Hello' not 11 145 | ``` 146 | 147 | #### Why can't you call Procs and Lambda functions like regular functions with `()` 148 | 149 | If a lambda is defined like so: 150 | 151 | ```ruby 152 | foo = lambda { |x,y| x + y } 153 | ``` 154 | 155 | Then invoking it like below will throw an error: 156 | 157 | ```ruby 158 | foo(5) # => NoMethodError: undefined method `foo` for Object 159 | ``` 160 | 161 | This is better explained at [StackOverflow here](http://stackoverflow.com/questions/1686844/why-isnt-the-ruby-1-9-lambda-call-possible-without-the-dot-in-front-of-the-pare) 162 | 163 | ### Passing Procs/Lambdas as parameters to functions 164 | 165 | To pass procs/lambdas as parameters to functions for actions such as filtering, use the ```&``` to refer to the proc/lambda. This essentially unpackages/unwraps the code block from the proc/lambda 166 | 167 | ```ruby 168 | stuff = [:hello, :goodbye, 'Hello', 'Goodbye'] 169 | is_symbol = Proc.new { |val| val.is_a? Symbol } #Lets filter out anything that isn't a symbol 170 | 171 | stuff.select!(&is_symbol) # => [:hello, :goodbye] 172 | ``` 173 | 174 | 175 | ## Functions and Parameters 176 | 177 | ### Defining functions 178 | 179 | To define a function, the ```def``` keyword is used and is wrapped with an ```end``` to finish off the code block. 180 | 181 | For example: 182 | 183 | ```ruby 184 | #Function that takes in no args 185 | def foo 186 | puts 'Hello World' 187 | end 188 | ``` 189 | 190 | or: 191 | 192 | ```ruby 193 | #function that takes in 1 argument 194 | def foo(name) 195 | puts "Hello #{name}!" 196 | end 197 | ``` 198 | 199 | #### Returning from a function 200 | 201 | If you want to return something, you can use the ```return``` keyword. **HOWEVER**, if the last line of a function is the return statement, then the ```return``` keyword isn't needed. Ruby will automatically return the last variable set or retrieved without the return keyword. See below: 202 | 203 | ```ruby 204 | #bad 205 | def foo 206 | name = 'hello' 207 | return name #unnecessary return 208 | end 209 | 210 | #good way to do it 211 | def foo 212 | name = 'hello' #Ruby will auto return this variable value. 213 | end 214 | ``` 215 | 216 | Another example: 217 | 218 | ```ruby 219 | def times_2(n): 220 | n * 2 #Ruby will auto return this value without the return statement. 221 | end 222 | ``` 223 | 224 | A ```return``` IS needed if this is **NOT** the last line of the function 225 | 226 | 227 | ```ruby 228 | def foo(x): 229 | return "hello" if x == "friend" 230 | return "hater!" if x == "hater" 231 | "stranger" 232 | end 233 | ``` 234 | 235 | 236 | #### Functions with an arbitrary number of arguments using splat (```*```) 237 | In Java, you would define an arbitrary number of arguments of the same type via the ```...``` keyword like so: 238 | 239 | ```java 240 | // In Java 241 | public void function(int ...numbers) { /* do something */ } 242 | ``` 243 | 244 | In Ruby, the splat arguments keyword ```*``` is used. This tells ruby that *we don't know how many arguments there are.* 245 | 246 | For example: 247 | 248 | ```ruby 249 | def todd_five(greeting, *bros) 250 | bros.each { |bro| puts "#{greeting}, #{bro}!" } 251 | end 252 | 253 | todd_five("Innuendo Five!", "J.D", "Turk") 254 | ``` 255 | 256 | 257 | ### Executing functions with no parameters 258 | 259 | In JavaScript, it is mandatory to execute function with no arguments with parentheses but in ruby, parentheses aren't required and so most devs don't use them: 260 | 261 | ```ruby 262 | SomeClass.foo #This is equivalent to SomeClass.foo() in JS 263 | ``` 264 | 265 | ### Executing functions with one or more known parameters 266 | Unlike JS, in Ruby, parameters don't need to be enclosed by parentheses. The Ruby intepreter just looks for the parameters to be seperated by commas. 267 | 268 | ```ruby 269 | puts 'Hello' 'World' 'Goodbye' # Similar to console.log('Hello', 'World', 'Goodbye') 270 | puts('Hello', 'World') # Also correct in Ruby but less used as its unneccessary 271 | ``` 272 | 273 | 274 | #### When to use parentheses 275 | See the [Coding Conventions](coding_conventions.md#parentheses) page for more details. 276 | 277 | **tl;dr**: Omit parentheses for anything with keyword status in Ruby and explicitly use parentheses for everything else. 278 | 279 | ### Functions as arguments 280 | 281 | In Ruby, functions can be passed blocks via {} which act similar to anonymous functions in JavaScript (see below) 282 | 283 | ```ruby 284 | books = {} 285 | books['stuff'] = 'hello' #setting a key and value is the same as in JS 286 | books.values.each { puts 'Hello' } #equivalent to Object.values(books).forEach(function(){ console.log('Hello') }); in JS 287 | ``` 288 | 289 | ### Functions doing changes inplace 290 | Some JS functions do their changes to an object in place and some don't. Ruby, however, makes this matter very clear. 291 | 292 | Executing the function and ending with `!` makes the change in-place. For example: 293 | 294 | ```ruby 295 | name = "Gautham" 296 | puts name.upcase # => "GAUTHAM" 297 | puts name # => "Gautham" (the name wasn't changed) 298 | puts name.upcase! # => "GAUTHAM" 299 | puts name # => "GAUTHAM" (the name was changed when ! was specified in prev statement) 300 | ``` 301 | 302 | For functions with parameters, the ```!``` comes before the parameters 303 | 304 | ```ruby 305 | str = "sea shells by the sea shore" 306 | str.gsub!(/s/, "th") # Note how the ! is before the parameters 307 | print str # Returns "thea thhellth by the thea thhore" 308 | ``` 309 | 310 | Note that you cannot use the '!' to try to do an inplace change if the original type and resulting type from the operation are different. 311 | 312 | ```ruby 313 | str = 'Hello' 314 | str.to_i! #This will return an error. String and integer are not the same type 315 | str = str.to_i #The workaround 316 | ``` 317 | 318 | 319 | ### Function parameters to anonymous functions 320 | 321 | In Ruby, parameters to anonymous functions are enclosed via `|` or "pipe" characters like so: 322 | 323 | ```ruby 324 | books.values.each { |book| puts 'Gotta read ' + book } 325 | ``` 326 | 327 | which is equivalent to in JavaScript: 328 | 329 | ```javascript 330 | Object.values(books).forEach(function(book) { 331 | console.log('Gotta read ' + book); 332 | }); 333 | ``` 334 | 335 | ### ```yield``` and executing code blocks inside functions 336 | In Ruby, you can yield control to run a block of code inside another function. This has a variety of uses. 337 | 338 | As a refresher, a block is just a reusable piece of code enclosed by braces ```{}``` 339 | 340 | Using the ```yield``` keyword you can invoke code blocks and pass it arguments as if they were functions. **Unless the blocks are specified as arguments, they are outside the parentheses. See below:** 341 | 342 | ```ruby 343 | def foo(greeting) 344 | puts 'Inside the function foo' 345 | yield(greeting) 346 | puts 'Back inside the function foo' 347 | end 348 | foo("Top of the mornin to ya") { |arg| puts "#{arg} John" } 349 | ``` 350 | 351 | This prints out: 352 | 353 | ``` 354 | Inside the function foo 355 | Top of the mornin to ya John 356 | Back inside the function foo 357 | ``` 358 | 359 | -------------------------------------------------------------------------------- /ruby_oop_design.md: -------------------------------------------------------------------------------- 1 | # Ruby OOP Design 2 | 3 | *Everything is an object*. One of the fundamental tenets of Ruby is that *EVERYTHING* is an object. You will see this further in the classes section. 4 | 5 | ## Classes 6 | 7 | Unlike JS which needs to use closures to create class-like structures (at least until EcmaScript 6 is finalized and comes out), Ruby has an actual structure designated by the ```class``` attribute. 8 | 9 | Here are the basic syntaxes for a class: 10 | 11 | 1. ```class``` defines the class (pretty obvious) 12 | 2. ```initialize``` function is the constructor for the class. The name matters. The constructor MUST have this name if you are overriding the default empty constructor! 13 | 3. An instance variable must have the ```@``` prefixed to it (Example: _@name_) 14 | 4. To instantiate an instance of a class, unlike JS which uses ```new (...)```, Ruby uses a syntax with this format: ```.new(...)``` 15 | 5. ```self``` is a term to refer to the actual class itself NOT the instance of the class. 16 | 17 | Finally, Class names are written in `CamelCase` not ```snake_case```. 18 | 19 | 20 | Here is a simplistic example: 21 | 22 | ```ruby 23 | class Superhero 24 | def initialize(pseudonym, name) 25 | @pseudonym = pseudonym 26 | @name = name 27 | end 28 | 29 | def description 30 | puts "I'm #{@pseudonym} but my real name is #{@name}!" 31 | end 32 | end 33 | 34 | batman = Superhero.new('Batman', 'Bruce Wayne') 35 | batman.description # => "I'm Batman but my real name is Bruce Wayne" 36 | ``` 37 | 38 | ### Inheritence 39 | 40 | Unlike JS which uses a nonstandard prototypal inheritence, Ruby has a more classic inheritence akin to Java. It uses the ```<``` to designate what the class inherits from. 41 | 42 | Here is a basic example: 43 | 44 | ```ruby 45 | class Agent 46 | def hijack_person 47 | puts 'I got them. Intercepting them now.' 48 | end 49 | 50 | def order_sentinels 51 | puts "Send the sentinels. They can't use EMP yet" 52 | end 53 | end 54 | 55 | class Smith < Agent 56 | def give_monologue_to_neo 57 | puts 'Mr...Anderson. Humanity is the virus. We are the cure' 58 | end 59 | end 60 | 61 | Smith.new.order_sentinels # => 'Send the sentinels. They can't use EMP yet' 62 | Smith.new.give_monologue_to_neo # => 'Mr...Anderson. Humanity is the virus. We are the cure' 63 | 64 | ``` 65 | 66 | As you can see, the Agent class has two functions and by using the ```child_class < parent_class``` syntax, we were able to have Smith class inherit from the Agent class and call not only the Agent's own functions but the inherited functions as well. 67 | 68 | **Ruby only allows single parent inheritence. To get around this, see [here](#mixins-with-include-and-extend) 69 | 70 | ### Overriding inherited functions 71 | 72 | This is just like all other languages, just name the function the same as in the parent class to override it. 73 | 74 | ### Calling super (superclass version) function 75 | 76 | If you have overriden a parent class function but now still need access to the parent class function, you can use the ```super``` keyword like you would in Java. 77 | 78 | ```ruby 79 | class Dog 80 | def speak 81 | puts "I'm a dog." 82 | end 83 | end 84 | 85 | class Pitbull < Dog 86 | def speak 87 | super #If there were any arguments, it would be super(...) 88 | puts "But I'm also a pitbull..." 89 | end 90 | end 91 | ``` 92 | 93 | ### Getters and Setter functions 94 | Getter and setter functions can be created via standard function definitions but this is suboptimal. We don't want to create getters and setters manually for a lot of the instance variables. 95 | 96 | Ruby allows a nice shortcut for this using the ```attr_reader```, ```attr_writer``` and ```attr_accessor``` classes! They take in the instance variable name structured as a symbol (see example below). 97 | 98 | Instead of writing your getter and setter function like so: 99 | 100 | ```ruby 101 | class Foo 102 | @name #just creating the instance var. currently 'nil' 103 | 104 | def name 105 | @name 106 | end 107 | 108 | def name=(value) 109 | @name = value 110 | end 111 | end 112 | 113 | a = Foo.new 114 | a.name = 'Billy' 115 | ``` 116 | 117 | you can just write this: 118 | 119 | ```ruby 120 | class Foo 121 | attr_accessor :name #The name of the attribute written as a symbol. 122 | end 123 | 124 | a = Foo.new 125 | a.name = 'Billy' 126 | a.name # => 'Billy' 127 | ``` 128 | 129 | ```attr_accessor``` will generate the getter and setter for the variable while ```attr_reader``` and ```attr_writer``` will only generate the getter or the setter function respectively. 130 | 131 | If you are confused about the ```name=(value)``` then please see [the naming convention entry in the Coding Conventions page](coding_conventions.md#setter-naming-convention) 132 | 133 | ### Class Definitions (Gotchas when coming from other languages) 134 | 135 | In Ruby, code that defines a class is no different from any other code. This means you can place the class definition code almost anywhere. For example: 136 | 137 | ```ruby 138 | # this is actually valid 139 | # yields: 140 | # Hello 141 | # Hello 142 | 2.times do 143 | class Foo 144 | puts 'Hello' 145 | end 146 | end 147 | ``` 148 | 149 | ##### Classes can be defined multiple times 150 | 151 | In Ruby, the first time the interpreter encounters a class definition, it creates the class with the specific members that have been specified. If it encounters a definition for the same class again, it actually *extends the existing definition*. 152 | 153 | ```ruby 154 | # Defines class Foo 155 | class Foo 156 | def bar 157 | 2 158 | end 159 | end 160 | 161 | # extends already defined Foo 162 | class Foo 163 | def baz 164 | 3 165 | end 166 | end 167 | 168 | # The above 2 definitions is equivalent to this 169 | class Foo 170 | def bar 171 | 2 172 | end 173 | 174 | def baz 175 | 3 176 | end 177 | end 178 | ``` 179 | 180 | This metaprogramming feature is a pretty powerful way to extend classes at runtime and this is how the Rails's `ActiveRecord` classes work (see the rails doc for details). 181 | 182 | The JS equivalent of this would be overriding the `prototype` of an existing type. 183 | 184 | ###### Careful in overriding existing functions! 185 | 186 | This kind of extending classes on existing types inherent to the language is termed by JS devs as "monkeypatching" and is dangerous to do on existing types. For example: 187 | 188 | ```ruby 189 | class Foo 190 | def bar 191 | 3 192 | end 193 | end 194 | 195 | # somewhere else in the code 196 | # The following actually overwrites existing bar definition 197 | class Foo 198 | def bar 199 | 5 200 | end 201 | end 202 | 203 | Foo.new.bar # => 5 204 | ``` 205 | 206 | This example might seem silly but it is very important to note. In JavaScript, developers are warned not to overwrite existing types like `String.prototype` or `Array.prototype` that might unintentionally affect other functionality or libraries used in the app. Ruby code has the same implications and so the same care must be taken. 207 | 208 | ### Scope 209 | 210 | JavaScript is a wonderful language in the way we can manipulate access to variables via closures. In Ruby, the scoping rules completely different. 211 | 212 | Unlike JS which is all based on a function scope, Ruby has 4 different scopes: 213 | 214 | 1. **global variables (prefixed with ```$```)** - are available everywhere. _If you don't prefix the variable with ```$``` but it is outside of any function or class, then it is still a global variable_. 215 | 2. **local variables** - are available only to the methods they are defined in. 216 | 3. **class variables (prefixed with ```@@```)** - are available to all members of the class and between instances of the class. Adding a class variable is essentially like attaching a variable to a JavaScript object's prototype. As soon as it's defined, it is shared and viewed by all instances of the object. 217 | 4. **instance variables (prefixed with ```@```)** - are available to a particular instance of the class 218 | 219 | **NOTE:** To access a global variable defined with ```$```, it **MUST** be accessed with ```$``` as the prefix. 220 | 221 | **NOTE 2**: Another way to think of class variables is to think that they are like Java's ```static``` variables or functions. They are called the same way too. 222 | 223 | A good example of using class variables is for counting the instances of a class 224 | 225 | ```ruby 226 | class Foo 227 | @@foo_instance_count = 0 228 | 229 | def initialize 230 | @@foo_instance_count += 1 231 | end 232 | 233 | def self.get_instance_count 234 | @@foo_instance_count 235 | end 236 | end 237 | 238 | a = Foo.new 239 | puts Foo.get_instance_count #Note we are accessing via the class itself and not the instance 240 | # => 1 241 | b = Foo.new 242 | puts Foo.get_instance_count # => 2 243 | ``` 244 | 245 | ### Everything is an object (even a class) 246 | 247 | If you define a class Foo: 248 | 249 | ```ruby 250 | class Foo; end 251 | ``` 252 | 253 | Then the class `Foo` inherits from `Class`. 254 | 255 | But what exactly is a class? In Ruby, it's really just an object! This object sets up all of the methods that you associate with classes including `new`, `superclass` and `allocate`. 256 | 257 | But wait...if `Class` is an object, then does it inherit from something? Yes. Here is the inheritance chain: 258 | 259 | ``` 260 | BasicObject <--- Object <-- Module <-- Class 261 | ``` 262 | 263 | So technically... all classes are modules and `BasicObject` is the root of the Ruby class heirarchy. 264 | 265 | ### Class Reflection and Metaprogramming 266 | 267 | Unlike other languages like C where much of the metadata on an object or class is stripped away during runtime, Ruby keeps almost all of it. 268 | 269 | Some useful information that can be available are: 270 | 271 | ##### Class and Superclass via `.class` and `.superclass` 272 | 273 | ```ruby 274 | class Foo 275 | end 276 | 277 | x = Foo.new 278 | x.class # => Foo 279 | x.superclass # => Class 280 | ``` 281 | 282 | Every object has a `class` property that is essentially a reference to the class that created it. In the aforementioned example, `x.class == Foo` 283 | 284 | ##### Getting a list of methods via `.methods`, `.public_methods`, `.protected_methods`, `.private_methods` 285 | 286 | ```ruby 287 | class Foo 288 | def bar 289 | end 290 | end 291 | 292 | x = Foo.new 293 | x.methods(false) # `false` tells the function to only return non-inherited methods. 294 | # => [:bar] 295 | 296 | #To get a subset by searching through the methods, calling grep() is useful 297 | x.methods.grep(/ba/) # => [:bar] 298 | ``` 299 | 300 | ##### Getting a list of instance variables via `.instance_variables` 301 | 302 | ```ruby 303 | class Foo 304 | @a = 3 305 | def initialize 306 | @b = 5 307 | end 308 | end 309 | 310 | Foo.instance_variables # => [:@a] 311 | Foo.new.instance_variables # => [:@b] 312 | ``` 313 | 314 | Why is `@a` not available for `Foo.new`? It's because` @a` is an instance variable of Foo (since class Foo is technically an object). When `Foo.new` is executed, the `initialize` function is called, creating a new instance variable `@b`. 315 | 316 | 317 | ## Module 318 | 319 | A module in Ruby is a data structure for holding methods and constants. 320 | 321 | Just like with classes, they have a ```CamelCase``` naming convention. 322 | 323 | ```ruby 324 | module Foo 325 | SOME_CONSTANT = 9 326 | end 327 | ``` 328 | 329 | ### Namespace resolution using ``::`` 330 | 331 | If there are multiple functions with the same name in different modules, to make sure Ruby knows to pick the right function, we use ```::``` format to be specific. 332 | 333 | For example, if you define a module with the constant PI 334 | 335 | ```ruby 336 | module Foo 337 | PI = 3.1415 338 | end 339 | ``` 340 | 341 | Then if you want to refer to the Math module's PI and not Foo's, you can specify it like so: 342 | 343 | ```ruby 344 | Math::PI #=> 3.141592653589793 345 | ``` 346 | 347 | You can also use the standard dot notation as well **IF it is a function** 348 | 349 | ```ruby 350 | Date::Today 351 | Date.Today #same as Date::Today 352 | ``` 353 | 354 | 355 | ### Importing a module with ```require``` and ```include``` 356 | 357 | There are two ways to import a module: 358 | 359 | 1. ```require 'module'``` - This imports the module but you still have to refer to it by namespace. For example, if you import Math library, to use the cos() function, you still need to say ```Math.cos``` 360 | 2. ```include Module``` - This imports the module AND acts as if the module contents are now part of the class/module. This is very important as it allows you to use the module's constants and methods without the prefix. As a result, if you import the Math library, you can just say ```cos(34)``` instead of ```Math.cos(34)```. **For this reason, the include must be inside the class or module declaration.** 361 | 362 | 363 | Importing a module in Ruby uses the ```require``` keyword like so: 364 | 365 | ```ruby 366 | require 'date' #import the date module. Note how the name is surrounded by quotes. 367 | Date.today # date.today 368 | ``` 369 | 370 | Unlike with ```require```, importing a module with ```include``` means the module must **NOT** be wrapped as a string. It also must be imported from within a module or class. 371 | 372 | ```ruby 373 | class Foo 374 | include Math 375 | def cosine(radians) 376 | cos(radians) #Look Ma! No Namespace prefix for the cos()! 377 | end 378 | end 379 | ``` 380 | 381 | ### Mixins 382 | 383 | #### Mixin with ```include``` 384 | When you use ```include```, the module's methods act as if they are now part of the **instance of the** class/module and this has far reaching effects. 385 | 386 | See below: 387 | 388 | ```ruby 389 | module Gun 390 | def shoot(name) 391 | puts "Shot #{name}" 392 | end 393 | end 394 | 395 | class Man 396 | include Gun 397 | end 398 | 399 | joe = Man.new 400 | joe.shoot("Pete") # => 'Shot Pete' 401 | ``` 402 | 403 | As you can see, the Man class was essentially augmented with the module's functions. This is called a **mixin**. 404 | 405 | Let's continue: 406 | 407 | ```ruby 408 | class BadMan < Man; end 409 | 410 | gavrillo = BadMan.new 411 | gavrillo.shoot("Franz Ferdinand") # => 'Shot Franz Ferdinand' 412 | ``` 413 | 414 | This is how single inheritence can be side stepped. Classes can be mixed in and inherited and the child classes would then inherit the constants and methods of the module even if they aren't explicitely inclduing it themselves. 415 | 416 | #### Mixin with ```extend``` 417 | The mixin with ```extend``` works exactly the same way as the [mixin with include](#mixins-with-include) but it works on a **Class level**. 418 | 419 | See example below (thanks Codeacademy for the example): 420 | 421 | ```ruby 422 | module ThePresent 423 | def now 424 | puts "It's #{Time.new.hour > 12 ? Time.new.hour - 12 : Time.new.hour}:#{Time.new.min} #{Time.new.hour > 12 ? 'PM' : 'AM'} (GMT)." 425 | end 426 | end 427 | 428 | class TheHereAnd 429 | extend ThePresent 430 | end 431 | 432 | TheHereAnd.now 433 | ``` 434 | 435 | Note how the class itself can call ```now``` and not just instances of the class. 436 | 437 | ## Constants 438 | 439 | In Ruby, any reference that begins with an uppercase letter whether its a variable, a class name or module name is a constant. 440 | 441 | Unlike other languages, in Ruby, constants can have their values set after they have already been initialized. 442 | 443 | A Ruby constant is different from a regular variable in only 1 way: *Scope*. 444 | 445 | See the following: 446 | 447 | ```ruby 448 | SomeConstant = 'HELLO' # One constant 449 | module Foo 450 | SomeConstant = 'hello' # another different constant due to a different scope. 451 | class Bar 452 | SomeConstant = 'bye' # another different constant 453 | end 454 | end 455 | ``` 456 | 457 | To refer to a constant in one particular scope, the `::` is used. From the previous code example: 458 | 459 | ```ruby 460 | SomeConstant # => HELLO 461 | ::SomeConstant # The "::" prefix can be used to refer to the root scope. 462 | # => HELLO 463 | Foo::SomeConstant # => hello 464 | Foo::Bar::SomeConstant # => bye 465 | ``` 466 | 467 | ### Accessing constants and nesting during runtime 468 | 469 | If constants of a specific module need to be accessed, then the `constants` keyword is used: 470 | 471 | ```ruby 472 | module Foo 473 | SomeConstant = 'hello' 474 | end 475 | 476 | Foo.constants # => [:SomeConstant] 477 | ``` 478 | 479 | To find the path of a specific module, the `Module.nesting` can be used: 480 | 481 | ```ruby 482 | module Foo 483 | class Bar 484 | module Baz 485 | Module.nesting # => [Foo::Bar::Baz, Foo::Bar, Foo] 486 | end 487 | end 488 | end 489 | ``` 490 | 491 | --------------------------------------------------------------------------------