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

Injector Versioning

In this release, we have introduced the definition of Injector Versioning.   We have included a separate Rspec file with examples on it, and have expanded the documentation to include a new section describing what it is and how it works. We hope you find it useful.


    # injector declaration
    injector :My_injector

    # first version
    #__________________
    My_injector() do                
      def bar
        :a_bar                                  # version bar.1
      end
      def foo
        # ...
      end
    end

    object1 = Object.new
    object1.enrich My_injector()                # apply --first snapshot
    object1.bar.should == :a_bar                # pass the test

    # second version
    #__________________
    My_injector() do                    
      def bar
        :some_larger_bar                        # version bar.2 --re-defines bar
      end
      def some_other_function
        # ...
      end
    end

    object2 = Object.new
    object2.enrich My_injector()                # apply --second snapshot
    object2.bar.should == :some_larger_bar      # pass the test

                                                ############################
    object1.bar.should == :a_bar                # object1 still using bar.1
                                                ############################
      

We have also started to set design limits to some of the other features for things which fall outside the domain of influence, and eliminated the binaries. Finally, we have improved the ReadMe file to be hopefully, more didactically oriented and easier to follow.

Once again we would like to thank the people who have contacted us for their input on how to better explain what Injectors are, and how to improve the documentation, and please continue to send your comments and  inquiries to the email address on the github page: https://github.com/LouHenryAlvarez/jackbox.

To use the product: gem install jackbox


Thanks again,

lha

Wednesday, January 21, 2015

Injector Orthogonality

In this release we have primarily relegated code in the examples name space to a second plane. It is assumed that if you want to run those examples you will know to enable them in the spec_helper, and that you will have the debugger appropriate for version of Ruby present on your machine as we have eliminated the dependencies.

We have also started a new set of examples on injectors that illustrate some additional properties of injectors we have cataloged under the description of orthogonality. They are intended to do just that, show some of the orthogonality available to injectors with respect to the rest of the library.

In this example we illustrate the various alternate and equivalent ways of working with Injector and member method declarations. Take a look:


class SomeClass
end

injector :Function do
   def meth
   end
end
SomeClass.inject Function()
# ...
SomeClass.eject Function() 



injector :Function
SomeClass.inject Function() do
   def meth
   end
end

# ...
SomeClass.eject Function() 




SomeClass.inject facet :Function do
   def meth
   end
end

# ...
SomeClass.eject Function() 

In this example we show how injectors like other mix-ins can be self extended/enriched, and they can under the right premises also be made to work in conjunction with #decorate and #with.


injector :tester 
                      
tester do                      
   enrich self          
                      
   def meth arg         
      arg * arg
   end
end
tester.meth(4).should == 16  


tester do
   decorate :meth do |arg|    
      super(arg) + 1
   end
end
tester.meth(3).should == 10  

with tester do         
   meth(5).should == 26
   def math arg1, arg2      
      meth(arg1 + arg2)
   end
end
tester.math(3, 2).should == 26 
  

A few last examples before we go.


class SomeClass
end

injector :Ortho

with Ortho() do
   def foo
   end
end

SomeClass.inject Ortho()

# ...


      

   
   

with SomeClass do
   include Ortho()
   extend Ortho(), Ortho()
end
     
# ....

with SomeClass do
   eject *injectors
end
      

  



with Ortho() do
   lets(:brand){'Special Brand'}

   def print
      puts brand
   end
end

enrich Ortho()
make.should == 'Special Brand'
#...
  

We hope you find the code illustrative, and please continue to send your comments and inquiries to the address on Github. We will do our best to answer them as quickly and knowledgeably as we can. Remember that some of this is uncharted territory and we are kind of making it up as we go.

Thanks so much for the people that have show interest, and kind regards to all.


lha

Wednesday, January 14, 2015

Can Closures be Modules?

Well, Ladies and Gents we would like to introduce you to our new library called Jackbox.  It toys with the ideas of closures as modules.  In it you'll find a series of new takes on ruby that are sure to spike you interest.  With it we have come up with a solution to the decorators handicap in ruby and introduced some new constructs for code injection.

 
class ClosureExpose

   some_value = 'some class level value'

   injector :capture do
      define_method :local_value do
         some_value
      end
   end

end

class SecondClass
   include ClosureExpose.capture
end

# the result
obj = SecondClass.new
obj.local_value.should == 'some class level value'

      

Or at the simple object level:
 
Thing = Object.new
Thang = Object.new

injector :agent

Thing.extend agent
Thang.extend agent

agent do                                          # on the fly definitions
   def capability
      'do the deed'
   end
   def location
      'main building'
   end
end

Thing.capability.should == 'do the deed'
Thang.location.should == 'main building'
      

Jackbox Google+

The main library function at this time centers around the concept of code Injectors. To make it easier to grasp the idea behind them, these can perhaps be thought of as a form of closures which can also serve as modules. Most of all Injectors propose some additional interesting properties to the idea of a mix-in. For instance, ...read on

Please feel free to use it free of charge and to send us your comments or inquiries.  Available from RubyGems.org for Linux, Mac, and Windows.  Just run: gem install jackbox.

More info here: https://github.com/LouHenryAlvarez/jackbox

Thank you.