Newbie: Question => How to do this with Classes ?

E

Eye Matz

class Important
def set_this_value_method(value)
end
end

class SemiImportant < Important
set_this_value_method :something_or_anything
end

Could some kind sould please, please take the time to explain the
fundamentals of Ruby's class/module functionality in regards to the
above example.

I'm a photographer/php 'programmer' so I speak fairly good English, but
very little geek speak, so please don't assume too much. Having said
the above, I've created fairly complex class structures/frameworks in
PHP, so I'm not completely dense, although grepping Ruby's syntax
certainly makes me feel that way.

I have the books "Pickaxe", "Ruby for Rails" & "AWDR" and I have tried
to read my way to an answer, but these books are designed for
programmers, and not visual people like myself, so hence I can't see the
answers in them, even though they may well be in there.

To give you the context of my question, please consider this Rails code
example:

class DumbNewbie < ActiveRecord::Base
has_many :questions
end

Hope I've been clear, yet succinct, enough to not waste too much
bandwith. I'll be extremely grateful for anyone taking the time to get
me over this major hurdle.
 
E

Eye Matz

Jean said:
See this post:
http://ola-bini.blogspot.com/2006/09/ruby-metaprogramming-techniques.html

I think the second point is what you seek, and it is explained too :)

Hi Jean,

Thanks for your reply, but I'm sorry to say, that page contains just
more confusion. A copy&paste job and changing of that code into my test
scenario just causes an error
"NameError: undefined local variable or method ‘singleton_class’ for..."

The blog post is hitting me way too high, and so does 95% of all other
examples I've found so far.

But please take that bit of code and rewrite it, WITH clear and
extensive comments for each line of code, within my given example in the
original post, and maybe then I can test run it and work it out from
there. I learn from code that is gradually (slowly!!) extended into
doing what I want it to do,

WIthout that it's just geek speak, and no way near fluent in that :(
 
D

dblack

Hi --

class Important
def set_this_value_method(value)
end
end

class SemiImportant < Important
set_this_value_method :something_or_anything
end

Could some kind sould please, please take the time to explain the
fundamentals of Ruby's class/module functionality in regards to the
above example.

In the second snippet, you're sending the message
"set_this_value_method" to the class object SemiImportant. In order
for that object to understand the message, a method called
set_this_value_method has to be defined either in

1. the object's class (which, in this case, is actually Class
2. on a singleton (per-object) basis for the object
3. on a singleton basis in the object's super[super[super...]]class.

So, you could do this:

class Important
def self.set_this_value_method(value) # note the 'self'
end
end

class SemiImportant < Important
set_this_value_method :x
end


David

--
David A. Black | (e-mail address removed)
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
 
T

Tim Hunter

Eye said:
class Important
def set_this_value_method(value)
end
end

class SemiImportant < Important
set_this_value_method :something_or_anything
end

Could some kind sould please, please take the time to explain the
fundamentals of Ruby's class/module functionality in regards to the
above example.

I'm a photographer/php 'programmer' so I speak fairly good English, but
very little geek speak, so please don't assume too much. Having said
the above, I've created fairly complex class structures/frameworks in
PHP, so I'm not completely dense, although grepping Ruby's syntax
certainly makes me feel that way.

I have the books "Pickaxe", "Ruby for Rails" & "AWDR" and I have tried
to read my way to an answer, but these books are designed for
programmers, and not visual people like myself, so hence I can't see the
answers in them, even though they may well be in there.

Let me recommend Why's (Poignant) Guide to Ruby:
http://www.poignantguide.net/ruby/ as a good introduction to Ruby that's
more accessible to "visual people."

Since you've already got some programming experience you may be able to
just skim the first parts. Or, more likely, just read them for their
entertainment value :)

Good luck!
 
J

Jean Helou

My explanation or any other good explanations won't make sense if you
don't understand the singleton_class concept. There is a diagram which
explains it in the pickaxe book, if I remember correctly it's in the
duck typing section.

The singleton_class is like an instance-specific proxy for the class.
when you add a method to the singleton_class it is like modifying the
class of the instance but only for this particular instance.

now for your example :
class Important
def singleton_class
#get the singleton class for this instance
#A good explanation for the singleton class is available in the pickaxe book
#if i remember correctly it's in the duck typing section with a diagram
#which makes it all clear.
class << self; self; end
end

#define the class method which will be available as a dsl element.
#this is only "syntactic sugar" for your dsl to make it nicer
def self.set_this_value_method(value)
define_attr_method :this_value_method, value
end

#Then defines a new method called "name" in the singleton class of
the instance.
#note that here the instance is a class thus it adds a class method
def self.define_attr_method(name, value)
singleton_class.class_eval do
define_method(name) do
value
end
end

end


class SemiImportant < Important
set_this_value_method :something_or_anything
end

now you can call SemiImportant.this_value_method and it will return
:something_or_anything

jean
 
J

Jean Helou

M

MonkeeSage

Eye said:
class Important
def set_this_value_method(value)
end
end

class SemiImportant < Important
set_this_value_method :something_or_anything
end

Could some kind sould please, please take the time to explain the
fundamentals of Ruby's class/module functionality in regards to the
above example.

Since you asked for a fundimental level explaination I hope this helps
and doesn't seem pretentious:

A class is an object, and like all objects it can have different
attributes or "properties" which control how it behaves. In your
example the def keyword is used to give the Important class object a
special attribute called a method. That is basically just a block of
code that has a name and when that name is dereferenced the code is
executed and whatever arguments you pass the method become available
inside the code block (as well as any other methods or variables in the
context where you call the method from). So visually you can picture it
like this:

Important +
|
set_this_value_method ---> [code block]

But set_this_value_method can't be called directly from Important
(i.e., Important.set_this_value_method) because it wants an instance as
its caller rather than the actual class object. To make an instance you
use Important.new. So Important.new.set_this_value_method finds the
code block of set_this_value_method in the instance object of class
Important, and executes it. To just use the method with the class
object as the caller rather than an instance, you can use def
self.set_this_value_method.

In the second case, you're "subclassing" the Important class object:
class SemiImportant < Important. That is like taking all of the
attributes from Important and adding them to SemiImportant, as if you
had typed them in that class by hand.

Important ----+
SemiImportant +
|
set_this_value_method ---> [code block]

And since you then have "set_this_value_method :something_or_anything"
directly in the class body (i.e., outside of a method definition), as
soon as the interpreter parses the class definition it will run that
code. But since you are in the class object itself and not an instance,
you can't see set_this_value_method in the superclass (Important). But
if you use the class method (def self.set_this_value_method) in class
Important, then it will work correctly. Another option would be to
place this into a special method definition named initialize, which
will only be called when you create an instance of SemiImportant. And
in that case you must call the #super method to initialize the
superclass as well since you are overriding its constructor (the
initialize method).

So, either:

class Important
def self.set_this_value_method(value)
p value
end
end
class SemiImportant < Important
set_this_value_method 'foo' # called now
end

Or:

class Important
def set_this_value_method(value)
p value
end
end
class SemiImportant < Important
def initialize
super # initialize the superclass also
set_this_value_method 'foo'
end
end
SemiImportant.new # called now

I hope this wasn't too basic. I just didn't want to assume anything and
confuse you further (though I'm sure I probably did anyhow, what with
my babling)! But it's better too have much info you already know than
not enough that you dodn't. ;)

Regards,
Jordan
 
E

Eye Matz

unknown said:
So, you could do this:

class Important
def self.set_this_value_method(value) # note the 'self'
end
end

class SemiImportant < Important
set_this_value_method :x
end

Hi David,

Thanks for your reply! This was very much the way I was trying to do
things and expecting things to work, but when I did it, things did NOT
work. Go figure! :( Having taken yours & Jean's replies, I came up with
this heavily commented code, WITH lots of questions inside the comments
:)

==============

# base class that is extended by other classes for shared
methods/variables within the
# instance object
class Important
# Not sure if this is really needed, or how to refer/change this to a
@@class_variable ??
attr_accessor :my_value

# the method that will be used in sub-classes to set the internal
value
def self.set_this_value_method(value) # note the 'self'
# commented out use of class variable, since using a method is
better for
# possible expansion in the future
#@@my_value = value
# call to internal method that sets the value to the class variable
self.set_my_value(value)
end

# method that sets/(process) the actuall value
def self.set_my_value(value)
# using class variable here, but don't understand fully WHY?
# should ideally be normal instance variable, but don't know how
@@my_value = value
# why does not this type of syntax work ?
#self.my_value = value
end

# just dumps the value out
def get_my_value
@@my_value
end

def the_value
# using the method instead of the variable here
"the_value: my value is [#{get_my_value}]"
end
end

# sub-class that is based upon base class
class SemiImportant < Important
# here we set the internal 'my_value' variable to something
set_this_value_method 'something'
end

# creating a new instance
sc = SemiImportant.new
# why does this NOT show the my_value variable?
# how could I make it show this variable?
puts sc.inspect # => #<SemiImportant:0x35409c>

puts sc.get_my_value # => something
puts sc.the_value # => the_value: my value is [something]
puts sc.my_value # => nil
# with this call I can change the value of my_value
sc.class.superclass.set_my_value("Don't understand fully")
# but I cannot retrieve the value set with this call. WHY??
puts sc.class.superclass.my_value

==========

Hopefully someone else that is struggling with the same can find this
little snippet and hopefully save themselves some over-worked brain
cells.

If you (anyone) can answer the included questions I'd love to know the
answers.

Thanks again.
 
E

Eye Matz

Jean said:
now for your example :
class Important
def singleton_class
#get the singleton class for this instance
#A good explanation for the singleton class is available in the
pickaxe book
#if i remember correctly it's in the duck typing section with a
diagram
#which makes it all clear.
class << self; self; end
end

#define the class method which will be available as a dsl element.
#this is only "syntactic sugar" for your dsl to make it nicer
def self.set_this_value_method(value)
define_attr_method :this_value_method, value
end

#Then defines a new method called "name" in the singleton class of
the instance.
#note that here the instance is a class thus it adds a class method
def self.define_attr_method(name, value)
singleton_class.class_eval do
define_method(name) do
value
end
end

end


class SemiImportant < Important
set_this_value_method :something_or_anything
end

now you can call SemiImportant.this_value_method and it will return
:something_or_anything

jean

Hi Jean,

Thanks you VERY much for making that example clearer !

One minor error in it, though
def singleton_class
class << self; self; end
end

should be

def self.singleton_class
class << self; self; end
end

And Yes, I do understand the concept of Singleton classes, just NOT very
well in Ruby or in Ruby syntax. My problem is really more to do with the
grammatical logic, ie: when should I use this or that, or how should I
write this or that to get this or that result.

I haven't found a clear and concise account of that, and therefore I am
writing stuff like this [ Name are Matz I ] in Ruby, and things don't
work so well then.

Thank you for your help!
 
J

Jean Helou

Jean said:
now for your example :
class Important
def singleton_class
#get the singleton class for this instance
#A good explanation for the singleton class is available in the
pickaxe book
#if i remember correctly it's in the duck typing section with a
diagram
#which makes it all clear.
class << self; self; end
end

#define the class method which will be available as a dsl element.
#this is only "syntactic sugar" for your dsl to make it nicer
def self.set_this_value_method(value)
define_attr_method :this_value_method, value
end

#Then defines a new method called "name" in the singleton class of
the instance.
#note that here the instance is a class thus it adds a class method
def self.define_attr_method(name, value)
singleton_class.class_eval do
define_method(name) do
value
end
end

end


class SemiImportant < Important
set_this_value_method :something_or_anything
end

now you can call SemiImportant.this_value_method and it will return
:something_or_anything

jean

Hi Jean,

Thanks you VERY much for making that example clearer !

One minor error in it, though
def singleton_class
class << self; self; end
end

should be

def self.singleton_class
class << self; self; end
end

And Yes, I do understand the concept of Singleton classes, just NOT very
well in Ruby or in Ruby syntax. My problem is really more to do with the
grammatical logic, ie: when should I use this or that, or how should I
write this or that to get this or that result.

I haven't found a clear and concise account of that, and therefore I am
writing stuff like this [ Name are Matz I ] in Ruby, and things don't
work so well then.

Thank you for your help!
Maybe this will help since he asked himself the exact same question :
http://wanderingbarque.com/ruby/DynamicRuby.html

he understood the how but not the why... hope this helps.

jean
 
E

Eye Matz

Tim said:
Let me recommend Why's (Poignant) Guide to Ruby:
http://www.poignantguide.net/ruby/ as a good introduction to Ruby that's
more accessible to "visual people."

Hi Tim,

Thanks for your reply. Yes, I've tried Why's Guide about 30 times by
now, but I seriously lack a sense of humor it seems, or at least his
kind of humor.

I learn best by real life code examples that has plenty of comments
attached, so I can grep the logic within each line of the execution, and
I'm fairly certain I'm not alone in that.

Perhaps someone some day could create a Distilled version of Why's
Guide, for the rest of us?
 
E

Eye Matz

Jordan said:
Since you asked for a fundimental level explaination I hope this helps
and doesn't seem pretentious:

I hope this wasn't too basic. I just didn't want to assume anything and
confuse you further (though I'm sure I probably did anyhow, what with
my babling)! But it's better too have much info you already know than
not enough that you dodn't. ;)

Wow ! Thanks for taking the time Jordan, and all I can say is: "When
is your book being published ? I'll buy two copies."
 
M

MonkeeSage

Eye said:
Wow ! Thanks for taking the time Jordan, and all I can say is: "When
is your book being published ? I'll buy two copies."

LOL! Well, it would be a very short book since that's about the extent
of my knowledge, heh! David Black <from this very thread> has a book on
ruby out there [1], and he's a pretty smart dude. ;)

[1] http://www.manning.com/black/

Regards,
Jordan
 

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. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top