Creating a Class factory

Discussion in 'Ruby' started by Gavin Kistner, Oct 1, 2005.

  1. As noted in another thread, I'm looking at ways of creating a Struct-
    like class; one that is a factory for creating classes. I did it one
    way by using Struct itself, but I'm not wild about it. I'd like to
    write my own, that sets true instance variables instead of struct's
    members thing. Is Struct using C magic during its initialize to cause
    "Struct.new" to return class objects, or is it just doing the
    equivalent of the following:

    class Foo
    def self.new
    klass = Class.new( self )
    # setup klass here
    klass
    end
    end

    Is there a better way to make a class that creates 'instances' which
    are also classes?

    Erps, except that the above doesn't work, because if you ask the new
    class to inherit from the factory, then 'new' is overridden and
    doesn't call initialize. For example:

    class KeywordClass
    def self.new( property_hash )
    klass = Class.new( self )
    code = <<-ENDCODE
    attr_accessor #{property_hash.keys.map{|k|
    k.to_s.intern.inspect}.join(', ')}
    def initialize( values={} )
    #{property_hash.map{ |prop,default|
    "@#{prop} = values[#{prop.inspect}] || #
    {default.inspect}"
    }.join("\n")}
    end
    ENDCODE
    klass.class_eval code
    klass
    end
    def foo
    "whoa"
    end
    end

    People = KeywordClass.new :cat=>true
    puts People.new.cat
    #=> ArgumentError: wrong number of arguments (0 for 1)
    Gavin Kistner, Oct 1, 2005
    #1
    1. Advertising

  2. Gavin Kistner

    Ara.T.Howard Guest

    On Sun, 2 Oct 2005, Gavin Kistner wrote:

    > As noted in another thread, I'm looking at ways of creating a Struct-like
    > class; one that is a factory for creating classes. I did it one way by using
    > Struct itself, but I'm not wild about it. I'd like to write my own, that sets
    > true instance variables instead of struct's members thing. Is Struct using C
    > magic during its initialize to cause "Struct.new" to return class objects, or
    > is it just doing the equivalent of the following:
    >
    > class Foo
    > def self.new
    > klass = Class.new( self )
    > # setup klass here
    > klass
    > end
    > end
    >
    > Is there a better way to make a class that creates 'instances' which are also
    > classes?
    >
    > Erps, except that the above doesn't work, because if you ask the new class to
    > inherit from the factory, then 'new' is overridden and doesn't call
    > initialize. For example:
    >
    > class KeywordClass
    > def self.new( property_hash )
    > klass = Class.new( self )
    > code = <<-ENDCODE
    > attr_accessor #{property_hash.keys.map{|k|
    > k.to_s.intern.inspect}.join(', ')}
    > def initialize( values={} )
    > #{property_hash.map{ |prop,default|
    > "@#{prop} = values[#{prop.inspect}] || #
    > {default.inspect}"
    > }.join("\n")}
    > end
    > ENDCODE
    > klass.class_eval code
    > klass
    > end
    > def foo
    > "whoa"
    > end
    > end
    >
    > People = KeywordClass.new :cat=>true
    > puts People.new.cat
    > #=> ArgumentError: wrong number of arguments (0 for 1)


    traits let's you do this easily:

    harp:~ > cat a.rb
    require 'traits'

    class People
    trait 'cat' => true
    end
    p People::new.cat

    # or

    module KeywordClass
    def self::new *a, &b
    klass = Class::new { a.each{|t| trait t} }
    klass.module_eval &b if b
    klass
    end
    end
    People2 = KeywordClass::new 'hat', 'cat' => true
    p People2::new.cat
    p People2::new.hat

    People3 = KeywordClass::new(%w(cat in the hat)){ trait 'striped' => true }
    person = People3::new
    People3.reader_traits.each{|t| p t => person.send(t)}


    harp:~ > ruby a.rb
    true
    true
    nil
    {"cat"=>nil}
    {"in"=>nil}
    {"hat"=>nil}
    {"the"=>nil}
    {"striped"=>true}

    hth. traits also inherit their default values up the general inheritence
    hierarchy - even for class traits.

    -a
    --
    ===============================================================================
    | email :: ara [dot] t [dot] howard [at] noaa [dot] gov
    | phone :: 303.497.6469
    | Your life dwells amoung the causes of death
    | Like a lamp standing in a strong breeze. --Nagarjuna
    ===============================================================================
    Ara.T.Howard, Oct 1, 2005
    #2
    1. Advertising

  3. Gavin Kistner

    Ara.T.Howard Guest

    On Sun, 2 Oct 2005, itsme213 wrote:

    > Ara,
    >
    > Any plans to gemify traits?
    >
    > Cheers ...


    yes. my trouble, attm, is that i'm extremely busy and often update one or two
    of my packages per week. the way i sync them all up to
    http://codeforpeople.com/lib/ruby is a simple

    scp -r ./lib/ruby/* codeforpeople.com:lib/ruby

    this, along with writing READMES, minimal docs, and sample programs is all i
    can manage. the gem thing is too hard for me to keep up to date with - at
    least until i took a few days to setup rake files and tasks to upload to
    rubyforge. the other issues i have are that i hate cvs and especially cvs
    frontends, the most typical way is use my code is to be editing in vim with
    something like

    http://codeforpeople.com/lib/ruby/traits/traits-0.7.0/sample/a.rb

    open in lynx - all screen'd (screen being the worlds best 'ide' ;-) together
    (i develop pretty much without X because i ssh everywhere all the time so
    anything gui is out). it's often, once per day, that i have to pull up
    something like

    http://codeforpeople.com/lib/ruby/lockfile/lockfile-1.3.0/lib/lockfile.rb

    because i can't remember how i implemented something. archaic i know, but i
    don't really know anyone personally that manages 35 or so libraries with
    around 10 of them active at any one time - and that excludes the 30 or so i
    manage for work - in a way that sounds easier to me. the other thing i can't
    stand about gems is the versioning - it kills me. in any case i realize, on
    the one hand, that someone out there probably knows how to skin this cat in
    less time that it took me to write this - i'm all ears too - but for now
    packing gems and updating them to a gemserver just slows me down too much. i
    do have code generators (dumb ones) and scripts i use to manage my current
    stuff so i'm open to scriptable ideas that allow easy viewing of the code
    online too.

    otth it's apparent that gems is the future (gem guys - make them install into
    system space and have sane/rigid version please!) so i promise to at least do
    something stop-gap to gem-ify my stuff.

    cheers.

    -a
    --
    ===============================================================================
    | email :: ara [dot] t [dot] howard [at] noaa [dot] gov
    | phone :: 303.497.6469
    | Your life dwells amoung the causes of death
    | Like a lamp standing in a strong breeze. --Nagarjuna
    ===============================================================================
    Ara.T.Howard, Oct 1, 2005
    #3
    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. Digby
    Replies:
    1
    Views:
    5,784
    Digby
    Oct 20, 2003
  2. Medi Montaseri
    Replies:
    17
    Views:
    836
    Medi Montaseri
    Sep 3, 2003
  3. Simon Elliott
    Replies:
    0
    Views:
    366
    Simon Elliott
    Jan 11, 2005
  4. C#
    Replies:
    4
    Views:
    388
  5. Alan
    Replies:
    4
    Views:
    243
    Bill Felton
    Jan 27, 2011
Loading...

Share This Page