Rspec Screenshot

Rspec Screenshot
Copyright © 2014, 2015 LHA. All rights reserved.

Thursday, November 19, 2015

Release Candidate 2 (beta version)

Yesterday, we released Jackbox RC2.

With this release we have concluded the upgrade of the inheritance model and are gearing up for version 1.0.  The inheritance model in Jackbox now has to concurring aspects.  First, there is the now well known Versioned Inheritance.  This form of inheritance takes all pre-existing methods and makes them part of your new Injector version for use.

With RC2 however, we have added a new aspect to this design pattern. We have called it Just-in-Time Inheritance for lack of a better term (taking suggestions), and because it self-injects ancestor function just at it is need by your code.  In this way our modular closures are endowed now with a similar model of inheritance as you would find in classes, all happening in the mix-in however.

Also in this release we have made some improvements to the VMC (virtual method cache), numerous updates, introduced more examples, and once again updated the documents.  One major perhaps incompatible change is the reversal in the ordering of how injectors are added and presented.  We are now following in line with Ruby which handles ancestor precedence in a left to right order instead of the other way around. 

Once again we would like to Thank everyone who has shown their support through the numerous emails we have received and, also once again we hope we have met with your expectations.

Please visit us: http://jackbox.us


Thank you, kindly,

Lou

Wednesday, November 18, 2015

JIT Inheritance

This flavor of the inheritance model allows our modular closures to have similar properties to the inheritance of classes. With it you can expect to have access to its super members as part of the call, just like you would with classes. In addition to the inheritance resulting from versioning, JIT inheritance presents a more complete scenario adding color to the picture painted by code injectors. The key takeaway here is this: Code Injectors are mix-ins that share a similar inheritance model with classes. You can version them to gain access to versioned inheritance or you can override its members to access an ancestor chain comprised of all previous tags. As always we will use some example code to illustrate:


    # 
    # Our Modular Closure
    # 
    Tag1 = trait :Tagger do
        def m1
            1
        end

        def m2
            :m2
        end
    end

    # 
    # Normal Versioned Injector inheritance
    # 
    Tagger do
        def other                   
            'other'                   # -- same ancestors as before
        end                                 
    end

    expect(Tagger().ancestors).to eql( [Tagger()] )

    # test it

    o  = Object.new.extend(Tagger())

    # inherited
    o.m1.should == 1
    o.m2.should == :m2

    # current
    o.other.should == 'other'


    #
    # JIT inheritance
    # 
    Tag2 = Tagger do
        def m1                        # The :m1 override invokes JIT inheritance
            super + 1                 # -- Tag1 is summoned into ancestor chain
        end                           # -- allows the use of super

        def m3                          
            'em3'
        end
    end

    # test it

    p = Object.new.extend(Tag2)

    # JIT inherited
    p.m1.should == 2

    # regular inheritance
    p.m2.should == :m2
    p.m3.should == 'em3'
    p.other.should == 'other'

    expect(Tagger().ancestors).to eql( [Tagger(), Tag1] )
    expect(Tag2.ancestors).to eql( [Tag2, Tag1] )
      

For more on this please see the rspec files in the project page or on the gem itself.

As always, Thank you kindly.

Monday, October 26, 2015

Injector Directives: collapse and rebuild

Continuing with our series: This time around we want to start a series on Injector Directives. We will begin by showing injector code pre-withdrawal and then its subsequent re-instatement. This is a feature that allows code to stay dormant until needed. Note: We use injector directives :collapse/:silence and :rebuild/:active. Take a look a the following example code:

    trait :PreFunction do           # Pre to main evaluation
      def _pre_
        puts '++++++++++'
      end
    end

    trait :PosFunction do           # Pos to main evaluation
      def _pos_
        puts '=========='
      end
    end

    # Our class

    class Model                     # Injector application is muted!

      inject PreFunction(:silence)  
      inject PosFunction(:silence) 

      def meth arg
        _pre_
        puts arg * arg
        _pos_
      end
    end

    # test

    obj = Model.new                 # functionality is silent !!
    obj.meth( 2 )
    # ==> 4


    PreFunction(:active)            # functionality is activated
    PosFunction(:active)

    # test
    
    obj.meth( 2 )
    # ==> ++++++++++
    # ==> 4
    # ==> ==========
  

Friday, September 11, 2015

Decorators in Scale

Jackbox allows the scaling of Decorators onto the entire object. Traditionally this has been a problem for Ruby. There have been some partial solutions published by different authors, but they all fall short of the true GOF standard, posing some problems for their effective use and implementation. Here are a couple of references on the subject matter for your review: Evaluating Alternative Decorator Implementations and Decorator Pattern in Ruby.

But, with Jackbox we overcome these problems and give a new spin to this design pattern with Ruby. The Injector metaphor is the key, take a look at this code:

    # our class (can be anything..., think html rendering, or string processing)

    class Coffee
        def cost
            1.50
        end
    end

    # our decorators

    trait :milk do                   # first decorator
        def cost
            super() + 0.30
        end
    end
    trait :vanilla do                # second decorator
        def cost
            super() + 0.15
        end
    end

    # the coffee

    cup = Coffee.new.enrich(milk, vanilla, vanilla)      
    # the list can go on....

    # our tests

    cup.cost.should == 2.10
    cup.injectors.sym_list.should == [:milk, :vanilla, :vanilla]

    # coffee is coffee

    cup.should be_instance_of(Coffee)                 
      
Multiple applications of the same decorator are a cinch, just add them to the end of the list. Class identity remains untouched, a coffee is a coffee after all. Removing a decorator can be done by calling #eject or sending Injector Directives, and most of all the code is clean and concise. For more on Injectors and their function see the main page or the project rspec files.

Wednesday, September 9, 2015

Simple Decorator

This feature of Jackbox allows you place decorators on individual methods without to much fuss, it gives you a nice alternative to #alias_method_chain in certain contexts. It also allows the use of #super and to revert back if necessary. This feature can also be used on instances even after an existing class decoration. Here is the code:

    # instance decoration

    one.decorate :foo do |arg|
      super() + ' ' + arg
    end

    one.foo(' after').should == 
      'foo decoration after'

    one.undecorate :foo

    one.foo.should == 'foo decoration'




        

    #class decoration
    
    class One
      def foo
        'foo'
      end
    end

    class One
      decorate :foo do
        super() + ' ' + 'decoration'
      end
    end

    one = One.new
    one.foo.should == 'foo decoration'
      
It also works like so:

    Object.decorate :inspect do
      super() + " is your object"
    end
    Object.new.inspect.should =~ /is your object/
      

Sunday, September 6, 2015

An Alternative Way to Refine a Class

This Jackbox feature provides an alternative way to refine classes, that also illustrates some additional uses of our Modular Closures©/Code Injectors. For this to happen, we rely once again on our trusty method #lets. We will delve right into the code:

    module Work
     lets String do
      def self.new(*args)
       "+++#{super}+++"
      end
     end
    end

    class WorkAholic
     include Work
 
     def work_method
      String('Men-At-Work')
     end
    end

    str = WorkAholic.new.work_method              # Our String re-class
    str.should == '+++Men-At-Work+++'

    str = String.new('men-at-work')               # Regular String
    str = 'men-at-work'

    str = String('Men-At-Work')                   # Regular Kernel version
    str = 'Men-At-Work'
  

Two important things here are first that String is re-classed only within the scope of Work, and second that the top level String is left untouched. In addition, each name space can have its own private re-class of String. We can have a specialized version of the class for each name space and avoid un-necessarily polluting any other name spaces. Bringing Injectors into the mix we can "refine" this pattern a little more. Take a look at the following:

    # Injector declaration

    Sr1 = trait :StringRefinements do              # use tagging
      lets String do
          def self.new *args, &code
              super(*args, &code) + ' is a special string'
          end
      end
    end

    class OurClass
      include Sr1                                 # our tag

      def foo_bar
          String('foo and bar')
      end
    end

    c = OurClass.new

    c.foo_bar.class.should == String
    c.foo_bar.should == 'foo and bar is a special string'


    # A common jack

    jack :Log do
      require 'logger'
      def to_log
        Logger.new($stdout).warn(self)
      end
    end

    StringRefinements do
      String() do
      
        def extra                         # add more stuff into current re-class
            :extra
        end

        inject Log()
      end
    end

    c.foo_bar.should == 'foo and bar is a special string'
    c.foo_bar.extra.should == :extra

    $stdout.should_receive(:write).at_least(1) 
    c.foo_bar.to_log


    # New Version

    Sr2 = StringRefinements do                    # a new tag
    
      lets String do                              # a new re-class
        def to_s
            super + '****'
        end

        inject Log()
      end
    end

    # c is still the same

    c.foo_bar.should == 'foo and bar is a special string'
    c.foo_bar.extra.should == :extra


    class OurOtherClass
      include Sr2                         # Apply new tag to another class

      def foo_bar
          String('foo and bar')
      end
    end

    d = OurOtherClass.new

    d.foo_bar.should == 'foo and bar'
    d.foo_bar.to_s.should == 'foo and bar****'
    expect{ d.foo_bar.extra }.to raise_error(NoMethodError)

    d.foo_bar.to_log
       

This allows us to create versioned re-classes. Since re-classes are methods, albeit special constructor methods, these can mix in with other methods in the modular closure version giving you many variants. You can have multiple re-class versions, or can use them together with other patterns.

Furthermore, it is easy to determine if a re-class exists and use it instead of the original class by simply testing for its presence in the given namespace in order to change its behavior through further injector applications. Check out the following snippets:

    reclass? String

    # or ...

    module MyModule
        reclass? String
    end

    # also ...


    #############################
    # Use a certain re-classing if it exists
    # if not use the regular original class
    #############################

    String("my string") rescue String.new("my string")


  

So in general terms re-classes offer an alternative way to create and use certain refinements to a class which also makes use of the other properties of our modular closures/injectors. Finally, re-classes work with versions of Ruby **1.9.3 thru 2.2.1**.

Thanks,

lha

Wednesday, August 12, 2015

Release Candidate 1 (alpha version)

Ladies and Gentlemen we have the pleasure to announce Jackbox RC1.  

With this release we have completed our integration into the Ruby base.  We have also concluded a number of enhancements and addressed a couple of previously standing issues.

The specification for Injector behavior under inheritance is now complete.  The spec on Injector naming and tags is also done.   With this release we also complete the specification on Injector Versioning, and the introspection API.  We introduce the concept of Soft Tags, and a new coding pattern we have termed Transformers Pattern.  We also introduce a new alias to the #injector function simply named #jack which fits in line with the product name of Jackbox.  

There is now a trace of the target hosted Injectors kept through an Injector #history also aliased to #versions.   Moreover there is a sub-trace to only the soft-tagged versions through the #tags method.  This history also holds a pointer to every #precedent in the chain.  

The basic method #with has been refined to evaluate definitions for a module using #module_eval and has been improved in some other subtle aspects.  The display of 'jacks' on the console was also improved to hopefully provide a more compact and more legible form.   

With this release we also introduced the concept of equality to Injectors.  Finally, this release starts the exploration on using Weak References for Injectors.  We’ll see how that goes.

For a more complete list of changes and enhancements, please refer to the CHANGES.txt on the gem itself as well as to the rspec files and README.

I would like to thank once again all the people who have shown their support and interest, and wish everyone happy coding.

lha
  

Wednesday, May 20, 2015

Injectors-to-the-Top

In this months release we continue to bring Jackbox more in line the Ruby base.  We have addressed a couple of issues that existed with use of Injectors at the Ruby top-level.  The Injector metaphor now works consistently all the way through. The basic idea to remember at the top is that #inject does its work on the Object class while #enrich does so in the 'main' instance.


    injector :Major do
      def meth
        1
      end
    end

    inject Major()

    meth.should == 1

    eject :Major

    expect{meth}.to raise_error(NoMethodError) 

      

    # Because 'main' is an Object instance, granted
    # a (special Object instance), the previous call 
    # to #eject operates like in any other instance
    # and ejects #Major only for the 'main' instance


    Object.new.meth.should == 1                                      

    # To actually eject from Object

    Object.eject :Major

    expect{Object.new.meth}.to raise_error(NoMethodError) 

      
We have also fixed some issues that existed with ancestor chains, have introduced new methods to #inspect, #to_s, and #show Injectors, and once again cleaned up the examples, code, and the readme file.  This last one continues to grow, and hopefully is a good read.

We have also decided to put-off, the Jackbox Challenge until we have a 1.0 release candidate which should be coming.  Unfortunately, we have to do development in between other the things we are involved.  But, it I promise it won't be long.

Once again Many Thanks to all the wonderful people who have shown their interest and support.  Don't forget to visit our webpage: http://jackbox.us.

To install just type: gem install jackbox

lha

Tuesday, January 27, 2015

PURE Ruby Code Injectors

In this release we have continued the trend towards integration with the Ruby base, and have eliminated all external dependencies from the main library.  It is now all PURE Ruby.  The only dependencies remaining are now the ones needed for the command line utility.

We have also added some more examples, and cleaned up others, and once again tried to improve the ReadMe file.  We are letting everyone know that from now on we will be doing our updates hopefully on a monthly basis or until a release candidate is available.

We would also like to take this opportunity to announce we will be conducting what we have termed a Jackbox Challenge in the coming month.  We hope it will be to everyone's liking and interest.  We will be offering a prize for the winner.  We are still working out the contest rules, but hope to have them ready soon.

Thank you again to all the people who have shown their interest and support, and we hope to see you soon on a website near you.

For more info: http://louhenryalvarez.github.io/jackbox/

Lou

Friday, January 23, 2015

Injector Naming/Tagging

In this release, we primarily increased the integration with the Ruby base and have eliminated the NEED to use #inject/#enrich although these are still recommended for injectors from a cognitive standpoint. However, injectors now accept and it is now completely possible to just use #include/#extend, for which the former are now just aliases, even with Injector Versioning.
Also, we continued the trend to set some design limits on the code, tried to manifest those in the form of Jackbox::UserError, improved injector directive algorithms, cleaned up some of the specs and comments, and once again have improved the Readme file.  Finally, the concept of version naming/tagging was introduced.

    injector :Bar

    Tag = Bar do
      def foo_bar
        'a bar and foo'
      end
    end

    AnotherTag = Bar do
      def foo_bar
        'a foo and bar'
      end
    end


    class One
      inject Tag                                        # first version tag
    end
    One.new.foo_bar.should == 'a bar and foo'


    class Two
      inject AnotherTag                                 # second version tag
    end
    Two.new.foo_bar.should == 'a foo and bar'
   
Please visit us at: https://github.com/LouHenryAlvarez/jackbox
Once again we would like to thank the people who have shown interest, and have sent us their comments. We hope we can keep up with your expectations.  We will certainly try our best to do so.

Thank you,

lha