Forum: Ruby What does this statement do?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
36bb3d34936645673a87e6732d3281ca?d=identicon&s=25 Stanislaw Wozniak (swozniak)
on 2009-03-02 15:04
Hi Guys,

I have been wondering what does this statement do and what does it set.
It interferes with my methods_missing handler:

{code}
class MyClass

   something = "something else"

end
{code}
36bb3d34936645673a87e6732d3281ca?d=identicon&s=25 Stanislaw Wozniak (swozniak)
on 2009-03-02 15:20
Stanislaw Wozniak wrote:
> Hi Guys,
>
> I have been wondering what does this statement do and what does it set.
> It interferes with my methods_missing handler:
>
> {code}
> class MyClass
>
>    something = "something else"
>
> end
> {code}

I guess this is assigning a string to a variable that is created in the
MyClass scope. But my problem is that I have some setter methods that
I'm using through method_missing, but method_missing is never triggered
because it is assigning stuff just like in the example above.
3afd3e5e05dc9310c89aa5762cc8dd1d?d=identicon&s=25 Tim Hunter (Guest)
on 2009-03-02 15:25
(Received via mailing list)
Stanislaw Wozniak wrote:
>>
>> end
>> {code}
>
> I guess this is assigning a string to a variable that is created in the
> MyClass scope. But my problem is that I have some setter methods that
> I'm using through method_missing, but method_missing is never triggered
> because it is assigning stuff just like in the example above.

You're saying that "something" is supposed to be treated like a method
instead of like a variable? Try

self.something = "something else"
83ca41657a99b65d99889abe712ba5e2?d=identicon&s=25 Jason Roelofs (Guest)
on 2009-03-02 15:29
(Received via mailing list)
On Mon, Mar 2, 2009 at 9:18 AM, Stanislaw Wozniak <stan@wozniak.com>
wrote:
>>
>
That statement is the same as calling MyClass.something=("something
else")

If you want method_missing to catch it, you need to define a
method_missing on the class itself, like this:

class MyClass

  def self.method_missing(name, *args)
  end

end

Jason
36bb3d34936645673a87e6732d3281ca?d=identicon&s=25 Stanislaw Wozniak (swozniak)
on 2009-03-02 15:32
Ok, this is the example I want to get to work. Method set_field is never
triggered because local variable set_field is being set.

class A

  def self.set_field=(value)
      puts "Trying to set field value"
  end

  def method_missing(name, *args)
  self.class.method(name).call args
  end
  def self.method_missing(name, *args)
  new.method(name).call args
  end

end

class B < A

   def my_method(value)
      set_field = value
   end

end

B.my_method
8f6f95c4bd64d5f10dfddfdcd03c19d6?d=identicon&s=25 Rick Denatale (rdenatale)
on 2009-03-02 15:54
(Received via mailing list)
On Mon, Mar 2, 2009 at 9:31 AM, Stanislaw Wozniak <stan@wozniak.com>
wrote:

>  self.class.method(name).call args
>      set_field = value
>   end
>
> end
>
> B.my_method
>

Yes this is a well-known ruby newbie gotcha.

Because the Ruby syntax allows simple names to refer to either a local
variable or a method invocation, there are some times when things get
ambiguous.

In the case of a name on the right hand side of an assignment, or
equivalent
settings, the ruby compiler treats the name as a local variable if the
name
has already been assigned a value, and as a method call with an implied
receiver of self otherwise.

In the case of a name on the right hand side, it treats the name as a
local
variable, and assigns it a value.

You HAVE to explicitly give a receiver of self when invoking an
attribute
setter method in ruby. So in my_method you have to use self.set_field =
value.

And this is why, for those who like to mark methods as private.


class Foo

private
def a=(value)
     ...
   end

   def b
     ....
   end

   public
   def c
      self.a= 2  # This is okay
      self.b       # This triggers a NoMethodError "private method 'b'
called for ...
   end
end
--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale
36bb3d34936645673a87e6732d3281ca?d=identicon&s=25 Stanislaw Wozniak (swozniak)
on 2009-03-02 15:57
Thanks Rick,

This is clear explanation. Makes sense...
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2009-03-02 18:15
(Received via mailing list)
On 02.03.2009 15:27, Jason Roelofs wrote:
>>>    something = "something else"
>>
>
> That statement is the same as calling MyClass.something=("something else")

Actually, no.  See Rick's excellent explanation.  For test addicts:

[oracle@ora01 ~]$ ruby y.rb
test 1
foo called with 123
test 2
[oracle@ora01 ~]$ cat y.rb

class X
   def self.foo=(a)
     printf "foo called with %p\n", a
   end
end

puts "test 1"
X.foo = 123

class X
   puts "test 2"
   foo = 987
end

[oracle@ora01 ~]$

> If you want method_missing to catch it, you need to define a
> method_missing on the class itself, like this:
>
> class MyClass
>
>   def self.method_missing(name, *args)
>   end
>
> end

Won't help here, because the statement is interpreted as a local
variable assignment.

Kind regards

  robert
This topic is locked and can not be replied to.