How is this possible (Class.new.chain_method)

class Restaurant

attr_accessor :name, :cuisine, :price

def initialize(args={})
@name = args[:name] || “”
@cuisine = args[:cuisine] || “”
@price = args[:price] || “”
end

def self.bracket_method
args = {}
args[:name] = “Burger store”
args[:cuisine] = “Fast Food”
args[:price] = “10”
args[:wrongz] = “this isn’t printed”
return args
end

def chain_method
@name = “Pizza store”
@cuisine = “Fastest Food”
@price = “5”
@wrongz = “this is printed”
puts self.inspect
return self
end

x = Restaurant.new(bracket_method)
puts x.inspect
puts x.class
puts
y = Restaurant.new.chain_method
puts y.inspect
puts y.class

end

“bracket_method” is logical, but what is going on in case of
“chain_method” ?
Did I instantiate object “y” of class “Restaurant” without
initialization ?
How is that possible ?

I think I didn’t get right your question, perhaps because my “not so
good” english.

But, step-by-step it would be …

y = Restaurant.new.chain_method

is the same as …

rest = Restaurant.new # So, here, you have alread “initialized” the
object.
y = rest.chain_method

‘y’ will be the same object as ‘rest’ because the chain_method is
returning self.

Is this the question? If not, sorry for not helping much.

Best regards,
Abinoam Jr.

On Wed, Oct 23, 2013 at 5:54 AM, Abinoam Jr. [email protected] wrote:

y = rest.chain_method

‘y’ will be the same object as ‘rest’ because the chain_method is
returning self.

Expanding a little bit on what Abinoam Jr. said:

def initialize(args={})
@name = args[:name] || “”
@cuisine = args[:cuisine] || “”
@price = args[:price] || “”
end

The initialize method is called internally by “new”, passing all the
arguments you passed to “new”. In this case you are not passing any,
so initialize is called with no arguments. Now, if you look closely at
the definition of your initialize, you have an optional argument with
a default value, so when you don’t pass anything, “args” is an empty
hash, and so @name, @cuisine and @price are initialized to empty
values. When you then call “chain_method” on an object initialized
this way, those variables are assigned to the values “Pizza store” and
so on.

Hope this helps,

Jesus.

On Wed, Oct 23, 2013 at 12:59 PM, Stu P. D’naim [email protected]
wrote:

don’t get error, but when I remove args = {}, there it is. For a moment

y = rest.chain_method
@name = “www store”
equal to strings from chain_method_two ?
It’s supposed to be a setter method

Methods in Ruby return the value of the last expression. In your case
the last expression is @wrongz = “www is printed”, which evaluates to
the String “www is printed”, so that’s what the method returns.

Jesus.

“Jesús Gabriel y Galán” [email protected] wrote in post
#1125295:

The initialize method is called internally by “new”, passing all the
arguments you passed to “new”. In this case you are not passing any,
so initialize is called with no arguments. Now, if you look closely at
the definition of your initialize, you have an optional argument with
a default value

ahh, I forgot about significance of default value, I was wondering why I
don’t get error, but when I remove args = {}, there it is. For a moment
I thought that by doing Class.new.chain_method I was overriding .new
Thanks !

Abinoam Jr. wrote in post #1125275:

y = Restaurant.new.chain_method

is the same as …

rest = Restaurant.new
y = rest.chain_method

‘y’ will be the same object as ‘rest’ because the chain_method is
returning self.

This explains a lot, thank you ! Now, there is only one little thing
that I still don’t understand …

if I add to my code something like this:

def chain_method_two
@name = “www store”
@cuisine = “www Food”
@price = “5w”
@wrongz = “www is printed”
end

w = Restaurant.new.chain_method_two
puts w.inspect

now I get new object (because I’m not returning self) but:
@name, @couisine and @price are all equal to nil … shouldn’t they be
equal to strings from chain_method_two ?
It’s supposed to be a setter method

I know that, but I thought that by running .chain_method_two, instance
variables values should be changed from nil to newly assigned strings
… I hate it when I think I finally understood something, but it turns
out that it doesn’t work the way I think it will … I guess I’m gonna
go back and check out again stuff about reader/writer methods.
Thanks for your time !

On Wed, Oct 23, 2013 at 1:41 PM, Stu P. D’naim [email protected]
wrote:

I know that, but I thought that by running .chain_method_two, instance
variables values should be changed from nil to newly assigned strings
… I hate it when I think I finally understood something, but it turns
out that it doesn’t work the way I think it will … I guess I’m gonna
go back and check out again stuff about reader/writer methods.
Thanks for your time !

How are you checking that they are nil, because you lose the reference
to the object you modify:

w = Restaurant.new.chain_method_two

if you do this, Restaurant.new will return the instance, on which you
call chain_method_two, but you don’t keep a reference to the instance,
so how do you know the values were not changed?

2.0.0p195 :001 > class Restaurant
2.0.0p195 :002?> def chain_two
2.0.0p195 :003?> @a = 3
2.0.0p195 :004?> @b = “something”
2.0.0p195 :005?> end
2.0.0p195 :006?> end
=> nil
2.0.0p195 :007 > value = Restaurant.new.chain_two
=> “something”
2.0.0p195 :008 > value
=> “something”
2.0.0p195 :009 > reference = Restaurant.new
=> #Restaurant:0x0000000266e610
2.0.0p195 :010 > reference.chain_two
=> “something”
2.0.0p195 :011 > reference
=> #<Restaurant:0x0000000266e610 @a=3, @b=“something”>

Jesus.

class Restaurant

attr_accessor :name, :cuisine, :price

def initialize(args={})
@name = args[:name]
@cuisine = args[:cuisine]
@price = args[:price]
end

def chain_method_two
@name = “www store”
@cuisine = “www Food”
@price = “5w”
@wrongz = “www is printed”
end
end

x = Restaurant.new
x.chain_method_two
puts x.inspect

y = Restaurant.new.chain_method_two
puts y.inspect

you said:

y = Restaurant.new.chain_method
is the same as …
rest = Restaurant.new
y = rest.chain_method

but from my code above, x - works, y - just returns string … so, now
it seems it is not the same thing … I am confused again

edit:
ok, I added self at the end of my setter method and now everything works

def chain_method_two
@name = “www store”
@cuisine = “www Food”
@price = “5w”
@wrongz = “www is printed”
self
end

I think I finally understand what were you talking about !

On Wed, Oct 23, 2013 at 2:05 PM, Stu P. D’naim [email protected]
wrote:

def chain_method_two

it seems it is not the same thing
As others have said already: the reason is that #chain_method_two does
not return self.

Cheers

robert