Can Ruby do this magic... elegantly

J

J2M

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
 
A

Austin Ziegler

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
 
A

ara.t.howard

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
 
T

Trans

J2M said:
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.
 
R

Robert Klemme

J2M said:
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
 
J

J2M

Robert, T, A & Austin;

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

Thank you all.
James
 
D

dblack

Hi--

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 | (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
 
R

Robert Klemme

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"

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
 
J

J2M

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

Trans

J2M said:
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.
 
R

Robert Klemme

Trans said:
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
 
J

J2M

Trans said:
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
 
J

J2M

Robert said:
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.
 

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,756
Messages
2,569,535
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top