What does this statement do?

Discussion in 'Ruby' started by Stanislaw Wozniak, Mar 2, 2009.

  1. 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}
    --
    Posted via http://www.ruby-forum.com/.
     
    Stanislaw Wozniak, Mar 2, 2009
    #1
    1. Advertising

  2. 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.
    --
    Posted via http://www.ruby-forum.com/.
     
    Stanislaw Wozniak, Mar 2, 2009
    #2
    1. Advertising

  3. Stanislaw Wozniak

    Tim Hunter Guest

    Stanislaw Wozniak wrote:
    > 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.


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

    self.something = "something else"

    --
    RMagick: http://rmagick.rubyforge.org/
     
    Tim Hunter, Mar 2, 2009
    #3
  4. On Mon, Mar 2, 2009 at 9:18 AM, Stanislaw Wozniak <> wrote:
    > 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
    >>
    >> =A0 =A0something =3D "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.
    > --
    > Posted via http://www.ruby-forum.com/.
    >
    >


    That statement is the same as calling MyClass.something=3D("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
     
    Jason Roelofs, Mar 2, 2009
    #4
  5. 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
    --
    Posted via http://www.ruby-forum.com/.
     
    Stanislaw Wozniak, Mar 2, 2009
    #5
  6. [Note: parts of this message were removed to make it a legal post.]

    On Mon, Mar 2, 2009 at 9:31 AM, Stanislaw Wozniak <> wrote:

    > 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
    >


    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
     
    Rick DeNatale, Mar 2, 2009
    #6
  7. On 02.03.2009 15:27, Jason Roelofs wrote:
    > On Mon, Mar 2, 2009 at 9:18 AM, Stanislaw Wozniak <> wrote:
    >> 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.
    >> --
    >> Posted via http://www.ruby-forum.com/.
    >>
    >>

    >
    > 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
     
    Robert Klemme, Mar 2, 2009
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    3
    Views:
    815
  2. Jay McGavren
    Replies:
    11
    Views:
    1,156
    Alan Krueger
    Jan 16, 2006
  3. tedsuzman
    Replies:
    2
    Views:
    7,122
    Michel Claveau, résurectionné d'outre-bombe inform
    Jul 21, 2004
  4. Ted
    Replies:
    1
    Views:
    478
    Duncan Booth
    Jul 22, 2004
  5. Replies:
    21
    Views:
    1,068
    Giannis Papadopoulos
    Aug 2, 2005
Loading...

Share This Page