Learn Ruby and rails from rails guru
Pankaj Bhageria
This user hasn't shared any biographical information
Homepage: http://railsguru.org
Posts by Pankaj Bhageria
jQuery Event Handling
Jul 22nd
This is a continuation of the following series of posts
- http://railsguru.org/2010/08/introduction-to-jquery/
- http://railsguru.org/2010/09/getting-started-with-jquery/
Till now we have learnt how to
- Select elements from an html page.
- Perform operations on them
- read/write their attributes.
- read/write their contents.
Till now we have been performing these operations in firebug.
To actually use them, you would need to bind them to some events.
Like
- On clicking a link show a div
- On checking a check box, show a text box.
- On selecting “Others” from a drop down(select box) then show a text field.
To understand the binding of functions to events, you need to first understand some JavaScript concepts.
Javascript Prereqisites
A function is just another variable
{
}
is same as
}
Calling a function through a variable
}
to call the function append parenthesis in the end.
In case the function accepts any parameters, then
to call the function append parenthesis in the end, and pass the parameters.
Passing a function to another function
Let us consider a function named “run_ten_times” which accepts a function ‘x’ as a parameter, and calls ‘x’ 10 times.
{
for(var i = 0; i < 10; i ++ )
{
x();
}
}
Calling with a variable
a) Define the function.
{
alert("call by variable");
}
#or
var f1 = function ()
{
alert("call by variable");
}
b) Pass ‘x’ to the function run_ten_times()
Calling with a anonymous function
Define and pass the value at the same time.
(Also see this http://helephant.com/2008/08/javascript-anonymous-functions/)
Here we will not assign the argument function to a variable, but define it directly at the place where we pass it.
function(){
alert("from anonymous function");
}
)
Here the function which is passed as the argument is called an anonymous function as we have not assigned it a name i.e we have not assigned it to a variable.
The receiving function treats both of them(anonymous and named function) as same. It is just that the anonymous function looks more complex and difficult to understand. It is one of the concepts that makes understanding jQuery complex for beginners.
So we have seen how functions are just like other variables in JavaScript. This can also be said as functions are first class objects in Javascript.
Now we know enough javascript, which is required to understand the further sections. So lets get back to jQuery events.
Binding an event to a function
Let us take an example.
A div should hide when a link is clicked.
Consider the following html for the same.
<div id="target_div">
Click the above link to hide me.!
</div>
Create an html page with this code and open it in firefox.
We need to hide the div on clicking the link.
So we need to bind the click event on the link.
jQuery provides a function click(event_handler), for the same
click(event_handler)
This binds the function “event_handler” to the click event of all the elements in the jQuery object.
ie whenever the element(on which the click event is binded) is clicked then the function event_handler will be called.
So lets use this click function to accomplish our task.
We need to do 3 things to bind an event to an element
1) Select the element.
2) Define the handler.
3) Bing the handler on the event of the element.
For our example.
1) select the link which on click will hide the div.
2) define a function “hide_div” which hides the div.
3) bind the function “hide_div” to the click event of the selected link.
{
$("#target_div").hide();
}
$("#hide_link").click(hide_div);
With the html page you create in the above section open in firefox, write this code in firebug(do not write the code directly in html page yet!). As this is multi line code, you would need to click a small up arrow on the extreme right of the place where you type your commands in fire bug. On clicking the arrow, the input line of console opens up into a right panel. Here you can type multiline codes and execute them by clicking run at the bottom of the command window. Whenever you modify the code, you may need to refresh the page(unless you want to retain the changes) before running it, as the previous code may have made certain changes on the page.
Write the above code in the firebug, and click run. Now go and click the link and see it hiding
.
Now Refresh the page and use the anonymous function technique to do the same.
{
$("#target_div").hide();
}
);
The code has become shorter, but more complex. Once you get used to it it will be fine.
Click “Run” and go ahead and click the hide link. Once again your div should hide.
A small trick.
- Refresh the page, and in the above code, modify the line to hide the div to following.
-
$("#target_div").hide(3000);
Execute the code(click ‘Run’) and then test the hide link. Do you see the div hiding slowly. Yes it has taken 3 seconds(3000 milliseconds) to hide. So the hide function optionally accepts a delay in milliseconds.
Same applies for the show() function.
Now paste the above code in the html page in the head section and reload.
$("#hide_link").click(function()
{
$("#target_div").hide();
}
);
</script>
Refresh the page and test.
The div will not hide!!
Why?
Because the binding happens before the DOM is ready/loaded. In simple terms, when the code to bind the event runs the element is not present on the page. The element comes on the page, after the code has finished running. So the event is not bound.
This can be more clear with the following analogy.
Consider event binding as tying thread to the element and the event handler.
While binding the event
1) We first select the element using selectors.
2) Tie a separate thread to each element selected and the event_handler function.
After this happens, if new elements of the same type(as already bound to the event) are added to the page, then there is no thread tied to the element, so the event does not fire for that element.
In this case, when the code executed, there were no elements on the page, so no elements were selected and no thread was tied.
For this we need to run the code once the page is loaded fully or when the DOM is ready.
jQuery provides a ready event on the document object for the same.
$(document).ready()
Following is the code to bind the ready event.
{
$("#target_div").hide();
}
function ready_handler()
{
$("#hide_link").click(hide_div);
}
$(document).ready(ready_handler);
The above code should be clear, other than the following line.
What this line does is binds the function ready_handler with the ready event of the document.
So the function ready_handler is called when the document is ready ie when the document has finished loading. The function ready_handler binds the function hide_div to the click event of the link #hide_link.
So when the link #hide_link is clicked the function hid_div is called which hides the div #target_div
Coming back to the line
Understanding document.ready
Till now we have seen that the $ accepts a selector string and returns the jQuery object/wrapped set.
But there are more ways to use the jQuery function.
We can also pass a DOM object to the $ function, and it returns the jQuery object for that object.
What is a DOM object
DOM object is the object exposed by the DOM.
Some examples of DOM objects.
1) document is the DOM object
on Firebug
>$(document)
2) document.getElementById(“#hide_link”) returns an object for the link.
do this on firebug
<a id="hide_link>
>var jq_a = $(a)
Object { 0=, more...}
> a.hide()
TypeError: a.hide is not a function { message="a.hide is not a function", more...}
> jq_a.hide()
We first found the DOM object for the link a#hide_link by using the dom method getElementById.
Then we found the corresponding jQuery object by passing the reference to the $ function.
Now we tried calling jQuery hide() function on both the objects. We found that the hide function can only be called via the jQuery object. This not only applies to the hide() function of jQuery but to all the functions.
To summarize:
1) DOM object is the object exposed by the DOM.
2) We need to have a jQuery object in order to call the jQuery functions.
3) To get a jQuery object from a Dom object, pass the DOM object to the $ function, and the return value is the jQuery object.
Coming back to our example, let us see the same example using anonymous functions.
Anonoymous documen.ready handler
$("#hide_div").click(hide_div);
});
function hide_div()
{
$("#target_div").hide();
}
Here instead of defining a separate function ready_handler, we pass an anonymous function to the ready event of the document.
Taking this one step further, we make the hide_div handler also anonymous.
$("#hide_div").click(function(){
$("#target_div").hide();
});
});
The “Only document.ready function anonymous” method is more readable than making all the function anonymous. From now onwards we will follow the method of keeping the document.ready anonymous.
Show div example
Let us add another link to the above example to show the div.
Following is the html after adding the link
We would need to bind a handler to the show link which will show the div.
Following would be the JavaScript code for the same.
$("#hide_div").click(hide_div);
$("#show_div").click(show_div);
});
function hide_div()
{
$("#target_div").hide();
}
function show_div()
{
$("#target_div").show();
}
The code is self explanatory.
Add a toggle link.
In the above example,we see that the hide link is only used when the div is visible and vice versa. We can make the same link do both hide and show. jQuery provides a method called toggle for the same. It does a show operation on hidden elements and hide operation on visible elements.
Following will be the code for the same
$("#toggle_div").click(toggle_div);
});
function toggle_div()
{
$("#target_div").toggle();
}
<a id="toggle_link">Hide/Show</a>
<div id="target_div">
Click the above link to hide me.!
</div>
Now there is only one link on click of which toggle is called.
Lets take another example
Show/hide a text box dependent on the value of dropdown.
We have a drop down to select occupation and an others option. on selecting other, the text field should be shown.
Here we need to show/hide the text box when the value of the select box changes. We can do this on the change event. jQuery provides a change() method for binding the change event.
When the value of the select box changes, we will read the value of the select box and show hide the the text field depending on the selected value.
We have seen how to read the attribute of any html tag. To read the value of a text field we could have directly used the method attr(“value”), which would have returned the text typed in the text field. You can try this out in the firebug. Similarly you could have changed the value of the textfield by doing
attr(“value”, text).
The case of a select tag is more complex. Here we cannot directly use the attr() method as the selected value is an attribute of the selected child.
jQuery provides a val() method for this.
val() returns the value of the form field ie textfield/ checkbox/ select tag/ radio button etc.
val(value) sets the value of the form field.
So to read the value of the select box you need to do
Please note that the value of the selected option is not the displayed value but the it is the value of the attribute “value” of the selected option
So if the option “Other” is selected.
We see that the value attribute of “Others” option has a blank value. So we need to test for a blank value, to test if the option selected is “Others”.
Lets go ahead and write the code.
$("#select_fruit").change(show_hide_other);
})
function show_hide_other()
{
var selected_fruit = $("#select_fruit").val();
if(selected_fruit == "")
{
$("#other_fruit").show();
}
else
{
$("#other_fruit").hide();
}
}
On the change event of the dropdown, the handler/function show_hide_other() is called.
This function will show/hide the textbox depending upon the value of the dropdown.
Go ahead and test this code. So the select box is showing and hiding as you would expect. There is only problem. On page load, the text field is visible, but the select box does not have fruits selected.
To fix this hide the text field on page load.
$("#select_fruit").change(show_hide_other);
$("#other_fruit").hide();
})
This seems to work fine. But it has a problem. We are assuming that on page load the value selected in the select box will not be “Others”. This may be true for a static html page( firefox caches the value selected, so on refresh the selected value will not change, so in case of static html page also it is a problem). For a web application, the value of the drop down may be anything including “Others”, as it will come from database and it may not be the first value of the dropdown.
There are multiple ways we can fix this issue.
1) Duplicate the logic of function show_hide_other in document.ready.
$("#select_fruit").change(show_hide_other);
if($("#select_fruit").val() == "")
{
$("#other_fruit").show();
}
else
{
$("#other_fruit").hide();
}
})
Note that the show_hide_other function is still there, tough have not show it above.
This is a very bad technique, as it involves code duplication, please do not follow this. I have included it here so that you know what not to do.
2) call the handler function in document.ready.
$("#select_fruit").change(show_hide_other);
show_hide_other();
})
This is much better than the first option as there is no repetition of code. There is a better option though
3) Trigger the change event after binding the event.
$("#select_fruit").change(show_hide_other);
$("#select_fruit").change();
})
jQuery provides methods to trigger the event. In general if you do not pass a parameter to the function which binds the event, it becomes a function which will trigger that event.
The above technique is very useful.
We can make a general rule for this.
Whenever the state of the page changes(certain elements are shown/hidden), then to ensure that the initial state of the page is maintained , after binding, the events which change the state, trigger the event. This will initialize the state.
Summary
We have learnt The following things in this post
We started with Javascript Basics.
- Different ways of defining and calling a function.
- Passing a function as a parameter to another function.
- Anonymous Functions.
- Functions as first class objects.
Then we moved on to events in jQuery.
- Binding an event to a function
- Event Handler
- $(document).ready
- Need of the $(document).ready function
- Binding handlers to $(document).ready by passing named and anonymous functions.
- The string concept of event binding.
- Example to show/hide/toggle a div on clicking a link
- Example to show/hide a text box depending upon the value of a dropdown.
- The generic solution to maintain page state.
Share
Getting Started with Jquery
Sep 4th
Getting started
Tools Required
Editor
Firefox + firebug(recommended)
Prerequisites
Basics of html, css, javascript.
To learn basics of html,css then please visit http://www.htmldog.com/
To learn basics of javascript visit http://www.w3schools.com/js/default.asp
To proceed with the tutorial you should be knowing how to use firebug. We will be working on firebug JavaScript console to get started with jQuery. Get some hands on firebug before moving ahead.
For getting started with firebug watch this video.
Downloading jQuery
http://docs.jquery.com/Downloading_jQuery
Minified version: http://code.jquery.com/jquery-1.4.2.min.js
Source version: http://code.jquery.com/jquery-1.4.2.js
Including jQuery file in your html file
Including it directly from the internet( works fine if internet connection is present) in the head section of your html file.
Downloading and including it
path is
- relative path to your html file if you are directly accessing it as a local file.
- relative path to your website if you are accessing it from a website(hosted or local).
if you are accessing the html file directly and saving it to same folder as you html file then
Conventions followed in the tutorial
whatever comes after “>” is the command to be typed in the firebug.
The line after the commnad is the output.
ex
> var a = 1
1
Here “var a = 1″ is the command you type out on console.
and “1″ is the output of the command.
| Notation | Meaning |
|---|---|
| div#special | A div element with id special |
| div.selected | A div element with class selected |
| div#special.selected | A div element with id special and class selected |
Note
An element can have multiple classes
An element can have only one id.
Getting Started
Create the page(source code given below) and open it in your web browser. Open your firebug and get started. This will be the page you will be using to test the examples for the rest of this post.
Following is the source code for the page.
<HTML>
<HEAD>
<TITLE>Getting started with jQuery</TITLE>
<script src="http://code.jquery.com/jquery-1.4.2.min.js" type="text/javascript"></script>
</HEAD>
<BODY>
<h1>Getting started with jQuery</h1>
<div class="selected" id="special">
<a></a>
<p >
This is 1st paragraph.
<a class="details more"></a>
</p>
<p>
This is 2nd paragraph.
</p>
<p>
This is 3rd paragraph.
</p>
</div>
<div>
<a></a>
</div>
<div>
<a></a>
</div>
-------------------
<ul>
Fruits
<li>
Apple
</li>
<li>
Mango
</li>
<li>
Banana
</li>
</ul>
<table>
<tr>
<th>First Name</th>
<th>Last Name</th>
</tr>
<tr class="selected" id="user_1">
<td>Pankaj</td>
<td>Bhageria</td>
</tr>
<tr class="selected" id="user_1">
<td>John</td>
<td>Resig</td>
</tr>
</table>
</BODY>
</HTML>
What can be done in jquery
Let us see what can be done using jQuery
- Modifying HTML page based on some events
- Hide/show parts of page on some events like clicking a link/checking a checkbox etc
- On clicking a check box check all the checkboxes
- Client Side Validations
- Animation
- Ajax interactions
For doing all of the above things, you need to do the following
- Select the element(s) from the document on which you would do some operation.
- Perform the operation. Operation can be showing/hiding, reading the contents, changing the contents, attaching event to the element etc.
Selecting element(s) on the page
To select element(s) on the page we use the $ or the jQuery function. $ function is the core of jQuery.
$ or the jQuery function
For selecting an element from the page pass a selector string to the $ function.
The elements which match the selector string are returned by the $ function. The output of the $ function
is called the jQuery object or the wrapped set.
The jQuery object/wrapped set is an array like structure which contains all the elements which matches the selector. The jQuery object exposes several functions which help in easy read/write operations on the dom.
We will see more on about jQuery object later.
Let us study selectors first.
Selectors
If you know CSS selectors ,you already know selectors, they are the same
.
There are different types of selectors as given below.
-
Tag Name Selector “tag_name”
To select elements with their names(element name) use the element name as the selector.
ex to select all divs on the page(refer the example page)
>$("div")
[div#special.selected, div, div]The string passed to the $ function is the selector. The return value which you see ie an array like structure is the jQuery object/wrapped set. The jQuery object contains 3 divs. 1st one has an id special and class selected. Other 2 do not have any id or class.
ex to select all the the links on the page
>$("a")
[a, a.details, a, a] -
Class selector: “.class_name”
ex to select all the elements having class “selected”
>$(".selected")
[div#special.selected, tr#user_1.selected]2 elements are having class selected a div and a row.
-
Id Selector: “#id”
ex to select the element with id “special”
>$("#special")
[div#special.selected] -
AND operation.
Till now we studied 3 basic selectors. There may be cases when you need to select elements which satisfy more than one selector.
So as a general rule to select an element which should satisfy selector A and selector B you need to concatenate both the of the selectors as AB
ex
To select div which have class selected
selector A = “div”
selector B = “.selected”
AB = “div.selected”>$("div.selected")
[div#special.selected]it can be extended to more selectors as ABCD and so on
where A, B, C D are different selectors.more examples
To select a div with id special
A = “div”
B = “#special”
AB = “div#special”>$("div#special")
[div#special.selected]To select a row with class “selected” and id “user_1″
A = “tr”
B = “.selected”
C = “#user_1″ABC = “tr.selected#user_1″
>$("tr.selected#user_1")
[tr#user_1.selected]Please note that the above 2 examples, we have used “id” as one part of the selectors.
Practically this would not be very useful, as the id of an element is unique. So you could have just used the id to select that element. Using the tag name and the class name selectors in addition to the id selector only slows down the operation.To select a link with classes details and more
A = “a”
B = “.details”
C = “.more”ABC = “a.details.more”
>$("a.details.more")
[a.details]Fire bug shows only first class in the output, but if you explore the html/click on the selected link,you will see that the link selected is having a class “more”.
-
OR operation
Many times we want to select elements which either satisfy selector A or satisfy selector B
To do an OR operation concatenate all the selectors separated by a comma “,”To select all divs and paragraphs on the page
A = “div”
B = “p”
A, B = “div, p”> $("div, p")
[div#special.selected, p, p, p, div, div]To select all divs with class selected and all paragraphs on the page
A1 = “div”
B1 = “.selected”
C = A1B1 = “div.selected”A2 = “p”
D = A2 = “p”
C, D = “div.selected, p”
> $("div.selected, p")
[div#special.selected, p, p, p]
Now that we know how to select elements from the jQuery page, now we will see how to do operations on them.
Performing operations on element(s)
HTML is composed of multiple nested tags
Each tag has the following parts
Contents(text/Children ie sub tags)
ex
The operations which can be performed on the above HTML can be divided in 2 types
Read operations
- Read the contents of the tag
- Read the value of a particular attribute
Write operations
- Modify the contents of the tag
- Change the value of an attribute
- Add an attribute to element
- Remove an attribute
- Remove the element
- hide the element
- show the element
jQuery provides functions to do above operations on the dom. These function can be called on the jQuery object(wrapped set).
3 Important points to be noted
- To read the contents of all the elements in the jQuery object, you would need to loop on the the object like an array. We will see how to do this in the next post.
READING
html()
Returns the contents/inner html of the first element in the jQuery object.
Select a p tag and display its html.
"This is 1st paragraph. <a class="details more"></a> "
Return the value of the attribute “attr_name” for the first element in the jQuery object.
Read the id of the div
>"special"
WRITING
html(new_content)
Replaces the innter html/content for all the elements in the jQuery Object with new_content.
ex. Modify the html of all paragraghs
[p, p, p]
Note the return value is the jQuery object itself.
ex. Modifiy the title of the header
[h1]
attr(attr_name,new_value)
Sets the value of the attribute with name “attr_name” to new_value, for all the elements in the jQuery object. If the attribute is not present, it is added.
[table]
Note the border of the table appears. Here there was no attribute existing, so the attribute was created.
removeAttr(attr_name)
Removes the attribute with name “attr_name” for all the elements in the jQuery object.
ex
>[div#special, div, div]
Note in the output that there are no classes present. You can also traverse the html and check the page.
Refresh the page after this so that the other examples work.
remove()
Removes the element present in the jQuery object.
>[div,div,div]
There are two important functions, which donot
hide()
Hides all the elements(which are visible) in the jQuery object. To hide the element it add a style “display:none;” to the element.
>[div,div,div]
This hides all the divs on the page.
show()
Shows all the elements(which are hidden) in the jQuery object. To show the element it removes the style “display:none;” from the element.
>[div,div,div]
This shows all the hidden divs on the page.
We have covered basic of selecting elements and doing some operations on them. Rest we will see in next post.
Summary
Selectors
| Type | Expression |
|---|---|
| Tag | tag_name |
| Class | .class_name |
| Id | #id |
| AND operation | AB |
| OR operation | A, B |
Read/Write operations
| Function | Description |
|---|---|
| html(), html(new_content) | Read/Write content/inner html |
| attr(attr_name), attr(attr_name,new_value) | Read/Write attribute |
| removeAttr(attr_name) | Reomve attribute |
| remove() | Reomve element |
| show()/hide() | Show/Hide the element |
Share
Introduction to jQuery
Aug 14th
What is jQuery
Jquery is a javascript library which has made my life a lot easier.
From jquery.com
jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript.
Why jQuery
- Working will plain javascript is very cumbersome.
- You do not need to worry about browser compatibility if you use jQuery.
- There are many plugins available, so almost every time you need some functionality, you will find a plugin for it.
- There is huge community support.
- Its very easy.
What can be done with jQuery:
-
-
Modifying HTML page based on some events
- Hide/show parts of page on some events like clicking a link/checking a checkbox etc
- On clicking a check box check all the checkboxes
- Client Side Validations
- Animation
- Ajax interactions
And lots more, see below for some examples
Show me some examples
Jquery UI Plugins
Animation and Effects
Third party plugins
-
-
Client Side validations.
- jquery validator
- Valid8
- Tree
- Grids
- jQuery spread sheet
-
-
Graphs
- jqPlot
- Flot
- Google charts with jquery
-
- Superfish.
- Navigation
tutorial - Dropdown Menu The tutorial
- More.
Menus
-
-
Image popup/Light box
- Light Box
- Image Fly Out
- Replacement for alert, prompt, and confirm
- Masked Inputs
- Auto grow text area
- Input Hints
Many more are there, the list will be very long if I add every thing. And as I write this or as you read this, some one, some where is building another plugin
.
How to learn jQuery
You are at the right place
. Wait for more posts.
Till then you can explore http://docs.jquery.com/Tutorials
Share
Quick Start Ruby -5, Inheritance
May 22nd
This is a continuation of the following series of posts
Quick Ruby Tutorials-1
Quick Ruby Tutorials-2
Quick Ruby Tutorials-3
Quick Ruby Tutorials-4, Decision Making
def self.x
puts “I m a class method defined in class A”
end
def y
puts “I m an instance method defined in class A”
end
end
class B
end
b = B.new
B.x # no method error
b.y # no method error
The errors are obvious as we the methods x and y do not exist in class B.
end
b = B.new
B.x # “I m a class method defined in class A”
b.y # “I m an instance method defined in class A”
In the defination of class B, the part “< A" tells ruby that class B is inheriting from class A.
When class B inherits from class A, all the properties(methods, instance and class variables) in class A are available to class B
Syntax is as follows
end
Let us take another example
attr_accessor :sound
def initialize(s)
puts "in initialize of Animal class"
self.sound = s
end
def make_sound
puts self.sound + “ “ + self.sound
end
end
Let us define a class dog which inherits from animal
end
d = Dog.new(“bhow”) #in initialize of Animal class
d.make_sound # “bhow bhow”
Here we need to pass the sound of dog, every time a new dog is born.
But dog will always make the sound “bhow”. We need not pass the value for sound every time we create an instance of the Dog. For this we would need to override the initialize method in the Dog class as shown.
def initialize
puts "in initialize of Dog class"
self.sound = “bhow”
end
end
d = Dog.new #in initialize of Dog class
d.make_sound # “bhow bhow”
Note that in the above Dog class we have overridden the initialize method of the animal class(base class).
This overrides the initialize method of the base class(irrespective of the number of arguments).
So when the dog object is created, the initialize method of the Animal class is not executed.
There will be many occurrences when we only want to slightly modify the behaviour of the base class method, like
- add some more processing to the output of the method.
- call the method with some specific parameters to the method.
For this we need to access the base class(Animal) method in the derived class(Dog) method.
We can do this with the keyword “super”.
def initialize
puts "in initialize of Dog class"
super(“bhow”)
end
end
d = Dog.new
#in initialize of Dog class
#in initialize of Animal class
d.make_sound # bhow bhow
As we see first the initialize method in the Dog is called, which calls the initialize method in the Animal class with parameter “bhow”
Let us consider another use of “super”. We want the dog to bark 4 times when the make sound is called, unlike the make_sound method of the animal class which makes sound 2 times.
def initialize
puts "in initialize of Dog class"
super(“bhow”)
end
def make_sound
super
super
end
end
d = Dog.new
#in initialize of Dog class
#in initialize of Animal class
d.make_sound # bhow bhwo bhow bhow
Above we called super 2 times in the make_sound function. Due to this the sound is printed 4 times.
Let us take another example for overriding.
def to_s
"the string version of this array is: " + super
end
end
x = MyArray.new(['a','b','c'])
x.to_s # the string version of this array is: abc
In the above example we saw how we processed the output of the base class method, in the child class method.
Share
Quick Ruby Tutorials-4, Decision Making
Apr 17th
This is a continuation of the following series of posts
Quick Ruby Tutorials-1
Quick Ruby Tutorials-2
Quick Ruby Tutorials-3
Currently our Dog eats, anything and everything given to it. Lets give our dog some choice.
if you give the dog chocolate, it should ask for some more, otherwise it should behave normally.
def eat(food="bone")
puts "I am eating #{food}"
if (food == "chocoloate") # parnthesis are optional
puts "Give me some more"
end
end
end
d = Dog.new
d.eat("bread") # I am eating bread
d.eat("chocolate")
#I am eating chocolate
#Give me some more.
In the above code, we are using the If statement to make decisions ie to execute a certain part of code only if a particular condition is satisfied.
Syntax of if statement is as follows
# code1 which executes when expression1 is true
elsif (<expression2>)
# code2 which executes when expression2 is true and expression1 is false
elsif (<expression3>)
# code3 which executes when expression3 is true and expression 1 & 2 are false
else
#code 4 which executes when expression 1&2&3 are false.
end
The expression can be any ruby statement. If the output of the expression is true/not nil then the corresponding code is executed other wise it moves to the next elsif/else
So above
if expression1 one evaluates to true then code 1 is executed
if expression1 is false and expression2 is true then code2 is executed
…
if no expression is evaluated to true then the code in the else block is executed.
The elsif and the else block are optional.
There can be multiple elsif blocks but only one else block.
Else block does not accept any argument.
The else block is the last block in the if statment. After that there can be no further elsif/else
The if statement ends with a “end” irrespective of then number of elsif.
There can be different forms of if statements given below
#code which is executed if expression is true
end
A short form for this is this is
This is called a one liner if statement
Example:
puts "Drive Slow" if speed > 60 # Drive Slow
time = "afternoon"
puts "Good Morning" if time == "morning" #
The one liner if statements are very useful when there is no elsif/else part and the body of the if is just a single line of ruby code.
#code1
else
#code2
end
Here one of the parts code1 or code2 is always executed.
#code1
elsif expression2
#code2
end
Here if expression1 is true then code1 is executed, if expression1 is false but expression2 is true then code2 is executed. If both are false then nothing is executed.
More about expressions.
Again: The body of the if statement is executed if the expression evaluates to true or a non nil value which is not false.
Or
The body of the if statement is not executed if the expression evaluates to false or nil.
We will demonstrated this using one liner if statement.
In the body of the one liner if, we will keep a puts statement.
So if there is any output on screen, then we know that the expression has been satisfied.
puts "this will not print" if 2 > 3 #
puts "2 is less than 3" if 2 < 3 # 2 is less than 3
puts "this will not print" if 3 < 2 #
puts "3 which is a non nil object evaluates to true" if 3 #3 which is a non nil object evaluates to true
puts "true" if true # true
puts "this will not print" if false #
puts "this will not print" if nil
puts "3 is equal to 3" if 3 == 3 # 3 is equal to 3
puts "x is equal to 3" if x = 3 # x is equal to 3
puts "3 is not equal to 2" if 3 != 2 #3 is not equal to 2
Above we have used constants in the expression. This was to keep things simple.
We can use variables, method calls, and their combination in an expression.
Every expression can be a combination of objects, methods calls, operators.
2 important things to note from the above example are:
we can check whether an variable/object x exists by doing
The if statement is only executed when the object x exists ie when its value is not nil.
Second thing is, in case of an assignment operation, the output of the expression is the value which is assigned.
So if we do
x = y
then the output of this expression is y.
Coming back to the dog example:
Lets modify our Dog class so that,
if you give it “banana” to eat, the dog should not eat. It should ask for something else.
def eat(food="bone")
if food == "banana"
puts "I do not eat banana, give me something else"
else
puts "I am eating #{food}"
end
if food == "chocolate"
puts "Give me some more"
end
end
end
d = Dog.new
d.eat("banana") #I do not eat banana, give me something else
d.eat("bread") # I am eating bread
d.eat("chocolate")
#I am eating chocolate
#Give me some more.
Note that the condition if food == chocolate is being tested for even if the food is banana. We should move that loop into the body of if. This is called nested if ie an if inside if.
def eat(food="bone")
if food == "banana"
puts "I do not eat banana, give me something else"
else
puts "I am eating #{food}"
if food == "chocolate"
puts "Give me some more"
end
end
end
end
d = Dog.new
d.eat("banana") #I do not eat banana, give me something else
d.eat("bread") # I am eating bread
d.eat("chocolate")
#I am eating chocolate
#Give me some more.
It would much cleaner if we add a one liner if condition here, that makes it much more readable
def eat(food="bone")
if food == "banana"
puts "I do not eat banana, give me something else"
else
puts "I am eating #{food}"
puts "Give me some more" if food == "chocolate"
end
end
end
Lets add some more conditions, If you give it bone then it should say “great, u made my day”.
if you give it “sandwich” then it should say “mmmmmmmmmmmm, I have never eaten like this one before”
if you give it milk, then it should tell “Thankyou, I will become a strong dog after drinking milk”
Previous conditions also apply. It should not say “I am eating xyz” along with other statements as above.
def eat(food="bone")
if food == "banana"
puts "I do not eat banana, give me something else"
elsif food == "chocoloate"
puts "Give me some more"
elsif food == "bone"
puts "Great, you made my day"
elsif food == "sandwich"
puts "mmmmmmmmm I have never eaten like this one before"
elsif food == "milk"
puts "Thank you, I will become a strong dog after drinking milk"
else
puts "I am eating #{food}"
end
end
end
We replace this by a case statement.
Case statement is an alternative for a if statement.
If the output of a calculation depends on a value of an object, and the number of cases are high then it can become very cumbersome if you use if statement. It is much easier doing the same using a case statement.
Syntax for the case statement is :
when match_1 then result_1
when match_2 then result_2
when match_3 then result_3
when match_4 then result_4
else result_5
end
</end>
<code lang="ruby">
class Dog
def eat(food="bone")
message = case food
when "banana" then "I do not eat banana, give me something"
when "chocolate" then "Give me some more"
when "bone" then "Great, you made my day"
when "sandwich" then "mmmmmmmmm I have never eaten like this one before"
when "milk" then "Thank you, I will become a strong dog after drinking milk"
else "I am eating #{food}"
end
puts message
end
end
So this looks much cleaner the the code with if statement.
Note how we collected the output of the case statement in the variable message, and then printed the variable. We could have instead printed the value in the case statement it self as done in the if statement.
But this one is better, as if later, instead of printing the message on screen, I just want to return the message, or store it in a file then I would need to just change one line. Instead if we had embedded the puts in the case itself, then we would need to change many lines.
The code which adapts to a change, with lesser lines of changes, in lesser number of files, is a better code.
Let us take a different scenario:
A dog will reject the following items: banana, mango
It will accept the following : biscuit, bread, milk
def eat(food="bone")
if food == "banana" || food == "mango"
puts "I do not eat #{food}, give me something else"
elsif food == "milk" || food == "bread" || food == "biscuit"
puts "thank you for giving me #{food}"
else
puts "Can this be eaten?"
end
end
end
d = Dog.new
d.eat("banana") #I do not eat banana, give me something else.
d.eat("bread") # thank you for giving me bread.
d.eat("ball") # can this be eaten?
Now,if this list of eatables gets very long( the food which dog can eat and once which it cannot), then the program would become very cumbersome.
Let us use some magic of arrays to this.
@@good_food = ["milk", "bread", "biscuit","bone"]
@@bad_food = ["banana", "mango"]
def eat(food="bone")
if @@bad_food.include? food
puts "I do not eat #{food}, give me something else"
elsif @@good_food.include? food
puts "thank you for giving me #{food}"
else
puts "Can this be eaten?"
end
end
end
Here we are defining 2 class variables: @@good_food and @@bad_food. We initialize each of these to an array holding the respective food types.
In the if statement we use a method include?(x) on the array object.
This method returns true if x is present in the array else it returns false.
For a complete list of methods present in the array classs go to: http://ruby-doc.org/core/classes/Array.html
One fine day our dogs realize that global warming is increasing a high rate.
All the scientist dogs get together and do a research on this. They come to a conclusion that the major cause of the global warming is non vegetarianism(http://www.goveg.com/environment.asp).
So they all decide to go veg
Now if you gave our veg dogs a bone or meat to eat, should reject it, telling that stop non veg,stop global warming!.
Let us modify our code to do the same.
@@non_veg_food = ["bone","meat"]
@@good_food = ["milk", "bread", "biscuit"]
@@bad_food = ["banana", "mango"]
def eat(food="bone")
if @@bad_food.include? food
puts "I do not eat #{food}, give me something else"
elsif @@good_food.include? food
puts "thank you for giving me #{food}"
elsif @@non_veg_food.include? food
puts "Go Veg, Stop Global Warming!"
else
puts "Can this be eaten?"
end
end
end
dog = Dog.new
dog.eat("bone") #Go Veg, Stop Global Warming!
So, by now our dogs have become very choosy. You can go ahead and do the following extensions:
- Add methods to the class to modify(add/remove) the food choices of the dog
- Currently all our dogs have the same choices, add functionality so that each dog can have their own choices, they may have some default choices when the are born.
- Let the food habits of a dog develop automatically: When a dog is given a food to eat when it is hungry, add the foo to the good food list, when a dog is given food to eat when it is not well, or when it is not hungry then add the food to bad food list.
These are just ideas, you can try whatever comes to your mind, be creative
.
Share
Quick Ruby Tutorials-3, class and instance methods
Apr 6th
This is a continuation of the following series of posts
Quick Ruby Tutorials-1
Quick Ruby Tutorials-2
In the last post our Dog class had the abilities to eat, sleep, bark, shit etc.
The class definition for Dog class looked like
attr_reader :weight, :height, :color
attr_accessor: name
def initialize(weight = 1,height = 0.5, color = "white")
puts "in initialize"
@weight, @height, @color = weight, height, color
end
def bark
puts "bhow bhow!!!"
end
def eat(food="bone")
puts "I am eating #{food}"
end
def sleep
puts "bbye, I am going to sleep"
end
def shit
puts "aah! now I am hungry again"
end
end
Let us extend it.
Besides other activities like sleeping, barking etc, our dog can now eat food.
On eating the food digestion should start. We make one more method for the same and call it in
the “eat” method.
def eat(food="bone")
puts "I am eating #{food}"
digest_food
end
def digest_food
puts "digesting food"
end
end
d = dog.new
d.eat
# I am eating bone
#digesting food
We could have written the code to digest food in the method “eat”, but we create a separate method called “digest” and call this method in “eat”. This is known as Single Responsibility Principle(SRP), ie each method should have only one responsibility. This helps to maintain the code.In future if the code changes, it is easier to change and test a small method which does only one thing. If we have a method which is big and performs many tasks at the same time then it is difficult to change and maintain the code.
Here we can directly call the digest_food method as shown.
This is not correct, digestion should only start after eating food. If we call digest_food directly then it can start even if the dog has not eaten the food.
Digesting food is an internal function of the dog which is triggered due to some other external event( here eating food).We should not be able to access digest_food method from outside the class.
For this we will make the digest_food method as private.
Private??
What are Private and Public Methods?
Private methods are ones which cannot be accessed/called from outside the class.
The methods which we were defining till now were public methods. By default all the methods of the class are public ie they can be accessed inside/outside the class. To make a method as private we need to add a keyword private as shown below.
private
def digest_food
end
def another_method
end
end
d = Dog.new
d.digest_food #error: private method digest food called
d.another_method #error: private method another_method called
As seen above, all the methods defined after the keyword private are private methods.
So our class definition looks like.
def eat(food="bone")
puts "I am eating #{food}"
digest_food
end
private
def digest_food
puts "digesting food"
end
end
d = dog.new
d.digest_method #error: private method another_method called
What are Class methods and Instance Methods?
Whatever methods we were defining till now were instance methods. Like bark, eat, digest_food etc.
We called these methods with respect to the instance/object like.
dog.bark
As these methods are related to an instance of the class they are called instance methods.
We cannot call instance method with respect to the class.
dog.weight #works
Dog.weight #error: NoMethod error
Class methods are ones which are called with respect to the class.
We have already come across a class method “new”. We don’t need to define “new” as Ruby gives this method for free with every class
.
We do Dog.new, we cannot do dog.new.
Class variables and instance variables
Instance variables are variables which are linked to the instance/object of the class
Instance variables as we have seen start with @ sign. There is a separate copy of the instance variable for each instance. They are accessible within a class in all the instance methods. They are not accessible outside a class. They are the ones responsible to store the data for an instance/object.
Class variables are once which store the data at class level.
Only one copy of the class variable is created for a class.
Class variables can be accessed in class as well as instance method.
There is a separate copy of instance variable for for every instance, but there is only one copy class variable.
Let us use a class variable to keep the count of number of dogs born.
@@population
end
#NameError: uninitialized class variable @@population in Dog
Above we defined a class variable population. Class variables are defined by adding a “@@”" before the variable name. But we need to initialize a class variable when it is being defined.
@@population = 0
end
We will increment the count of population after each dog is born. We can do this in the initialize method. We will also add a class method to access the value of the class variable.
@@population = 0
def initialize
@@population += 1
end
def self.population
return @@population
end
end
puts Dog.population # 0
d1 = Dog.new
puts Dog.population # 1
d1 = Dog.new
puts Dog.population # 1
d2 = Dog.new
puts Dog.population # 2
d3 = Dog.new
puts Dog.population # 3
Note how the class method is defined. A extra “self.” is added in front of the method name.
Let us try accessing the object_id(it is unique for every object) of the variable @@population in a class method and instance method.
@@population = 0
def initialize
@@population ++
end
def self.population
return @@population
end
def population
return @@population
end
def self.class_population_id
return @@population.object_id
end
def instance_population_id
return @@population.object_id
end
end
puts Dog.population # 0
d1 = Dog.new
d2 = Dog.new
d3 = Dog.new
d4 = Dog.new
puts Dog.population # 4
puts d1.instance_population_id # 233323
puts d2.instance_population_id # 233323
puts d3.instance_population_id # 233323
puts d4.instance_population_id # 233323
puts Dog.class_population_id #233323
Above we have done the following
- defined a class and instance method “population” to access the population count.
- defined a class and instance method “class_population_id” and “instance_population_id” to access the object_id of the class variable @@population.
The value of the population count from class and different instances is the same.
The object_id of class_variable @@population is also same from class and instance methods.
This implies that there is only one copy of the class variable.
More examples of a class method could be
- a find method to find the dogs with a particular name
- a count method which will return the total number of dogs
- an average age method which returns the average age of all the dogs which are alive.
Note the above all methods are performing some operation on a set of dogs, not on an individual dog, so they have to be defined as a class method.
We can use instance methods in place of class method, and call it with reference to a particular instance, but it is not the correct way.
def average_weight
puts "This should have been defined as a class method"
end
end
dog = Dog.new
dog.average_weight # This should have been defined as a class method
end
class Dog
def self.average_weight
puts "perfect"
end
end
Dog.average_weight #perfect
We can also use class methods in place of instance methods by passing the instance as a parameter to the method but again that is not the correct way.
def self.weight(dog)
puts "this should have been as instance method as it is related only to a particular dog."
end
end
dog = Dog.new
Dog.weight(dog) #this should have been as instance method as it is related only to a particular dog.
class Dog
def weight
puts "perfect"
end
end
dog = Dog.new
dog.weight #perfect
So In this post we have seen the following
Public And Private methods
Class methods and Instance methods
Class variable and instance variable.
More in the next post.
Share
Quick Ruby Tutorials–2
Mar 24th
This is a continuation of the post Quick Ruby Tutorials -1
In the last post we created a Dog class with the ability to eat and bark. Lets continue to add more features to our class.
Each dog has a name, weight, height, color etc.
Let us add the property “weight” to the Dog class.
For this we need to
1) Store the weight of the dog. For this purpose we use an instance variable. Instance variables are explained later.
2) Add a method to access the weight
3) Add a method to set the weight.
def get_weight
@weight
end
def set_weight(w)
@weight = w
end
end
dog1 = Dog.new
dog1.set_weight(4)
dog1.get_weight #4
dog2 = Dog.new
dog2.get_weight # nil
dog2.set_weight(10)
dog2.get_weight # 10
dog1.get_weight # 4 , weight of dog1 still remains the same
@weight is an instance variable.
Instance variable start with @ sign.
Instance variable can be defined in any instance method. In this case it is defined in set_weight. In get weight it is being accessed, so if get_weight is called before set_weight then it returns a nil.
Note that, changing the weight of dog2 does not effect the weight of dog1.
So there is different copy of instance variable(@weight) for every instance(object). That is why we call it a instance variable.
Let us try accessing our instance variable directly from the object.
dog.@weight #error : syntax error
dog.weight #error: undefined method weight.
So we see that the instance variables are not accessible outside the object. That is the reason we needed to define the the instance methods get_weight and set_weight.
Let us change the names of the methods get_weight and set_weight
def weight
return @weight
end
def weight= new_weight
puts "in method weight="
# @weight is an instance variable. Instance variables start with @ sign.
@weight = weight
end
end
Now we can do
dog.weight #nil
dog.weight= 10 #in method weight=
dog.weight # 10
dog.weight = 20 #in method weight=
dog.weight # 20
Supper!!!
Note the special type of name we have given to method “weight=”.
This method is called when we do weight= or weight =(note the space between “weight” and “=”)
All these are same
dog.weight= 10
dog.weight = 10
Due to these type of methods and the possibility of eliminating parenthesis,
it does not look like we are accessing a method. It is as if we are accessing a variable “weight” inside the dog object.
When the name of the method is of the format method_name=, then ruby expects the method to accept only a single parameter. If you define a method with this format which accepts no parameters or accepts more than one parameters, then there would be a run time error. Try doing this
Hold to your seats tight, you may fly away after reading the next example
attr_accessor :weight
end
dog = Dog.new
dog.weight #nil
dog.weight = 10
dog.weight # 10
How did this happen, with just one line of code in the Dog class??
attr_accessor is a method which generates the getter method(to get the value of the instance variable),
and setter method(to set the value of the instance variable)
:weight: this is a data type symbol in ruby. attr_accessor creates instance variable @weight when it is passed the symbol :weight
More about symbols
Symbol. A symbol is an instance of the class Symbol and is defined by prefixing a colon with an identifier eg :name, :weight, :height etc. .
symbols are data types in ruby which are identified by a unique value property ie you cannot create 2 separate objects with same values.
y = :test
x.object_id # 79858
y.object_id# 79858
a = "test"
b = "test"
a.object_id # 22528570
b.object_id # 22520730
object id for both x and y are same. Object id is an internal id unique to the variable.(the values may be different for you)
object id for the strings are different. ie 2 different objects are created
Symbols are lighter version of their string counter parts
Symbols are much lighter on memory than strings
Most operations which can be performed on strings cannot be done on symbols.
Operations like read a part of the string, append something, delete some part of string etc
symbols with space are defined like :”ruby on rails”
symbols comparison is faster than string comparison as symbol comparison is just one comparison of hash value, but string comparison involves multiple comparison character by character(till there is no match)
When to use a symbol/ when to use a string
Whenever you want to name some thing: some property, key/value of a hash, but no string operations are required , use a symbol.
Getting back to our example,
Here attr_accessor generates for us the 2 mehtods weight and weight=.
We can pass multiple parameters to the attr_accessor method
attr_accessor :weight, :height, :name, :color
end
This creates the setter and getter methods for instance variables @weight, @height, @name and @color. ie it will create weigh,weight=, height and height= etc methods.
So now we can do
d.weight = 10
d.weight #10
d.height = 1
d.height #1
d.name = "Tim"
d.name #"Tim"
d.color = "brown"
d.name # "brown"
Similar to attr_accessor there attr_reader and attr_writer methods.
attr_reader only generate the reader(weight/height).
attr_writer only generates the writer(weight=/height=).
The properties of dog such as height/weight/color etc cannot me modified externally. ie they can only be read, not written. They may get modified due some internal processes. Like the weight and height of the dog grows due to metabolic activities internally.
The instance methods we define should only expose things which are possible.
So modification of weight, height, color should not be possible directly .
Of course we should be able to feed the dog more to increase its weight
attr_reader :weight, :height, :color
attr_accessor :name
end
d = Dog.new
d.weight = 1 # error undefined method weight= for the instance
d.height = 2 # error undefined method height= for the instance
d.color = "brown" # error undefined method color= for the instance
puts d.weight #nil
puts d.height #nil
puts d.color #nil
Not that you would need to comment out the line with errors for the program execution to complete
So it is clear from the above example that only setter/writer methods are not defined, only getter/reader methods are defined
Now our dog is born with no values set for weight, height, color. This is not correct.
Whenever a dog is born(a new object is created), the dog should have some weight, height, color etc.
Lets say when a dog is born it has a weight of 1 kg, height 0.5 feet and color “brown”.
We can use constructors for this purpose, similar to those in C++.
A constructor is a method which is called immediately after a new object is created.
In ruby the constructor method is named “initialize”.
So if you define a method with name “initialize” in your class, it will be called after a object of that class is created.
attr_reader :weight, :height, :color
attr_accessor: name
def initialize
puts "in initialize" #This is used to demonstrate the flow of control
@weight =1
@height = 0.5
@color = "brown"
end
end
dog = Dog.new #in initialize
puts dog.weight # 1
puts dog.height #0.5
dog.color # brown
Let us give our dog a name
puts dog.name # Tim
Note that a dog when born does not have a name. It is given to it later.
That is the reason we did not assign the name in the initialize method.
As per the above code, all the dogs born will have a weight of 1kg, height of 0.5 feet and white color.
If god would have written such a program, then there would be no diversity on this planet. That would be very boring, right?
We should have a option of selecting the weight, height and color. If we can pass these parameters to the new method that would be perfect.
That can be done making our initialize method accept some parameters.
attr_reader :weight, :height, :color
attr_accessor: name
def initialize(weight, height, color)
puts "in initialize"
@weight, @height, @color = weight, height, color #note the parallel assignment of variables
end
end
dog1 = Dog.new(2,1,"white") # in initialize
puts dog1.weight # 2
puts dog1.height # 1
puts dog1.color # white
dog2 = Dog.new # error: wrong number of arguments 0 for 3
It would be great if there are some defaults for the weight, color and heigth.
ie, if the value is not passed then use a default value
attr_reader :weight, :height, :color
attr_accessor: name
def initialize(weight = 1,height = 0.5, color = "brown")
puts "in initialize"
@weight, @height, @color = weight, height, color
end
end
d = Dog.new #in initialize
puts d.weight # 1
puts d.height # 0.5
puts d.color # white
d2 = Dog.new(4,2) #in initialize
puts d2.weight # 4
puts d.height # 2
puts d.color # brown
d3 = Dog.new
puts d2.weight # 1
puts d.height # .5
puts d.color # brown
So now God has lot more flexibility in creating new dogs
Add other abilities to our Dog :sleep, eat, run
attr_reader :weight, :height, :color
attr_accessor: name
def initialize(weight = 1,height = 0.5, color = "white")
puts "in initialize"
@weight, @height, @color = weight, height, color
end
def bark
puts "bhow bhow!!!"
end
def eat(food="bone")
puts "I am eating #{food}"
end
def sleep
puts "bbye, I am going to sleep"
end
def shit
puts "aah! now I am hungry again"
end
end
dog = Dog.new
dog.bark # bhow bhow!!!
dog.eat # I am eating bone
dog.sleep # bbye, I am going to sleep
dog.shit #aah! now I am hungry again
Now our dog can eat, bark, sleep and shit.
Good enough, we will enhance our dog in the next post.
Share
Learn Ruby – Procs, Blocks, Lambda
Mar 12th
Procs and Blocs is the part of Ruby which is not clear to many. This post should help you clear your doubts about Procs and Blocks.
Procs
Like variables hold data, procs hold the code itself.
Procs are first class objects of ruby with class Proc
We define a Proc as follows:
#or
my_proc = Proc.new do
puts “I am a Proc”
end
The first syntax is generally used for one liner Procs and the second one for multiline procs. Though there will be no errors if you do the other way, it is a good convention to follow.
Executing a Proc
To execute the Proc we do
Procs can accept parameters:
#single parameter, single line proc
print_name = Proc.new{|name| puts “my name is #{name}”}
print_name.call(“pankaj”) # “my name is pankaj”
#multiple parameters, single line proc
print_full_name = Proc.new{|first_name,last_name| puts "My name is #{first_name} #{last_name}"}
print_full_name.call("Pankaj","Bhageria") # My name is Pankaj Bhageria
#single parameter, multiple line proc
display_mult_table = Proc.new do |number|
for i in 1..5
puts "#{number} * #{i} = #{number*i}"
end
end
display_mult_table.call(2)
# 2 * 1 = 2
# 2 * 2 = 4
# 2 * 3 = 6
# 2 * 4 = 8
# 2 * 5 = 10
#multiple parameter, multiple line proc
for i in 1..limit
puts "#{number} * #{limit} = #{number*i}"
end
end
display_mult_table.call(2,3)
# 2 * 1 = 2
# 2 * 2 = 4
# 2 * 3 = 6
Note how the parameters are passed to the Proc definition in between the two vertical bars.
Passing a Proc to a method
As a proc is just another object, it can be passed around in methods, returned by methods etc. Suppose we want a block of code to be executed a certain number of times.
for i in 1..times # note the use of range here
code.call(i)
end
end
my_proc = Proc.new{|x| puts “I have been called #{x} times”}
run_code(5,my_proc)
#output:
# I have been called 1 times
# I have been called 2 times
# I have been called 3 times
# I have been called 4 times
# I have been called 5 times
Blocks
Blocks like procs are used to pass code to methods, but they are like undefined procs. ie they are not assigned to any variable, they are just passed to the methods. It will be more clearer when you see the examples.
They can be passed to any method, the method may or may not use them.
Then how does the method execute the block, as there is no parameter to reference it. The method can call the block, by giving the command “yield” which executes the code in the block.
# body of the method
end
some_method(){puts "I am passing a block"}
some_method{puts "I am passing a block"}
#Let us define a method which uses a block
def run_my_code
yield
end
run_my_code{puts "I am passing a block"}
# I am passing a block
#passing multiline blocks
run_my_code do
puts "I am passing a multiline block"
puts "This is the second line of the block"
end
#I am passing a multiline block
#This is the second line of the block
Blocks can be passed along with the other parameters of the method.
for i in 1..times
yield
end
end
run_my_code(2) { puts "passing a block along with params"}
#passing a block along with params
#passing a block along with params
run_my_code(2) do
puts "line1: passing a multi-line block along with params"
puts "line2: passing a multi-line block along with params"
end
#line1: passing a multi-line block along with params
#line2: passing a multi-line block along with params
#line1: passing a multi-line block along with params
#line2: passing a multi-line block along with params
Blocks can accept parameters like methods
for user in users
name = user[:first_name] + " " + user[:last_name]
yield(name)
end
end
#Name is Pankaj Bhageria
#Name is David Jones
Note that in the above example you can change the format of printing anytime by just changing the call to the method. You donot need to modify the method.
So this seperates the 2 things -
Working on the data: Here we are simply calculating the full name of the user, in real life it could have been more complex -
Using the result: Here we are passing the result to the output stream. We can store it to a database/file system or something.
If we need to store the result in a database/file we just need to modify the block passing along with the method.
Use of Ampersand(&)
Ampersand is used to convert a proc to a block and a block to a proc.
If a method want to accept a block but wants to use it as a proc, then add an & in front of the last parameter(the parameter which will receive the block.
my_code.call
end
run_my_code { puts "passing a block, accepting a proc"}
#passing a block, accepting a proc
Note above that we are using “my_code.call” and not yield.
If you have a proc and you want to pass it to a method which accepts block, then when passing use a ampersand before the proc parameter.
yield
end
my_proc = Proc.new { puts "passing a proc instead of block"}
run_my_code my_proc #error, wrong number of arguments
run_my_code &my_proc # passing a proc instead of block
So we have successfully passed a proc to a method which accepts a block
Important points
Only one block can be accepted by a method.
A block can be passed to any method, no need to define it.
To pass a proc instead of a block append an “&” in front of the Proc.
Lambda
my_lambda.call("Ruby")
#Ruby
Lambda is exactly same as a Proc with some minor difference, which we will take up in another post.
Share
Quick tips for learning Rails
Mar 11th
Know you basics well:
Without knowing your basics(programming, object oriented concepts, design patterns, database concepts),
you would face many difficulties in the path of becoming an expert.
Learn Ruby
It is a myth that knowing Ruby is not required to learn rails. But beware, without Ruby your path on Rails would be very bumpy and short.
Learn SQL:
Knowledge of sql is a must to write complex queries in active record and debugging problems related to database.
Write Code, Write Code, Write Code
This the best thing you can do.
Type out the code you write, do not copy paste from an ebook or any training material you are reffering.
This point is not about copy pasting chunks of code from the internet. When you are learning rails from some ebook or some e material, then when you try out examples, you tend to copy paste from the material. This way you never learn/remember the syntax and the method names.
Believe me, follow this one and you will remember the syntax, names of the methods only after 2-3 times you type it out. If you copy paste code, then even after 2 yrs of working on rails, you would be stuck without api.rubyonrails.org or google to refer for syntax.
Ask why
Ask why, understand why you are writing this and not something else. At first there will be many questions. Move ahead, and keep asking the questions, slowly all the pieces of the puzzle will join, and your questions will be answered.
Do not get stuck at some point, if you are not understanding some thing. Assume and move ahead, and come back to it later. Don’t be very fanatic about understanding everything in the first go. This way you may get frustrated and stop.
Read others good code.
This will help you prevent making mistakes and write better code faster.
Share


Quick Ruby Tutorials-1
Mar 19th
Posted by Pankaj Bhageria in Ruby
13 comments
So let us start learning Ruby.
To write ruby code you can use IRB ie interactive ruby for very short programs.
For larger programs you can use any other editor like Emacs or TextMate or SciTE(which ships with Ruby on windows).
Religiously we will make our first program ie “Hello World”
#OR
puts "Hello World" #Output: Hello World
puts is a method(function) which prints the string passed to it on the screen.
The string written after the # is the comment ie it is not executed by Ruby.
Comments are used to explain the code( like to show the output in our case).
These start with a # and the rest of the line after
The output for the above program is given at the end of the corresponding line as a comment. From now onwards we will not specify the word “Output” in the comments.
2+ 2 #this is a comment with other ruby code
As Ruby is fully object oriented language(Basically everything in ruby is an object.) we will start with classes and objects.
Let us create a class to represent a Dog.
end
Note how the classes are defined
end
To create an instance of Dog
d is the instance/object of the class dog.
So we have confirmed that the object d is of class Dog
As every thing in ruby is an object, let us check out the class of different datatypes.
puts "this is a string".class #String
puts 2.2.class #Float
We can create as many instances of dog we want
scooby = Dog.new
pummy = Dog.new
Here we have created 3 dogs: timmy, scooby, pummy
Now let us add to the dog capibilty to bark. For this we need to pass a command to the dog to bark
With the help of methods we can give the ability to ruby objects to receive messages
Methods are like functions in c/c++/java.
def bark
puts "bhow bhow!!"
end
end
d = Dog.new
d.bark() #bhow bhow !!
Ruby allows us to eliminate the parenthesis for method calls, it looks more cleaner without the parenthesis.
Note how the methods are defined
#method body
end
Above we used methods “new” and ‘class’. But we never defined these?
Ruby gives several methods for free to a class and object, so there is no need to define them.
When you pass message to an object, the object should reply back.
So every method in ruby returns some value.
Infact every statement in ruby has a return value.
the the class for nil is NilClass
Let us see the return values for different statements
go to irb and type the following without comments(comments are the output)
"test" # test
1 + 2 # 3
x = 1 # 1
x = 'Ruby' # Ruby
puts "Hello World"
#Hello World
# nil
Above we see the output of the various kinds of statements. The output is specified by the comments.
nil is the output of the puts satement. “Hello World” is due the puts statement, which prints on the screen.
nil in ruby mean, nothing, it is used to represent something which doesnot exist. It is similar to the null in sql.
#As we had told everything in ruby is an object, so nil also an object of Class NilClass
go to irb
NilClass
So a method when called also returns a specific value. Like the puts has a return value of nil.
return value of the method can be explicitly stated by return value or it is the output of the last statement executed in the method
The return value of the method bark is nil, because the last statement executed is puts “bhow bhow”, and puts method returns nil
Note the return value is not the string “bhow bhow”. This string is just printed be the puts statement.
puts value # nil
What is use of the return value.
The return value is useful when the method call is a part of another exression.
We can redefine our bark method as follows
def bark
return "bhow bhow!!"
end
end
d = Dog.new
puts d.bark # "bhow bhow !!"
Now the bark method returns the value “bark”, and this value is used in the put statement.
The return value could be used in any other way lik to store the value in a file/database.
We could have also defined our bark method as
def bark
"bhow bhow !!"
end
end
d = Dog.new
puts d.bark # "bhow bhow !!"
This works because, the as the rule, (as there is no explicit return) the return value is the output of the last statement executed. which is ”bhow bhow !!”
so return value of this is “bhow bhow!!”
Lets enable our dog to eat
We need to create a eat method for that
def eat
puts "I am eating"
end
end
d = Dog.new
d.eat # I am eating
We should be able to give specific food to our dog to eat.
The error tells that the method eat can accept 0 arguments and we are passing 1.(the paramter passed to a method is also called as arguments)
We should make the method “eat” accept 1 parameter/argument.
def eat(food)
puts "I am eating "
puts food
end
end
d = Dog.new
d.eat("bone")
# I am eating
# bone
From the above example we see that to define a method to accept parameters the syntax is as follows
end
To invoke the method with parameter you have to call the method with all the paramter values in the same order.
method_name(x,y,z) #x maps to param1, y maps to param2 z maps to param3
We also see that the method eat prints 2 lines. We didnot specify a new line(“/n”). This is because method puts prints a “/n” at the end by default.
We need to modify puts so that u can print the output in the same line.
def eat(food)
puts "I am eating #{food}"
end
end
d = Dog.new
d.eat("bone") # I am eating bone
d.eat "biscuit" # I am eating biscuit
Learnings from above example:
To replace a value of the value of a variable in a string do
Note that this will work only on the double quoted string
Try on irb
puts "value of x is #{x}" #value of x is 10
puts 'value of x is #{x}' #value of x is #{x}
In first case the value of x is printed, in the second case the string is printed as it is.
We could have also done
The above works if food is a string. If food is a Fixnum(integer) then
"I am eating " + 10.to_s
Learnings from above example:
to_s is a method of Fixnum class to convert it to string
To get a complete list of methods available in any class go to ruby-doc.org and see the list of methods in that class
Now every time we tell our dog to eat, we have to tell it, what is there to eat.
But most of the time we would be giving our dog, bone to eat. So when we do not tell what is there to eat, the dog should understand that we have given it bone.
If you have a background of C/C++/Java, you would probably think of using function overloading here, ie create another mehtod fodd which accepts no parameters.
If we do that in Ruby then the method which is defined first will be overridden and not overloaded ie that method will be replaced by the second method.
Let us see how
def eat(food)
puts "I am eating #{food}"
end
def eat
puts "I am eating bone"
end
end
d = Dog.new
d.eat # I am eating bone
d.eat("bone") #ArgumentError: wrong number of arguments(1 for 0)
Learnings from above example:
In Ruby there is no concept of method overloading.
In Ruby, you can re define a method any time, even after closing the class, you can reopen the class and then add/modify the exisiting methods.
define a class A
end
#reopen class a and add method m1 to it.
def m1
puts "in m1"
end
end
a = A.new
a.m1 #in m1
Reopen the class and add method m2
def m2
puts "in m2"
end
end
x = A.new
x.m1 # in m1
x.m2 # in m2
Reopen the class and modify method m2
def m2
puts "in modified m2"
end
end
a = A.new
a.m2 "in modified m2"
Let us add an eat method to a Fixnum class so that we can do 2.eat
we need to reopen the Fixnum class.
def eat
puts "I am not dog, a number cannot eat"
end
end
2.eat #I am not dog, a number cannot eat
Getting back to the world of Dogs.
We were solving to problem of allowing to call eat with and without passsing food.
We need to use default parameters for this.
The default parameter need not be passed to the method. When it is not passed it takes a default value which is defined during method defination.
So we make the parameter food as default ie the value of the food will be “bone” if no parameter is passed to the eat mehtod.
Let us see how.
def eat(food="bone")
puts "I am eating #{food}"
end
end
d = Dog.new
d.eat #I am eating bone
d.eat("chocolate") #I am eating chocolate
So now our dog understands that we have given it bone when we do not specify anything.
We have added methods for the dogs to bark, eat.
Now our dog can bark and eat.
We will add more features to our dog in later posts.
Let us summarize what we learnt
Print a string on output screen
Comments in Ruby
Define a class
Create a new object
Find the class of an object
Pass messages to an object by defining methods
Return value of methods and statements
Methods accepting parameters
Embedding values of variables in a string
Converting a number(Fixnum to a string)
Extending a class
Methods with default parameters
Share