Forum: Ruby mixin classes (continuning from the last post)

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
hurcan solter (Guest)
on 2007-03-17 23:11
(Received via mailing list)
Although I am a seasoned C/C++ programmer(+10 years), I am relatively
new to the ruby (about 2 days) despite having some reservations(ruby
debugger should be theslowest thing in the world) i am otherwise very
impressed with the language, I intend to use Ruby for some code
generation task ,Everything was going well until i hit that roadblock

class REXML::Element
    include TSort
    def initialize
        @dependencies=[]
    end
    def tsort_each_node(&block)
        @elements.each(&block)
    end
    def tsort_each_child(node, &block)
        @dependencies.each(&block) if @dependencies.size>0
    end
end
 well as you can see, i need to topologically sort some nodes in an
xml file and there was a module Tsort in the
ruby. from what understand i need to extend to class  REXML::Element
to feed Tsort algorithm. I have no problems
with adding the methods but when i feed this new node to tsort() I get
something like this

undefined method `size' for nil:NilClass
H:/ruby/somCompiler.rb:112:in `tsort_each_child'
c:/ruby/lib/ruby/1.8/tsort.rb:204:in
`each_strongly_connected_component_from
c:/ruby/lib/ruby/1.8/tsort.rb:183:in
`each_strongly_connected_component'
c:/ruby/lib/ruby/1.8/rexml/element.rb:939:in `each'
c:/ruby/lib/ruby/1.8/rexml/xpath.rb:53:in `each'
c:/ruby/lib/ruby/1.8/rexml/element.rb:939:in `each'
H:/ruby/somCompiler.rb:109:in `tsort_each_node'
.....
>From what I understand i am unable to add  @dependencies array to the
REXML::Element.Is it not possible
or i am missing something terribly here?
Any help would be greatly appreciated..
Hurcan
Gary W. (Guest)
on 2007-03-17 23:35
(Received via mailing list)
On Mar 17, 2007, at 5:10 PM, hurcan solter wrote:

>     end
>     def tsort_each_node(&block)
>         @elements.each(&block)
>     end
>     def tsort_each_child(node, &block)
>         @dependencies.each(&block) if @dependencies.size>0
>     end
> end

Just a guess but I suspect your problem is that you've effectively
thrown away the initialize method for REXML::Element and replaced it
with your own.  I think you want:

alias __original_initialize initialize
def initialize(*args, &block)
   __original_initialize(*args, &block)
   @dependencies = []
end

This way you make sure the original version of initialize
executes as well as your new code.

Gary W.
Robert K. (Guest)
on 2007-03-18 00:26
(Received via mailing list)
On 17.03.2007 22:33, Gary W. wrote:
>>     include TSort
>
> This way you make sure the original version of initialize
> executes as well as your new code.

While this is true, at least @dependencies should be properly
initialized unless REXML::Element instances are not created via new.

There's another gotcha: by including TSort initialization might be
broken, if TSort defines initialize and does not propagate to the parent
class.

To OP: "if @dependencies.size>0" can be rewritten as "unless
@dependencies.empty?" which again is superfluous here: #each will take
care of empty collections.

Maybe you need provide more code.  From what you have shown so far it is
not clear to me why @dependencies would be nil.

Kind regards

  robert
hurcan solter (Guest)
on 2007-03-18 00:31
(Received via mailing list)
On Mar 17, 11:33 pm, Gary W. <removed_email_address@domain.invalid> wrote:
> > class REXML::Element
> > end
>
> This way you make sure the original version of initialize
> executes as well as your new code.
>
> Gary W.

On the contrary, it's the original version that executes not mine.
You see,it's the REXML module that creates the Element instance
and it calls the original constructor(if it's the term) not mine. I
erronously thought
i am effectively replacing the REXML:Element with my own version.
What i am trying to accomplish is adding to an existing class a new
instance variable
in its definition.

For example
require "rexml/document"
include REXML

class REXML::Element
     def some_method
         puts "some_method called"
     end

doc = Document.new File.open("mydoc.xml")
doc.each_element("somexmltag"){|node|    # i have no intervention here
REXML does all the stuff
    puts node.methods   #=>  ["some_method" "namespaces" "attributes"]
etc etc
    node.some_method   #=> some_method called
the above code snippet works, and adds a method to an existing class
in some other module
i just wonder is it possible to add some instance variable in same
manner?
Gary W. (Guest)
on 2007-03-18 02:01
(Received via mailing list)
It looks like REXML already provides the two
iterators you need to satisfy TSort.  Try this:

require 'rexml/document'
require 'tsort'

class REXML::Element
   include TSort
   def tsort_each_node(&block)
     each_recursive(&block)
   end
   def tsort_each_child(node, &block)
     node.each_child(&block) if node.respond_to?(:each_child)
   end
end

doc = REXML::Document.new <<EOS
<mydoc>
   <someelement attribute="nanoo">Text, text, text</someelement>
</mydoc>
EOS
p doc.tsort



Gary W.
hurcan solter (Guest)
on 2007-03-18 02:55
(Received via mailing list)
On Mar 18, 2:00 am, Gary W. <removed_email_address@domain.invalid> wrote:
>    end
> p doc.tsort
>
> Gary W.

well my sorting criteria something different from that.Consider this;

        <fixedRecordData name="EntityIdentifierStruct">
                <field name="FederateID" dataType="short int"/>
    <field name="FederateIdentifier"
dataType="FederateIdentifierStruct"/
>
    <field name="orientation" dataType="OrientationStruct"/>
  </fixedRecordData>
       <fixedRecordData name="FederateIdentifierStruct">
    <field name="SiteID" dataType="short int"/>
    <field name="ApplicationID" dataType="long int"/>
       </fixedRecordData>
  EntityIdentifierStruct depends on FederateIdentifierStruct
  and FederateIdentifierStruct depends on none (primitives not
important)
  and i also have to extract that denpendency information from child
  node attributes so one to one comparison wont work. So I have
  to compose a dependency graph first and keep it somewhere
  (I am thinking the element itself ,so the need for instance
variable) only
  then i can give it to tsort_each_child to iterate over..,
  hurcan
Gary W. (Guest)
on 2007-03-18 03:24
(Received via mailing list)
On Mar 17, 2007, at 8:55 PM, hurcan solter wrote:
> well my sorting criteria something different from that.Consider this;

Then you are going to have to implement Tsort over a different type
of collection.  Tsort uses the eql? method to compare nodes and I
don't think you want to mess around with REXML's notion of equality.

I think it would be better off iterating over all the nodes in the
document and creating a new dependency graph based on your criteria
and then applying Tsort to that new data structure instead of the
REXML data structure.

I'll admit to not looking too deep into your problem but I get the
feeling that you are applying TSort to the wrong data structure.

Gary W.
This topic is locked and can not be replied to.