tags:

views:

113

answers:

4

Lets say I have the following class:

  class Test
    attr_accessor :name
  end

When I create the object, I want to do the following:

  t = Test.new {Name = 'Some Test Object'}

At the moment it results in name being nil still. Is this possible?

Note: I don't want to add an initialiser

Thanks

Ben

A: 

The code you're indicating is passing parameters into the initialize function. You will most definitely have to either use initialize, or use a more boring syntax:

test = Test.new
test.name = 'Some test object'
Matchu
+1  A: 

As mentioned by others, the easiest way to do this would be to define an initialize method. If you don't want to do that, you could make your class inherit from Struct.

class Test < Struct.new(:name)
end

So now:

>> t = Test.new("Some Test Object")
=> #<struct Test name="Some Test Object">
>> t.name
=> "Some Test Object"
ry
+3  A: 

ok,

I came with a solution which use an initialize method but on the other side do exactly what you want.

class Test
  attr_accessor :name

  def initialize(init)
    init.each_pair do |key, val|
      instance_variable_set('@' + key.to_s, val)
    end
  end

  def display
    puts @name
  end

end

t = Test.new :name => 'hello'
t.display

happy ? :)


Alternative solution using inheritance. Note, with this solution, you doesn't need to explicitly declare the attr_accessor !

class CSharpStyle
  def initialize(init)
    init.each_pair do |key, val|
      instance_variable_set('@' + key.to_s, val)
      instance_eval "class << self; attr_accessor :#{key.to_s}; end"
    end
  end
end

class Test < CSharpStyle
  def initialize(arg1, arg2, *init)
    super(init.last)
  end
end

t = Test.new 'a val 1', 'a val 2', {:left => 'gauche', :right => 'droite'}
puts "#{t.left} <=> #{t.right}"
Niklaos
A: 

There is a general way of doing complex object initialization—passing block with necessary actions. This block could be evaluated in context of the object, so you have easy access to all instance variables, methods etc.

Continuing your example

class Test
    attr_accessor :name

    def initialize(&block)
        instance_eval(&block)
    end 
end

and then

t = Test.new { @name = 'name' }

or

t = Test.new do
    self.name = 'name'
    # other initialization, if needed
end

Note that this way does not require complex changing of initialize method (which is, in fact, one-liner).

ib