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

  2. 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, Nov 12, 2006
    #2
    1. Advertisements

  3. J2M

    ara.t.howard Guest


    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
     
    ara.t.howard, Nov 12, 2006
    #3
  4. J2M

    Trans Guest

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

    dblack Guest

    Hi--

    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
     
    dblack, Nov 12, 2006
    #7
  8. 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

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

    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

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

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.