"Reflecting" on my self.n00b

There's two ways you can go depending on if you want to be able to add
attributes that are NOT stored.

The easiest way is to use attr_accessor:

class ServiceProfile
    attr_accessor :url, :username, :password, :certificate, :owner
    def load_certificate()
        @certificate.read
    end
    def call_service(&block)
    end
end

class MyService < ServiceProfile
    attr_accessor :extra
end

svc_profile = MyService.new

svc_profile.methods.sort.reverse.each { |meth|
    if /^(.*)=$/ === meth
        print "Enter #{$1.capitalize}: "
        $stdout.flush
        value = $stdin.gets.chomp
        svc_profile.send(meth, value)
    end
}

svc_profile.methods.sort.reverse.each { |meth|
    if /^(.*)=$/ === meth
        puts svc_profile.send($1)
    end
}

The problem with this, however, is that you can't add any xxx=(x)
methods to the class without them being added to your storage system.
Instead, you could do:

class AutoPopulator
    def self.attr_populator(*args)
        attr_accessor(*args)
        (@populators||=).concat(args)
    end
    def self.populators
        populators =
        populators = superclass.populators if superclass.respond_to?
:populators
        populators += @populators if @populators
        populators.uniq.collect {|x| x.to_s}
    end
end

class ServiceProfile < AutoPopulator
    attr_populator :url, :username, :password, :certificate, :owner
    def load_certificate()
        @certificate.read
    end
    def call_service(&block)
    end
end

class MyService < ServiceProfile
    attr_populator :extra
end

svc_profile = MyService.new

svc_profile.class.populators.each { |meth|
    print "Enter #{meth.capitalize}: "
    $stdout.flush
    value = $stdin.gets.chomp
    svc_profile.send("#{meth}=", value)
}

svc_profile.class.populators.each { |meth|
    puts svc_profile.send(meth)
}

···

-----Original Message-----
From: wmwilson01@gmail.com [mailto:wmwilson01@gmail.com] On
Behalf Of swille
Sent: Friday, 28 October 2005 11:11 AM
To: ruby-talk ML
Subject: "Reflecting" on my self.n00b

I'm admittedly quite a novice with programming. I'm sort of
playing around with some ideas, and I'm wondering if what I'm
doing is completely stupid, and if not, is there a better way
to do it? Also, is there any way that I could do some type
of type-ish validation on the data?

Basically, I want to provide what I suppose would be abstract
class (?), which someone else could extend and add attributes
if they'd like. I'd like to be able to look into the class
and pick out the attributes to populate (which is the reason
for all of the sp_set & sp_get stuff). Basically, my thought
is to be able to provide a web interface at some point to
populate the needed data of a class, and then maybe
Marshal.dump the object to a database and call it later using
that data as config data essentially. I'm sure I could learn
a ton about this from reading Rails code, but there's so much
of it that I don't know where to look. Output and code
follows. Please feel free to tell me if this is dumb :O)

Output:
Enter Username: name
Enter Url: url
Enter Extra: more
Enter Password: pass
Enter Owner: own
Enter Certificate: cert
name
url
more
pass
own
cert

Code:
<code>
class ServiceProfile
    def initialize()
    end

    def sp_set_url(url)
        @url = url
    end

    def sp_get_url()
        @url
    end

    def sp_set_username(username)
        @username = username
    end

    def sp_get_username()
        @username
    end

    def sp_set_password(password)
        @password = password
    end

    def sp_get_password()
        @password
    end

    def sp_set_certificate(certificate)
        @certificate = certificate
    end

    def sp_get_certificate()
        @certificate
    end

    def sp_set_owner(owner)
        @owner = owner
    end

    def sp_get_owner()
        @owner
    end

    def load_certificate()
        @certificate.read
    end

    def call_service(&block)
    end
end

class MyService < ServiceProfile
    def sp_set_extra(extra)
        @extra = extra
    end

    def sp_get_extra()
        @extra
    end
end

svc_profile = MyService.new

set_re = Regexp.new('^sp_set_(\w+)')
get_re = Regexp.new('^sp_get_(\w+)')

svc_profile.methods.sort.reverse.each { |meth|
    if meth.match(set_re)
        print "Enter #{Regexp.last_match(1).capitalize}: "
        value = $stdin.gets.chomp
        svc_profile.send(meth, value)
    end
}

svc_profile.methods.sort.reverse.each { |meth|
    if meth.match(get_re)
        puts svc_profile.send(meth)
    end
}
</code>

#####################################################################################
This email has been scanned by MailMarshal, an email content filter.
#####################################################################################