From: Gleb Posobin Date: 2013-07-09T16:52:19+09:00 Subject: Re: Well-Grounded Rubyist -- Person class implementation in chapter 4 question --089e013d1dc692e66604e10f70ef Content-Type: text/plain; charset=ISO-8859-1 Firstly, the error you are receiving has been explained by Sam. Now, to the interesting part: Code in 4.13 defines method_missing for Person class. This method gets run if you call some undefined method in the class. So, for example, if you do Person.blablabla("argument", 2), ruby looks in the Person's class methods (not instance methods, because blablabla was sent to the class itself, not to the instance of it) for a method with name "blablabla". It does not find such method, do then it looks whether the Person class has method_missing method defined. It does, so ruby calls Person.method_missing(:blablabla, "argument", 2), passing the parameters we called "blablabla" with to the method_missing. Ruby puts name method to the "m" variable and the rest of the arguments - to the args array (because it's marked with asterisk - so called splat method, you can read a little bit about it here). Then, ruby converts :blablabla symbol to string and checks whether it starts with "all_with_". It doesn't, so ruby calls super, which means "call parent class' method with the same name of the current one and pass it the same arguments". Now, let's have a look at what happens if we call Person.all_with_name("Julia"). Method Person.all_with_name is not defined, so ruby goes to method_missing for help. This time method's name starts with "all_with_", so ruby extracts the rest of the method's name after "all_with_" to attr variable. Now, ruby checks whether Person class has instance method with the name stored in newly created attr variable (which now contains "name"). Then ruby finds all persons from PEOPLE array, who have name equal to the args[0], which is first argument passed to the Person.all_with_name. "person.send" is another way of calling an instance method, e.g. person.send("haha") is the same as person.haha. Docs for object.send is here . So, at last ruby finds all persons, whose name includes "Julia" as a substring. And, as this PEOPLE.find_all is the last line in the method to be executed, method_missing returns an array of found persons. P.S. If we called Person.all_with_blablabla, we would get ArgumentError exception, because Person does not have instance method blablabla defined, which is checked in line 6 of 4.13 gist. P.P.S. I am myself not really experienced rubyist, so my explanation may contain some mistakes. Be sure to correct them if you notice. P.P.P.S. Also, my English is far from perfect, sorry for that. 2013/7/9 Arslan Farooq > Hi, > > I am new to programming and new to Ruby. > > I have been studying Ruby using David Black's book, and I need bit of > help with this: > > Code in listing 4.11, 4.12 and 4.13 needs to be pieced together (I > think) to do something useful. However it's a bit confusing... whether > they are meant to just studied as examples separately, or whether I am > supposed to piece them together. Please have a look at the code: > > https://gist.github.com/arslanfarooq/54ac5aa7796385e4a063 > > If you could explain a bit what's going on in 4.13 that would be great. > > On my computer I have combined the code in one file "person_class.rb" > and I am getting this error: > > person_class.rb:17:in `has_friends': undefined method `<<' for > nil:NilClass (NoMethodError) from person_class.rb:43:in `
' > > -- > Posted via http://www.ruby-forum.com/. > > --089e013d1dc692e66604e10f70ef Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable
Firstly, the error you are receiving has been explained by= Sam. Now, to the interesting part:
Code in 4.13 defines method_missing= for Person class. This method gets run if you call some undefined method i= n the class. So, for example, if you do Person.blablabla("argument&quo= t;, 2), ruby looks in the Person's class methods (not instance methods,= because blablabla was sent to the class itself, not to the instance of it)= for a method with name "blablabla". It does not find such method= , do then it looks whether the Person class has method_missing method defin= ed. It does, so ruby calls Person.method_missing(:blablabla, "argument= ", 2), passing the parameters we called "blablabla" with to = the method_missing. Ruby puts name method to the "m" variable and= the rest of the arguments - to the args array (because it's marked wit= h asterisk - so called splat method, you can read a little bit about it = here). Then, ruby converts :blablabla symbol to string and checks wheth= er it starts with "all_with_". It doesn't, so ruby calls supe= r, which means "call parent class' method with the same name of th= e current one and pass it the same arguments". Now, let's have a l= ook at what happens if we call Person.all_with_name("Julia"). Met= hod Person.all_with_name is not defined, so ruby goes to method_missing for= help. This time method's name starts with "all_with_", so ru= by extracts the rest of the method's name after "all_with_" t= o attr variable. Now, ruby checks whether Person class has instance method = with the name stored in newly created attr variable (which now contains &qu= ot;name"). Then ruby finds all persons from PEOPLE array, who have nam= e equal to the args[0], which is first argument passed to the Person.all_wi= th_name. "person.send" is another way of calling an instance meth= od, e.g. person.send("haha") is the same as person.haha. Docs for= object.send is=A0here. So, at last ruby finds all persons, whose name includes= "Julia" as a substring. And, as this PEOPLE.find_all is the last= line in the method to be executed, method_missing returns an array of foun= d persons.
P.S. If we called Person.all_with_blablabla, we would get ArgumentErro= r exception, because Person does not have instance method blablabla defined= , which is checked in line 6 of 4.13 gist.
P.P.S. I am myself not= really experienced rubyist, so my explanation may contain some mistakes. B= e sure to correct them if you notice.
P.P.P.S. Also, my English is far from perfect, sorry for that.


2013/7/= 9 Arslan Farooq <lists@ruby-forum.com>
Hi,

I am new to programming and new to Ruby.

I have been studying Ruby using David Black's book, and I need bit of help with this:

Code in listing 4.11, 4.12 and 4.13 needs to be pieced together (I
think) to do something useful. However it's a bit confusing... whether<= br> they are meant to just studied as examples separately, or whether I am
supposed to piece them together. Please have a look at the code:

https://gist.github.com/arslanfarooq/54ac5aa7796385e4a063<= br>
If you could explain a bit what's going on in 4.13 that would be great.=

On my computer I have combined the code in one file "person_class.rb&q= uot;
and I am getting this error:

person_class.rb:17:in `has_friends': undefined method `<<' fo= r
nil:NilClass (NoMethodError) from person_class.rb:43:in `<main>'<= br>
--
Posted via http://= www.ruby-forum.com/.


--089e013d1dc692e66604e10f70ef--