Can Ruby do this magic... elegantly

Discussion in 'Ruby' started by J2M, Nov 12, 2006.

  1. J2M

    J2M Guest

    I would like to be able to be able to include instance methods of a
    Struct into a class. e.g.

    foo = Struct.new:)attribute, :another_attribute)
    bar = foo.new

    class Bas

    some_ruby_magic

    end

    So that I can then do

    Bas.attribute="a value"
    Bas.attribute

    Kind of like doing module_functions but that doesn't work inside a
    class.
    Thanks,
    James
     
    J2M, Nov 12, 2006
    #1
    1. Advertising

  2. On 11/11/06, J2M <> wrote:
    > I would like to be able to be able to include instance methods of a
    > Struct into a class. e.g.
    >
    > foo = Struct.new:)attribute, :another_attribute)
    > bar = foo.new
    >
    > class Bas
    >
    > some_ruby_magic
    >
    > end
    >
    > So that I can then do
    >
    > Bas.attribute="a value"
    > Bas.attribute
    >
    > Kind of like doing module_functions but that doesn't work inside a
    > class.


    class Bas
    @__struct__ = Struct.new:)attribute, :another_attribute)

    class << self
    def method_missing(sym, *args)
    @__struct__.send(sym, *args) if @__struct__.respond_to?(sym)
    end
    end
    end

    That should work.

    -austin
    --
    Austin Ziegler * * http://www.halostatue.ca/
    * * http://www.halostatue.ca/feed/
    *
     
    Austin Ziegler, Nov 12, 2006
    #2
    1. Advertising

  3. J2M

    Guest

    On Sun, 12 Nov 2006, J2M wrote:

    > I would like to be able to be able to include instance methods of a
    > Struct into a class. e.g.
    >
    > foo = Struct.new:)attribute, :another_attribute)
    > bar = foo.new
    >
    > class Bas
    >
    > some_ruby_magic
    >
    > end
    >
    > So that I can then do
    >
    > Bas.attribute="a value"
    > Bas.attribute
    >
    > Kind of like doing module_functions but that doesn't work inside a
    > class.
    > Thanks,
    > James



    harp:~ > cat a.rb
    class Module
    def struct_attrs struct
    singleton_class = class << self
    self
    end
    singleton_class.module_eval{ struct.members.each{|m| attr_accessor m} }
    end
    end

    class Bas
    foo = Struct.new :attribute, :another_attribute
    bar = foo.new

    struct_attrs foo
    end

    Bas.attribute = "a value"
    p Bas.attribute


    harp:~ > ruby a.rb
    "a value"



    -a
    --
    my religion is very simple. my religion is kindness. -- the dalai lama
     
    , Nov 12, 2006
    #3
  4. J2M

    Trans Guest

    J2M wrote:
    > I would like to be able to be able to include instance methods of a
    > Struct into a class. e.g.
    >
    > foo = Struct.new:)attribute, :another_attribute)
    > bar = foo.new
    >
    > class Bas
    >
    > some_ruby_magic
    >
    > end
    >
    > So that I can then do
    >
    > Bas.attribute="a value"
    > Bas.attribute
    > Kind of like doing module_functions but that doesn't work inside a
    > class.


    Foo = Struct.new:)attribute, :another_attribute)

    class Bas
    extend Foo.to_module
    end

    Ha! Only if it were so easy! ;-) Actaully if one had access to Ruby's
    source it would rather trivial (hint). In anycase to par down Ara's
    solution to it's core:

    Foo = Struct.new :attribute, :another_attribute

    class Bas
    class << self
    attr_accessor *Foo.members
    end
    end

    Note the use of the constant which eases access by avoiding
    (class<<self;self;end).class_eval.

    T.
     
    Trans, Nov 12, 2006
    #4
  5. J2M wrote:
    > I would like to be able to be able to include instance methods of a
    > Struct into a class. e.g.
    >
    > foo = Struct.new:)attribute, :another_attribute)
    > bar = foo.new
    >
    > class Bas
    >
    > some_ruby_magic
    >
    > end
    >
    > So that I can then do
    >
    > Bas.attribute="a value"
    > Bas.attribute
    >
    > Kind of like doing module_functions but that doesn't work inside a
    > class.


    I don't know why people make it so complicated. :) All these are easier
    than other approaches suggested so far:

    Foo = Struct.new:)attribute, :another_attribute)
    class Bas < Foo
    end

    class Bas < Struct.new:)attribute, :another_attribute)
    end

    or even

    Bas = Struct.new:)attribute, :another_attribute) do
    def another_method() end
    end

    Kind regards

    robert
     
    Robert Klemme, Nov 12, 2006
    #5
  6. J2M

    J2M Guest

    Robert, T, A & Austin;

    A plethora of choices. All while I slept too ;)

    Thank you all.
    James
     
    J2M, Nov 12, 2006
    #6
  7. J2M

    Guest

    Hi--

    On Sun, 12 Nov 2006, Robert Klemme wrote:

    > J2M wrote:
    >> I would like to be able to be able to include instance methods of a
    >> Struct into a class. e.g.
    >>
    >> foo = Struct.new:)attribute, :another_attribute)
    >> bar = foo.new
    >>
    >> class Bas
    >>
    >> some_ruby_magic
    >>
    >> end
    >>
    >> So that I can then do
    >>
    >> Bas.attribute="a value"
    >> Bas.attribute
    >>
    >> Kind of like doing module_functions but that doesn't work inside a
    >> class.

    >
    > I don't know why people make it so complicated. :) All these are easier than
    > other approaches suggested so far:
    >
    > Foo = Struct.new:)attribute, :another_attribute)
    > class Bas < Foo
    > end
    >
    > class Bas < Struct.new:)attribute, :another_attribute)
    > end
    >
    > or even
    >
    > Bas = Struct.new:)attribute, :another_attribute) do
    > def another_method() end
    > end


    You're adding instance methods to Bas rather than to Bas's singleton
    class, though. The OP wants to do:

    Bas.attribute = "a value"


    David

    --
    David A. Black |
    Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
    DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
    [1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
    [2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
     
    , Nov 12, 2006
    #7
  8. wrote:
    > Hi--
    >
    > On Sun, 12 Nov 2006, Robert Klemme wrote:
    >
    >> J2M wrote:
    >>> I would like to be able to be able to include instance methods of a
    >>> Struct into a class. e.g.
    >>>
    >>> foo = Struct.new:)attribute, :another_attribute)
    >>> bar = foo.new
    >>>
    >>> class Bas
    >>>
    >>> some_ruby_magic
    >>>
    >>> end
    >>>
    >>> So that I can then do
    >>>
    >>> Bas.attribute="a value"
    >>> Bas.attribute
    >>>
    >>> Kind of like doing module_functions but that doesn't work inside a
    >>> class.

    >>
    >> I don't know why people make it so complicated. :) All these are
    >> easier than other approaches suggested so far:
    >>
    >> Foo = Struct.new:)attribute, :another_attribute)
    >> class Bas < Foo
    >> end
    >>
    >> class Bas < Struct.new:)attribute, :another_attribute)
    >> end
    >>
    >> or even
    >>
    >> Bas = Struct.new:)attribute, :another_attribute) do
    >> def another_method() end
    >> end

    >
    > You're adding instance methods to Bas rather than to Bas's singleton
    > class, though. The OP wants to do:
    >
    > Bas.attribute = "a value"


    Oh, ok then I misinterpreted that. I read "include instance methods
    into a class" as including them as instance methods. My bad. Sorry for
    the noise.

    In this particular case, /if/ the aim is to define attribute accessors a
    direct definition is probably the easiest solution

    class Bas
    class <<self
    attr_accessor :attribute, :another_attribute
    end
    end

    Regards

    robert
     
    Robert Klemme, Nov 12, 2006
    #8
  9. J2M

    J2M Guest

    I got the final solution down to this which I think is rather elegant;

    class Bas < Struct.new :attribute, :another_attribute
    class << self
    attr_accessor *Bas.members
    end
    end

    I love this languate; and now really appreciate the power of the
    singleton class.

    Thanks.
     
    J2M, Nov 12, 2006
    #9
  10. J2M

    Trans Guest

    J2M wrote:
    > I got the final solution down to this which I think is rather elegant;
    >
    > class Bas < Struct.new :attribute, :another_attribute
    > class << self
    > attr_accessor *Bas.members
    > end
    > end


    class Bas < Struct.new :attribute, :another_attribute
    class << self
    attr_accessor *members
    end
    end

    Do you realize that you are adding #attribute and #another_attribute at
    both the instance level and the class level, and niether will reference
    tha same values? I.e.

    Bas.attribute = 1
    bas = Bas.new
    bas.attribute = 2
    Bas.attribute #=> 1
    bas.attribute #=> 2

    T.
     
    Trans, Nov 12, 2006
    #10
  11. Trans wrote:
    > J2M wrote:
    >> I got the final solution down to this which I think is rather elegant;
    >>
    >> class Bas < Struct.new :attribute, :another_attribute
    >> class << self
    >> attr_accessor *Bas.members
    >> end
    >> end

    >
    > class Bas < Struct.new :attribute, :another_attribute
    > class << self
    > attr_accessor *members
    > end
    > end
    >
    > Do you realize that you are adding #attribute and #another_attribute at
    > both the instance level and the class level, and niether will reference
    > tha same values? I.e.
    >
    > Bas.attribute = 1
    > bas = Bas.new
    > bas.attribute = 2
    > Bas.attribute #=> 1
    > bas.attribute #=> 2


    Also, what is the point in creating a Struct in this case when you're
    basically only using member names?

    robert
     
    Robert Klemme, Nov 12, 2006
    #11
  12. J2M

    J2M Guest

    Trans wrote:

    > Do you realize that you are adding #attribute and #another_attribute at
    > both the instance level and the class level, and niether will reference
    > tha same values? I.e.
    >
    > Bas.attribute = 1
    > bas = Bas.new
    > bas.attribute = 2
    > Bas.attribute #=> 1
    > bas.attribute #=> 2


    Yes, this is the behaviour I want. I am not actually creating any
    instances. I just use it as a base class and inherit from it.

    Thanks,
    James
     
    J2M, Nov 12, 2006
    #12
  13. J2M

    J2M Guest

    Robert Klemme wrote:

    > Also, what is the point in creating a Struct in this case when you're
    > basically only using member names?
    >
    > robert


    Good spot :-/

    I started out using Struct as I wanted the extra methods for free and
    was creating instances off of it. I have just re-worked this and just
    mix enumerable into the class and get most of what I got from struct,
    so have strayed quite a way from the original question.

    James.
     
    J2M, Nov 12, 2006
    #13
    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. Ken Fine
    Replies:
    0
    Views:
    345
    Ken Fine
    Jul 19, 2003
  2. Michael Hudson
    Replies:
    3
    Views:
    371
    Bengt Richter
    Jul 22, 2003
  3. Michele Simionato
    Replies:
    15
    Views:
    577
  4. Giles Bowkett
    Replies:
    9
    Views:
    428
    Giles Bowkett
    Dec 17, 2007
  5. jrwats
    Replies:
    5
    Views:
    140
    Gary E. Ansok
    Dec 19, 2008
Loading...

Share This Page