mixit 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +6 -12
- data/lib/mixit/version.rb +1 -1
- data/lib/mixit.rb +82 -45
- data/test/test_mixit.rb +14 -34
- metadata +8 -8
    
        data/README.md
    CHANGED
    
    | @@ -37,21 +37,15 @@ __WHY?__ | |
| 37 37 |  | 
| 38 38 | 
             
            __EXAMPLES__
         | 
| 39 39 |  | 
| 40 | 
            -
            Temporarily mix ' | 
| 40 | 
            +
            Temporarily mix 'SomeModule' onto the 'self' referenced by _block_:
         | 
| 41 41 |  | 
| 42 | 
            -
                 | 
| 43 | 
            -
                   | 
| 42 | 
            +
                Mixit.temporarily SomeModule, :scope => self do 
         | 
| 43 | 
            +
                  p self.class  # => Object
         | 
| 44 | 
            +
                  p respond_to?(:some_mixed_method) # => true  
         | 
| 44 45 | 
             
                end
         | 
| 45 46 |  | 
| 46 | 
            -
                 | 
| 47 | 
            -
             | 
| 48 | 
            -
                Mixit.temporarily(Foo, block) do 
         | 
| 49 | 
            -
                  p self.class        # => Object
         | 
| 50 | 
            -
                  p respond_to?(:bar) # => true  
         | 
| 51 | 
            -
                end
         | 
| 52 | 
            -
             | 
| 53 | 
            -
                p self.class        # => Object
         | 
| 54 | 
            -
                p respond_to?(:bar) # => false
         | 
| 47 | 
            +
                p self.class # => Object
         | 
| 48 | 
            +
                p respond_to?(:some_mixed_method) # => false
         | 
| 55 49 |  | 
| 56 50 | 
             
            __INSTALL__
         | 
| 57 51 |  | 
    
        data/lib/mixit/version.rb
    CHANGED
    
    
    
        data/lib/mixit.rb
    CHANGED
    
    | @@ -5,60 +5,78 @@ class Mixit | |
| 5 5 |  | 
| 6 6 | 
             
              class << self
         | 
| 7 7 | 
             
                # 
         | 
| 8 | 
            -
                # @overload mix(*modules,  | 
| 9 | 
            -
                #   Temporarily extends  | 
| 8 | 
            +
                # @overload mix(*modules, options, &block) 
         | 
| 9 | 
            +
                #   Temporarily extends a scope with methods from __modules__.
         | 
| 10 10 | 
             
                #
         | 
| 11 11 | 
             
                #   @param [Module] modules
         | 
| 12 | 
            -
                #     A variable number of modules to extend the  | 
| 12 | 
            +
                #     A variable number of modules to extend the scope with.
         | 
| 13 13 | 
             
                #
         | 
| 14 | 
            -
                #   @param  | 
| 15 | 
            -
                #     (see Mixit#mix_onto) 
         | 
| 14 | 
            +
                #   @param [Hash] options 
         | 
| 16 15 | 
             
                #   
         | 
| 16 | 
            +
                #   @option options [Binding, Proc, Object] :scope 
         | 
| 17 | 
            +
                #     The scope to extend.
         | 
| 18 | 
            +
                #
         | 
| 17 19 | 
             
                #   @param block 
         | 
| 18 | 
            -
                #     (see Mixit# | 
| 20 | 
            +
                #     (see Mixit#mix!)
         | 
| 19 21 | 
             
                #   
         | 
| 20 22 | 
             
                #   @yieldparam object 
         | 
| 21 | 
            -
                #     (see Mixit# | 
| 23 | 
            +
                #     (see Mixit#mix!)
         | 
| 24 | 
            +
                #
         | 
| 25 | 
            +
                #   @raise [ArgumentError] 
         | 
| 26 | 
            +
                #     If the :scope option is missing.
         | 
| 22 27 | 
             
                #
         | 
| 23 28 | 
             
                #   @return [void]
         | 
| 24 29 | 
             
                #     
         | 
| 25 30 | 
             
                def mix(*args, &block)
         | 
| 26 | 
            -
                   | 
| 27 | 
            -
                   | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
                     | 
| 31 | 
            +
                  options = args.pop
         | 
| 32 | 
            +
                  modules = args
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  if options.has_key?(:scope)
         | 
| 35 | 
            +
                    scope = options[:scope]
         | 
| 31 36 | 
             
                  else
         | 
| 32 | 
            -
                     | 
| 33 | 
            -
                    modules  = args
         | 
| 37 | 
            +
                    raise ArgumentError, 'missing :scope option.'
         | 
| 34 38 | 
             
                  end
         | 
| 35 | 
            -
             | 
| 36 | 
            -
                  new(modules). | 
| 39 | 
            +
             | 
| 40 | 
            +
                  new(scope, modules).mix!(&block)
         | 
| 37 41 | 
             
                end
         | 
| 38 42 | 
             
                alias_method :temporarily, :mix
         | 
| 39 43 | 
             
              end
         | 
| 40 44 |  | 
| 41 | 
            -
             | 
| 42 45 | 
             
              #
         | 
| 43 46 | 
             
              # @return [Array<Module>] 
         | 
| 44 47 | 
             
              #   An Array of Module objects.
         | 
| 45 48 | 
             
              #
         | 
| 46 49 | 
             
              attr_reader :modules
         | 
| 47 | 
            -
             | 
| 50 | 
            +
             
         | 
| 51 | 
            +
              #
         | 
| 52 | 
            +
              # @return [Object]
         | 
| 53 | 
            +
              #   The scope.
         | 
| 54 | 
            +
              #
         | 
| 55 | 
            +
              attr_reader :scope
         | 
| 56 | 
            +
             | 
| 57 | 
            +
              #
         | 
| 58 | 
            +
              # @param [Binding, Proc, Object] scope
         | 
| 59 | 
            +
              #   A scope to extend.
         | 
| 48 60 | 
             
              #
         | 
| 49 61 | 
             
              # @param [Array<Module>] modules
         | 
| 50 62 | 
             
              #   An Array of Module objects.
         | 
| 51 63 | 
             
              #
         | 
| 52 | 
            -
              def initialize | 
| 64 | 
            +
              def initialize scope, modules
         | 
| 53 65 | 
             
                @modules = modules
         | 
| 54 66 | 
             
                @clones  = []
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                case scope
         | 
| 69 | 
            +
                when Binding
         | 
| 70 | 
            +
                  @scope = scope.eval "self"
         | 
| 71 | 
            +
                when Proc
         | 
| 72 | 
            +
                  @scope = scope.binding.eval "self"
         | 
| 73 | 
            +
                else
         | 
| 74 | 
            +
                  @scope = scope
         | 
| 75 | 
            +
                end
         | 
| 55 76 | 
             
              end
         | 
| 56 77 |  | 
| 57 78 | 
             
              #
         | 
| 58 | 
            -
              # Temporarily extends  | 
| 59 | 
            -
              #
         | 
| 60 | 
            -
              # @param [Object] receiver 
         | 
| 61 | 
            -
              #   An object to temporarily extend.
         | 
| 79 | 
            +
              # Temporarily extends {#scope} with methods from {#modules modules}. 
         | 
| 62 80 | 
             
              #
         | 
| 63 81 | 
             
              # @param [Proc] block
         | 
| 64 82 | 
             
              #   A block executed while the object is extended. 
         | 
| @@ -68,48 +86,67 @@ class Mixit | |
| 68 86 | 
             
              #
         | 
| 69 87 | 
             
              # @return [void]
         | 
| 70 88 | 
             
              #
         | 
| 71 | 
            -
              def  | 
| 89 | 
            +
              def mix! &block
         | 
| 72 90 | 
             
                if block.arity == 1
         | 
| 73 | 
            -
                  block.call extend!( | 
| 91 | 
            +
                  block.call extend!(true)
         | 
| 74 92 | 
             
                else
         | 
| 75 93 | 
             
                  begin
         | 
| 76 | 
            -
                     | 
| 77 | 
            -
                    extend!(receiver, false).instance_eval(&block)
         | 
| 94 | 
            +
                    extend!(false).instance_eval(&block)
         | 
| 78 95 | 
             
                  ensure
         | 
| 79 | 
            -
                     | 
| 80 | 
            -
             | 
| 81 | 
            -
                    end
         | 
| 82 | 
            -
             | 
| 83 | 
            -
                    @clones.each do |mod|
         | 
| 84 | 
            -
                      mod.instance_methods(false).each do |meth|
         | 
| 85 | 
            -
                        mod.send(:remove_method, meth)
         | 
| 86 | 
            -
                      end
         | 
| 87 | 
            -
                    end
         | 
| 96 | 
            +
                    remove_methods!
         | 
| 97 | 
            +
                    trigger_callback!
         | 
| 88 98 | 
             
                  end
         | 
| 89 99 | 
             
                end
         | 
| 90 100 | 
             
              end
         | 
| 91 101 |  | 
| 92 102 | 
             
              #
         | 
| 93 | 
            -
              # Extends  | 
| 94 | 
            -
              #
         | 
| 95 | 
            -
              # @param receiver 
         | 
| 96 | 
            -
              #   (see Mixit#mix_onto)
         | 
| 103 | 
            +
              # Extends {#scope} with the methods from {#modules modules}.
         | 
| 97 104 | 
             
              #
         | 
| 98 105 | 
             
              # @param [Boolean] to_be_cloned
         | 
| 99 | 
            -
              #   If true, a clone of the  | 
| 106 | 
            +
              #   If true, a clone of the scope is extended.
         | 
| 100 107 | 
             
              #
         | 
| 101 108 | 
             
              # @return [Object]
         | 
| 102 109 | 
             
              #   Returns the extended object.
         | 
| 103 110 | 
             
              #
         | 
| 104 | 
            -
              def extend! | 
| 105 | 
            -
                if  | 
| 106 | 
            -
                   | 
| 111 | 
            +
              def extend! clone_scope 
         | 
| 112 | 
            +
                if clone_scope
         | 
| 113 | 
            +
                  scope = @scope.clone
         | 
| 114 | 
            +
                else
         | 
| 115 | 
            +
                  scope = @scope
         | 
| 107 116 | 
             
                end
         | 
| 108 117 |  | 
| 109 118 | 
             
                @clones = @modules.map(&:clone)
         | 
| 110 | 
            -
                @clones.inject( | 
| 119 | 
            +
                @clones.inject(scope) { |obj, mod| obj.extend(mod) }
         | 
| 111 120 | 
             
              end
         | 
| 112 121 | 
             
              private :extend!
         | 
| 113 122 |  | 
| 123 | 
            +
              #
         | 
| 124 | 
            +
              # Remove methods used to extend {#scope} from module(s).  
         | 
| 125 | 
            +
              #
         | 
| 126 | 
            +
              # @return [void]
         | 
| 127 | 
            +
              #
         | 
| 128 | 
            +
              def remove_methods!
         | 
| 129 | 
            +
                @clones.each do |clone|
         | 
| 130 | 
            +
                  clone.instance_methods(false).each do |meth|
         | 
| 131 | 
            +
                    clone.send(:remove_method, meth)
         | 
| 132 | 
            +
                  end
         | 
| 133 | 
            +
                end
         | 
| 134 | 
            +
              end
         | 
| 135 | 
            +
              private :remove_methods!
         | 
| 136 | 
            +
             | 
| 137 | 
            +
              #
         | 
| 138 | 
            +
              # Calls cleanup! on module(s) used to extend a scope.
         | 
| 139 | 
            +
              #
         | 
| 140 | 
            +
              # @return [void]
         | 
| 141 | 
            +
              #
         | 
| 142 | 
            +
              def trigger_callback!
         | 
| 143 | 
            +
                @clones.each do |clone|
         | 
| 144 | 
            +
                  if clone.respond_to?(:cleanup!)
         | 
| 145 | 
            +
                    clone.cleanup!(@scope)  
         | 
| 146 | 
            +
                  end
         | 
| 147 | 
            +
                end
         | 
| 148 | 
            +
              end
         | 
| 149 | 
            +
              private :trigger_callback!
         | 
| 150 | 
            +
             | 
| 114 151 | 
             
            end
         | 
| 115 152 |  | 
    
        data/test/test_mixit.rb
    CHANGED
    
    | @@ -6,10 +6,6 @@ context Mixit do | |
| 6 6 | 
             
                    def callme
         | 
| 7 7 | 
             
                      :ok
         | 
| 8 8 | 
             
                    end
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                    def set_ivar
         | 
| 11 | 
            -
                      @set_ivar = 'asdf'
         | 
| 12 | 
            -
                    end
         | 
| 13 9 | 
             
                  end
         | 
| 14 10 | 
             
                end
         | 
| 15 11 |  | 
| @@ -17,7 +13,7 @@ context Mixit do | |
| 17 13 | 
             
                  it 'must provide access to mixed-in methods' do        
         | 
| 18 14 | 
             
                    block = proc { }
         | 
| 19 15 |  | 
| 20 | 
            -
                    Mixit.mix(@module, block) do 
         | 
| 16 | 
            +
                    Mixit.mix(@module, :scope => block) do 
         | 
| 21 17 | 
             
                      callme.must_equal(:ok)
         | 
| 22 18 | 
             
                    end
         | 
| 23 19 | 
             
                  end
         | 
| @@ -26,7 +22,7 @@ context Mixit do | |
| 26 22 | 
             
                    block = proc { }
         | 
| 27 23 | 
             
                    local = :ok
         | 
| 28 24 |  | 
| 29 | 
            -
                    Mixit.mix(@module, block) do 
         | 
| 25 | 
            +
                    Mixit.mix(@module, :scope => block) do 
         | 
| 30 26 | 
             
                      local.must_equal(:ok)
         | 
| 31 27 | 
             
                    end
         | 
| 32 28 | 
             
                  end
         | 
| @@ -35,7 +31,7 @@ context Mixit do | |
| 35 31 | 
             
                    def callme_() :ok end
         | 
| 36 32 | 
             
                    block = proc { }
         | 
| 37 33 |  | 
| 38 | 
            -
                    Mixit.mix(@module, block) do
         | 
| 34 | 
            +
                    Mixit.mix(@module, :scope => block) do
         | 
| 39 35 | 
             
                      callme_.must_equal(:ok)
         | 
| 40 36 | 
             
                    end
         | 
| 41 37 | 
             
                  end
         | 
| @@ -43,39 +39,23 @@ context Mixit do | |
| 43 39 | 
             
                  it 'must remove instance variables added by the calling block.' do
         | 
| 44 40 | 
             
                    block = proc { }
         | 
| 45 41 |  | 
| 46 | 
            -
                     | 
| 47 | 
            -
                       | 
| 42 | 
            +
                    @module.instance_eval do
         | 
| 43 | 
            +
                      def cleanup!(scope)
         | 
| 44 | 
            +
                        scope.send(:remove_instance_variable, :@ok)
         | 
| 45 | 
            +
                      end
         | 
| 48 46 | 
             
                    end
         | 
| 49 47 |  | 
| 50 | 
            -
                     | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
                  it 'must remove instance variables added by mixed-in modules.' do 
         | 
| 54 | 
            -
                    block = proc { }
         | 
| 55 | 
            -
             | 
| 56 | 
            -
                    Mixit.mix(@module, block) do
         | 
| 57 | 
            -
                      set_ivar
         | 
| 58 | 
            -
                      instance_variable_defined?(:@set_ivar).must_equal(true)
         | 
| 48 | 
            +
                    Mixit.mix(@module, :scope => block) do 
         | 
| 49 | 
            +
                      @ok = :no
         | 
| 59 50 | 
             
                    end
         | 
| 60 51 |  | 
| 61 | 
            -
                    instance_variable_defined?(:@ | 
| 62 | 
            -
                  end
         | 
| 63 | 
            -
             | 
| 64 | 
            -
                  it 'must not remove pre-existing instance variables.' do
         | 
| 65 | 
            -
                    block = proc {}
         | 
| 66 | 
            -
                    @ok   = :ok
         | 
| 67 | 
            -
             | 
| 68 | 
            -
                    Mixit.mix(@module, block) do
         | 
| 69 | 
            -
                      nil
         | 
| 70 | 
            -
                    end
         | 
| 71 | 
            -
                    
         | 
| 72 | 
            -
                    instance_variable_defined?(:@ok).must_equal(true)
         | 
| 52 | 
            +
                    instance_variable_defined?(:@ok).must_equal(false)
         | 
| 73 53 | 
             
                  end
         | 
| 74 54 |  | 
| 75 | 
            -
             | 
| 55 | 
            +
                 it 'must remove methods added by mixed-in modules.' do
         | 
| 76 56 | 
             
                    block = proc {}
         | 
| 77 57 |  | 
| 78 | 
            -
                    Mixit.mix(@module, block) do
         | 
| 58 | 
            +
                    Mixit.mix(@module, :scope => block) do
         | 
| 79 59 | 
             
                      nil
         | 
| 80 60 | 
             
                    end
         | 
| 81 61 |  | 
| @@ -87,7 +67,7 @@ context Mixit do | |
| 87 67 | 
             
                  it 'must provide access to mixed-in methods.' do
         | 
| 88 68 | 
             
                    block = proc {}
         | 
| 89 69 |  | 
| 90 | 
            -
                    Mixit.mix(@module, block) do |receiver|
         | 
| 70 | 
            +
                    Mixit.mix(@module, :scope => block) do |receiver|
         | 
| 91 71 | 
             
                      receiver.callme.must_equal(:ok)
         | 
| 92 72 | 
             
                    end
         | 
| 93 73 | 
             
                  end
         | 
| @@ -95,7 +75,7 @@ context Mixit do | |
| 95 75 | 
             
                  it 'must not extend the original receiver with mixed-in methods.' do
         | 
| 96 76 | 
             
                    block = proc {}
         | 
| 97 77 |  | 
| 98 | 
            -
                    Mixit.mix(@module, block) do |receiver|
         | 
| 78 | 
            +
                    Mixit.mix(@module, :scope => block) do |receiver|
         | 
| 99 79 | 
             
                      respond_to?(:callme).must_equal(false) 
         | 
| 100 80 | 
             
                    end
         | 
| 101 81 | 
             
                  end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: mixit
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.4.0
         | 
| 5 5 | 
             
              prerelease: 
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors:
         | 
| @@ -9,11 +9,11 @@ authors: | |
| 9 9 | 
             
            autorequire: 
         | 
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date: 2011-11- | 
| 12 | 
            +
            date: 2011-11-26 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              name: rake
         | 
| 16 | 
            -
              requirement: & | 
| 16 | 
            +
              requirement: &70097654179640 !ruby/object:Gem::Requirement
         | 
| 17 17 | 
             
                none: false
         | 
| 18 18 | 
             
                requirements:
         | 
| 19 19 | 
             
                - - ~>
         | 
| @@ -21,10 +21,10 @@ dependencies: | |
| 21 21 | 
             
                    version: 0.9.2
         | 
| 22 22 | 
             
              type: :development
         | 
| 23 23 | 
             
              prerelease: false
         | 
| 24 | 
            -
              version_requirements: * | 
| 24 | 
            +
              version_requirements: *70097654179640
         | 
| 25 25 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 26 26 | 
             
              name: minitest
         | 
| 27 | 
            -
              requirement: & | 
| 27 | 
            +
              requirement: &70097654179140 !ruby/object:Gem::Requirement
         | 
| 28 28 | 
             
                none: false
         | 
| 29 29 | 
             
                requirements:
         | 
| 30 30 | 
             
                - - ~>
         | 
| @@ -32,7 +32,7 @@ dependencies: | |
| 32 32 | 
             
                    version: '2.5'
         | 
| 33 33 | 
             
              type: :development
         | 
| 34 34 | 
             
              prerelease: false
         | 
| 35 | 
            -
              version_requirements: * | 
| 35 | 
            +
              version_requirements: *70097654179140
         | 
| 36 36 | 
             
            description: Temporarily extend the calling scope of a block with instance methods
         | 
| 37 37 | 
             
              from a module.
         | 
| 38 38 | 
             
            email:
         | 
| @@ -68,7 +68,7 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 68 68 | 
             
                  version: '0'
         | 
| 69 69 | 
             
                  segments:
         | 
| 70 70 | 
             
                  - 0
         | 
| 71 | 
            -
                  hash:  | 
| 71 | 
            +
                  hash: -1392924086282936836
         | 
| 72 72 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 73 73 | 
             
              none: false
         | 
| 74 74 | 
             
              requirements:
         | 
| @@ -77,7 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 77 77 | 
             
                  version: '0'
         | 
| 78 78 | 
             
                  segments:
         | 
| 79 79 | 
             
                  - 0
         | 
| 80 | 
            -
                  hash:  | 
| 80 | 
            +
                  hash: -1392924086282936836
         | 
| 81 81 | 
             
            requirements: []
         | 
| 82 82 | 
             
            rubyforge_project: mixit
         | 
| 83 83 | 
             
            rubygems_version: 1.8.11
         |