Forum: Ruby how is this possible (Class.new.chain_method)

E8f4cff5d676e9ef840fe7a030efc845?d=identicon&s=25 Stu P. D'naim (oldboy)
on 2013-10-22 22:34
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 ?
09a32175057418748822c587ac08c429?d=identicon&s=25 Abinoam Jr. (abinoampraxedes_m)
on 2013-10-23 05:54
(Received via mailing list)
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.
E088bb5c80fd3c4fd02c2020cdacbaf0?d=identicon&s=25 "Jesús Gabriel y Galán" <jgabrielygalan@gmail.com> (Guest)
on 2013-10-23 09:15
(Received via mailing list)
On Wed, Oct 23, 2013 at 5:54 AM, Abinoam Jr. <abinoam@gmail.com> 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.
E8f4cff5d676e9ef840fe7a030efc845?d=identicon&s=25 Stu P. D'naim (oldboy)
on 2013-10-23 12:59
"Jesús Gabriel y Galán" <jgabrielygalan@gmail.com> 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
E088bb5c80fd3c4fd02c2020cdacbaf0?d=identicon&s=25 "Jesús Gabriel y Galán" <jgabrielygalan@gmail.com> (Guest)
on 2013-10-23 13:22
(Received via mailing list)
On Wed, Oct 23, 2013 at 12:59 PM, Stu P. D'naim <lists@ruby-forum.com>
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.
E8f4cff5d676e9ef840fe7a030efc845?d=identicon&s=25 Stu P. D'naim (oldboy)
on 2013-10-23 13:41
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 !
E088bb5c80fd3c4fd02c2020cdacbaf0?d=identicon&s=25 "Jesús Gabriel y Galán" <jgabrielygalan@gmail.com> (Guest)
on 2013-10-23 13:46
(Received via mailing list)
On Wed, Oct 23, 2013 at 1:41 PM, Stu P. D'naim <lists@ruby-forum.com>
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.
E8f4cff5d676e9ef840fe7a030efc845?d=identicon&s=25 Stu P. D'naim (oldboy)
on 2013-10-23 14:05
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 !
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (robert_k78)
on 2013-10-23 14:56
(Received via mailing list)
On Wed, Oct 23, 2013 at 2:05 PM, Stu P. D'naim <lists@ruby-forum.com>
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
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.