"Luke A. Kanies" <luke / madstop.com> schrieb im Newsbeitrag
news:Pine.GSO.4.60.0408122129040.21400 / kirby.madstop.com...
> Hi all,
>
> I think this is a ruby question, as my problem is written in ruby, but
it
> is mostly just a programming question.
>
> I have two types of classes, objects and operations.  Each object has
one
> or more operation class associated with it (meaning that these are
> operations which can be executed on the objectgs).  When an object
> instance is created, it is created with one or more attributes, and as
> many operations as can be successfully run will also be created.
>
> For instance, given a File operation, and chmod, chown, and chgrp
> operations, if I create a File instance with only ownership information,
> then I can only create an instance of the chmod operation.

I've tried to translate your requirements and this is what I came up with
(note the two ways to execute an operation):

class ItemClass
  attr :operations

  def initialize
    @operations = {}
  end

  def add_operation(name, *attrs, &code)
    @operations[name.to_sym] = Operation.new(*attrs, &code)
    self
  end

  def create(attributes)
    inst = ItemInstance.new(self, attributes)

    @operations.each do |name, op|
      if op.mandatory_attributes.all? {|attr| attributes.has_key? attr}
        inst.operations[name] = op
      end
    end

    inst
  end
end

class ItemInstance
  attr_accessor :attributes, :operations

  def initialize(item_class, attributes)
    @item_class = item_class
    @attributes = attributes
    @operations = {}
  end

  def execute(op)
    operation = @operations[op.to_sym]
    raise NameError, "No such operation: #{op}" unless operation
    instance_eval &operation.code
  end

  def execute2(op)
    operation = @operations[op.to_sym]
    raise NameError, "No such operation: #{op}" unless operation
    operation.code.call(*operation.mandatory_attributes.map {|at|
attributes[at]})
  end
end


class Operation
  attr_reader :mandatory_attributes, :code

  def initialize(*attributes, &code)
    @mandatory_attributes = attributes
    @code = code
  end
end

# ----------------------------------------------

cl = ItemClass.new
cl.add_operation(:print_name, :name) do
  puts self.attributes[:name]
end

cl.add_operation(:print_name2, :name) do |name|
  puts name
end

cl.add_operation(:print_size, :size) do
  puts self.attributes[:size]
end

inst = cl.create(:name => "foo")
inst.execute :print_name # "foo"
inst.execute2 :print_name2 # "foo"
inst.execute :print_size # NameError


Alternatively you might be able to use Ruby classes as classes and Ruby
instances as instances.  That would have taken me some more thinking, but
it might be more elegant.

Kind regards

    robert