Generation of initialize

A

arcadiorubiogarcia

Hi everyone,

I'm new to Ruby. I'm looking for an elegant solution to a simple
problem.

I have some classes like this one in my code:


class A

attr_reader :a1, a2

def initialize(a1, a2)
@a1 = a1
@a2 = a2
end

end


I'm looking for a way in order not to have to define the initialize
method in each class. Struct doesn't fit my needs since due to single
inheritance I can't have any other superclass, and I would like to.

Any suggestions?

Thanks in advance.
 
T

Trans

Hi everyone,

I'm new to Ruby. I'm looking for an elegant solution to a simple
problem.

I have some classes like this one in my code:

class A

attr_reader :a1, a2

def initialize(a1, a2)
@a1 = a1
@a2 = a2
end

end

I'm looking for a way in order not to have to define the initialize
method in each class. Struct doesn't fit my needs since due to single
inheritance I can't have any other superclass, and I would like to.

Any suggestions?

You could create an attr_initializer, something like:

module MyInitSystem
# extend hack
def self.included(base)
base.extend ClassMethods
end

module ClassMethods
attr_reader :attr_initializers
def attr_initializer(*args)
@attr_initializers ||= []
@attr_initializers.concat(args)
attr_reader *args
end
end

def initialize(*args)
self.class.attr_initializers.each_with_index do |a,i|
instance_variable_set("@#{a}", args)
end
end
end

class A
include MyInitSystem

attr_initializer :a, :b
end

Albeit, I'd use a hash to populate my object by var name.

T.
 
A

Ashley Moran

Hi everyone,

I'm new to Ruby. I'm looking for an elegant solution to a simple
problem.

I have some classes like this one in my code:


class A

attr_reader :a1, a2

def initialize(a1, a2)
@a1 = a1
@a2 = a2
end

end


I'm looking for a way in order not to have to define the initialize
method in each class. Struct doesn't fit my needs since due to single
inheritance I can't have any other superclass, and I would like to.

Any suggestions?

Thanks in advance.

Hi

Don't know if this has been done before, but here's a quick stab I
took at it:

require 'generator'

module InitializesWith
def initializes_with(*params)
define_method :initialize do |*args|
iterator = SyncEnumerator.new(params, args)
iterator.each do |param, arg|
instance_variable_set "@#{param}", arg
end
end
end
end

class Class
include InitializesWith
end

class C
attr_reader :x, :y, :z
initializes_with :x, :y, :z
end

obj = C.new(1,2,3)

obj.x # => 1
obj.y # => 2
obj.z # => 3


Any good?

Ashley
 
A

arcadiorubiogarcia

Thank you both for your replies.

Just a minor detail regarding:
require 'generator'

module InitializesWith
def initializes_with(*params)
define_method :initialize do |*args|
iterator = SyncEnumerator.new(params, args)
iterator.each do |param, arg|
instance_variable_set "@#{param}", arg
end
end
end
end

class Class
include InitializesWith
end

This:

class C
attr_reader :x, :y, :z
initializes_with :x, :y, :z
end

evaluates to a Proc object, due to initializes_with implementation. I
guess it would be better to return nil at the end. Just a minor
aesthetic detail as I said.
 
T

Trans

Thank you both for your replies.

Just a minor detail regarding:






evaluates to a Proc object, due to initializes_with implementation. I
guess it would be better to return nil at the end. Just a minor
aesthetic detail as I said.

Return the attributes instead and you can do:

class C
attr_reader *initializes_with:)x, :y, :z)
end

T.
 
B

Brian Adkins

Hi everyone,

I'm new to Ruby. I'm looking for an elegant solution to a simple
problem.

I have some classes like this one in my code:

class A

attr_reader :a1, a2

def initialize(a1, a2)
@a1 = a1
@a2 = a2
end

end

I'm looking for a way in order not to have to define the initialize
method in each class. Struct doesn't fit my needs since due to single
inheritance I can't have any other superclass, and I would like to.

Are you looking for something like the following?

class A
auto_attr_reader :a1, :a2
end

a = A.new 7,8
puts a.a1 # -> 7
puts a.a2 # -> 8

You mentioned both wanting to be able to inherit from another class
and that you don't want to define initialize, so will all of the
classes you wish to inherit from not need initialization?
 
E

Erik Veenstra

It can be as simple as this.

gegroet,
Erik V. - http://www.erikveen.dds.nl/

----------------------------------------------------------------

class Class
def generate_initialize(*vars)
define_method:)initialize) do |*args|
vars.zip(args) do |var, arg|
instance_variable_set("@#{var}", arg)
end
end
end
end

class Foo
generate_initialize :a, :b, :c
end

p Foo.new(1, 2, 3)

----------------------------------------------------------------
 
B

Brian Adkins

It can be as simple as this.

gegroet,
Erik V. -http://www.erikveen.dds.nl/

----------------------------------------------------------------

class Class
def generate_initialize(*vars)
define_method:)initialize) do |*args|
vars.zip(args) do |var, arg|
instance_variable_set("@#{var}", arg)
end
end
end
end

class Foo
generate_initialize :a, :b, :c
end

p Foo.new(1, 2, 3)

Might as well define the attrs while you're at it so you can get the
data out :)
 
A

arcadiorubiogarcia

Hi again,

I'm trying to enhance the previous solution (shown again at the end).
I'd like to call the initialize method of the superclass from the
generated initialize. For the moment it's ok to call it without
parameters. Simply placing super inside the method definition doesn't
work. Can anyone explain me how to do it. Thanks in advance.

def initialize_with(*params)
define_method:)initialize) do |*args|
if args.size != params.size then
raise ArgumentError.new("wrong number of arguments"\
" (#{args.size} for #{params.size})")
end
params.zip(args) do |param, arg|
instance_variable_set("@#{param}", arg)
end
end
return params
end
 
T

Trans

Hi again,

I'm trying to enhance the previous solution (shown again at the end).
I'd like to call the initialize method of the superclass from the
generated initialize. For the moment it's ok to call it without
parameters. Simply placing super inside the method definition doesn't
work. Can anyone explain me how to do it. Thanks in advance.

Why doesn't it work?

def initialize_with(*params)
define_method:)initialize) do |*args|
if args.size != params.size then
raise ArgumentError.new("wrong number of arguments"\
" (#{args.size} for #{params.size})")
end
super() if defined?(super)
params.zip(args) do |param, arg|
instance_variable_set("@#{param}", arg)
end
end
return params
end

The "()" on super clears the auto-passing of parameters.

T.
 
J

Joel VanderWerf

Trans said:
Why doesn't it work?

def initialize_with(*params)
define_method:)initialize) do |*args|
if args.size != params.size then
raise ArgumentError.new("wrong number of arguments"\
" (#{args.size} for #{params.size})")
end
super() if defined?(super)
params.zip(args) do |param, arg|
instance_variable_set("@#{param}", arg)
end
end
return params
end

The "()" on super clears the auto-passing of parameters.

It seems to work (if this is what you meant):

module HasInitializeWith
def initialize_with(*params)
define_method:)initialize) do |*args|
if args.size != params.size then
raise ArgumentError.new("wrong number of arguments"\
" (#{args.size} for #{params.size})")
end
super() if defined?(super)
params.zip(args) do |param, arg|
instance_variable_set("@#{param}", arg)
end
end
return params
end
end

class A
extend HasInitializeWith
self.initialize_with :foo
end

p A.new(3) # ==> #<A:0xb7c28cbc @foo=3>
 
A

arcadiorubiogarcia

Thanks. It was the "()" on super.

It seems to work (if this is what you meant):

module HasInitializeWith
def initialize_with(*params)
define_method:)initialize) do |*args|
if args.size != params.size then
raise ArgumentError.new("wrong number of arguments"\
" (#{args.size} for #{params.size})")
end
super() if defined?(super)
params.zip(args) do |param, arg|
instance_variable_set("@#{param}", arg)
end
end
return params
end
end

class A
extend HasInitializeWith
self.initialize_with :foo
end

p A.new(3) # ==> #<A:0xb7c28cbc @foo=3>
 

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

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top