├── var ├── name ├── title ├── version ├── created ├── summary ├── organizations ├── authors ├── copyrights ├── description ├── repositories ├── requirements └── resources ├── work ├── deprecated │ ├── meta │ │ ├── name │ │ ├── title │ │ ├── version │ │ ├── created │ │ ├── license │ │ ├── authors │ │ ├── collection │ │ ├── summary │ │ ├── contact │ │ ├── homepage │ │ ├── repository │ │ ├── resources │ │ │ ├── homepage │ │ │ └── repository │ │ └── description │ ├── test_paramix-2008.rb │ ├── paramix-2010.rdoc │ ├── test_paramix-2005.rb │ ├── paramix-2005.rb │ └── paramix-2008.rb ├── announce.txt ├── public.rb ├── newidea │ └── newidea.rb └── oldschool │ ├── dynamod.rb │ └── dynamix.rb ├── Gemfile ├── .yardopts ├── .gitignore ├── demo ├── applique │ └── setup.rb ├── 06_extend.md ├── 05_include.md ├── 03_battery.md ├── 07_namespaces.md ├── 08_dynamic.md ├── 02_general.md ├── 01_basic.md └── 09_nested.md ├── lib ├── paramix │ └── version.rb └── paramix.rb ├── .travis.yml ├── MANIFEST ├── Assembly ├── LICENSE.txt ├── .index ├── README.md ├── HISTORY.md └── .gemspec /var/name: -------------------------------------------------------------------------------- 1 | paramix 2 | -------------------------------------------------------------------------------- /var/title: -------------------------------------------------------------------------------- 1 | Paramix 2 | -------------------------------------------------------------------------------- /var/version: -------------------------------------------------------------------------------- 1 | 2.0.1 2 | -------------------------------------------------------------------------------- /var/created: -------------------------------------------------------------------------------- 1 | 2006-01-01 2 | -------------------------------------------------------------------------------- /var/summary: -------------------------------------------------------------------------------- 1 | Parametric Mixins 2 | -------------------------------------------------------------------------------- /work/deprecated/meta/name: -------------------------------------------------------------------------------- 1 | paramix 2 | -------------------------------------------------------------------------------- /work/deprecated/meta/title: -------------------------------------------------------------------------------- 1 | Paramix 2 | -------------------------------------------------------------------------------- /work/deprecated/meta/version: -------------------------------------------------------------------------------- 1 | 2.0.0 2 | -------------------------------------------------------------------------------- /var/organizations: -------------------------------------------------------------------------------- 1 | --- 2 | - Rubyworks 3 | -------------------------------------------------------------------------------- /work/deprecated/meta/created: -------------------------------------------------------------------------------- 1 | 2006-01-01 2 | -------------------------------------------------------------------------------- /work/deprecated/meta/license: -------------------------------------------------------------------------------- 1 | LPGLv3 2 | -------------------------------------------------------------------------------- /work/deprecated/meta/authors: -------------------------------------------------------------------------------- 1 | Thomas Sawyer 2 | -------------------------------------------------------------------------------- /work/deprecated/meta/collection: -------------------------------------------------------------------------------- 1 | rubyworks 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | gemspec 3 | -------------------------------------------------------------------------------- /var/authors: -------------------------------------------------------------------------------- 1 | --- 2 | - Trans 3 | -------------------------------------------------------------------------------- /work/deprecated/meta/summary: -------------------------------------------------------------------------------- 1 | Parametric Mixins 2 | -------------------------------------------------------------------------------- /var/copyrights: -------------------------------------------------------------------------------- 1 | --- 2 | - (c) 2006 Rubyworks (BSD-2-Clause) 3 | -------------------------------------------------------------------------------- /work/deprecated/meta/contact: -------------------------------------------------------------------------------- 1 | trans 2 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | --protected 2 | --private 3 | lib 4 | - 5 | [A-Z]*.* 6 | 7 | -------------------------------------------------------------------------------- /work/deprecated/meta/homepage: -------------------------------------------------------------------------------- 1 | http://rubyworks.github.com/paramix 2 | -------------------------------------------------------------------------------- /var/description: -------------------------------------------------------------------------------- 1 | Parametric Mixins provides parameters for mixin modules. 2 | -------------------------------------------------------------------------------- /var/repositories: -------------------------------------------------------------------------------- 1 | --- 2 | upstream: git://github.com/rubyworks/paramix.git 3 | -------------------------------------------------------------------------------- /work/deprecated/meta/repository: -------------------------------------------------------------------------------- 1 | git://github.com/rubyworks/paramix.git 2 | -------------------------------------------------------------------------------- /work/deprecated/meta/resources/homepage: -------------------------------------------------------------------------------- 1 | http://rubyworks.github.com/paramix 2 | -------------------------------------------------------------------------------- /work/deprecated/meta/resources/repository: -------------------------------------------------------------------------------- 1 | git://github.com/rubyworks/paramix.git 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .reap/digest 2 | .yardoc 3 | doc 4 | log 5 | pkg 6 | tmp 7 | web 8 | DEMO.* 9 | -------------------------------------------------------------------------------- /demo/applique/setup.rb: -------------------------------------------------------------------------------- 1 | require 'ae' 2 | require 'ae/should' 3 | 4 | require 'paramix' 5 | -------------------------------------------------------------------------------- /work/deprecated/meta/description: -------------------------------------------------------------------------------- 1 | Parametric Mixins provides parameters for mixin modules. 2 | -------------------------------------------------------------------------------- /lib/paramix/version.rb: -------------------------------------------------------------------------------- 1 | module Paramix 2 | VERSION = "2.0.0" #:erb: VERSION = "<%= version %>" 3 | end 4 | -------------------------------------------------------------------------------- /var/requirements: -------------------------------------------------------------------------------- 1 | --- 2 | - detroit (build) 3 | - ergo (build) 4 | - qed (test) 5 | - ae (test) 6 | 7 | 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | script: "bundle exec qed" 3 | rvm: 4 | - 1.8.7 5 | - 1.9.2 6 | - 1.9.3 7 | - rbx-2.0 8 | - jruby 9 | - ree 10 | 11 | -------------------------------------------------------------------------------- /var/resources: -------------------------------------------------------------------------------- 1 | --- 2 | home: http://rubyworks.github.com/paramix 3 | code: http://github.com/rubyworks/paramix 4 | docs: http://rubydoc.info/gems/paramix 5 | wiki: http://wiki.github.com/rubyworks/paramix 6 | bugs: http://github.com/rubyworks/paramix/issues 7 | mail: http://groups.google.com/group/rubyworks-mailinglist 8 | -------------------------------------------------------------------------------- /MANIFEST: -------------------------------------------------------------------------------- 1 | #!mast .ruby .yardopts bin demo eg lib man qed spec test [A-Z]*.* 2 | .yardopts 3 | demo/01_basic.md 4 | demo/02_general.md 5 | demo/03_battery.md 6 | demo/05_include.md 7 | demo/06_extend.md 8 | demo/07_namespaces.md 9 | demo/08_dynamic.md 10 | demo/09_nested.md 11 | demo/applique/setup.rb 12 | lib/paramix/version.rb 13 | lib/paramix.rb 14 | LICENSE.txt 15 | HISTORY.md 16 | README.md 17 | DEMO.md 18 | -------------------------------------------------------------------------------- /work/announce.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | $title 4 | 5 | 6 | $version 7 | 8 | 9 | $homepage 10 | 11 | 12 | $slogan 13 | 14 | 15 | $summary 16 | 17 | 18 | I am please to announce the first offical release of Cherry/XML. 19 | 20 | $description 21 | 22 | And yes, the XML layout is just for shits-n-giggles :) 23 | 24 | 25 | 26 | $stamp 27 | 28 | -------------------------------------------------------------------------------- /demo/06_extend.md: -------------------------------------------------------------------------------- 1 | # Extend 2 | 3 | Given extend with parametric mixins. 4 | 5 | module ME 6 | include Paramix::Parametric 7 | 8 | parameterized do |params| 9 | 10 | public :f do 11 | params[:p] 12 | end 13 | 14 | end 15 | end 16 | 17 | class E1 18 | extend ME[:p => "mosh"] 19 | end 20 | 21 | class E2 22 | extend ME[:p => "many"] 23 | end 24 | 25 | Then should vary the return value of the class methods. 26 | 27 | E1.f.should == "mosh" 28 | E2.f.should == "many" 29 | 30 | -------------------------------------------------------------------------------- /demo/05_include.md: -------------------------------------------------------------------------------- 1 | # Include 2 | 3 | Given include with parametric mixins. 4 | 5 | module MI 6 | include Paramix::Parametric 7 | 8 | parameterized do |params| 9 | 10 | public :f do 11 | params[:p] 12 | end 13 | 14 | end 15 | end 16 | 17 | class I1 18 | include MI[:p => "mosh"] 19 | end 20 | 21 | class I2 22 | include MI[:p => "many"] 23 | end 24 | 25 | Then it should vary the return value of the instance methods. 26 | 27 | I1.new.f.should == "mosh" 28 | I2.new.f.should == "many" 29 | 30 | -------------------------------------------------------------------------------- /demo/03_battery.md: -------------------------------------------------------------------------------- 1 | # Works with Namespaces 2 | 3 | Parametric mixins work regardless of the namespace depth. 4 | 5 | module R 6 | module M 7 | include Paramix::Parametric 8 | 9 | parameterized do |params| 10 | public :f do 11 | params[:p] 12 | end 13 | end 14 | end 15 | end 16 | 17 | module Q 18 | class I 19 | include R::M[:p => "mosh"] 20 | end 21 | class E 22 | extend R::M[:p => "many"] 23 | end 24 | end 25 | 26 | Q::I.new.f #=> "mosh" 27 | 28 | Q::E.f #=> "many" 29 | 30 | -------------------------------------------------------------------------------- /demo/07_namespaces.md: -------------------------------------------------------------------------------- 1 | # Namespaces 2 | 3 | Given namespace depth does not adversly effect parametric mixins. 4 | 5 | module N 6 | module M 7 | include Paramix::Parametric 8 | parameterized do |params| 9 | public :f do 10 | params[:p] 11 | end 12 | end 13 | end 14 | end 15 | 16 | module Q 17 | class I 18 | include N::M[:p => "mosh"] 19 | end 20 | class E 21 | extend N::M[:p => "many"] 22 | end 23 | end 24 | 25 | Then 26 | 27 | Q::I.new.f == "mosh" 28 | 29 | And 30 | 31 | Q::E.f.should == "many" 32 | 33 | -------------------------------------------------------------------------------- /demo/08_dynamic.md: -------------------------------------------------------------------------------- 1 | # Dynamic Parametric Mixin 2 | 3 | Given dynamic methods using paramtric mixins. 4 | 5 | module MD 6 | include Paramix::Parametric 7 | 8 | parameterized do |params| 9 | 10 | public :f do 11 | params[:p] 12 | end 13 | 14 | attr_accessor params[:p] 15 | end 16 | end 17 | 18 | class C1 19 | include MD[:p => "c1"] 20 | end 21 | 22 | class C2 23 | include MD[:p => "c2"] 24 | end 25 | 26 | Then 27 | 28 | c = C1.new 29 | c.f.should == "c1" 30 | 31 | And 32 | 33 | c = C2.new 34 | c.f.should == "c2" 35 | 36 | And 37 | 38 | c = C1.new 39 | c.c1 = :yes1 40 | c.c1.should == :yes1 41 | 42 | And 43 | 44 | c = C2.new 45 | c.c2 = :yes2 46 | c.c2.should == :yes2 47 | 48 | -------------------------------------------------------------------------------- /Assembly: -------------------------------------------------------------------------------- 1 | --- 2 | email: 3 | mailto: 4 | - ruby-talk@ruby-lang.org 5 | - rubyworks-mailinglist@googlegroups.com 6 | 7 | gem: 8 | active: true 9 | 10 | github: 11 | gh_pages: web 12 | 13 | #mast: 14 | # service: Mast 15 | # include: [bin, demo, lib, meta, test, "[A-Z]*"] 16 | # exclude: ~ 17 | # active: true 18 | 19 | yard: 20 | priority: 2 21 | 22 | dnote: 23 | title: Developer's Notes 24 | labels: ~ 25 | output: log/NOTES.rdoc 26 | 27 | qed: 28 | files: demo 29 | 30 | qedoc: 31 | files : demo 32 | title : Paramix Demonstrandum 33 | output: QED.rdoc 34 | 35 | #rspec: 36 | # include: spec/ 37 | # exclude: ~ 38 | # loadpath: [lib] 39 | # requires: ~ 40 | # active: false 41 | 42 | syntax: 43 | files: lib/ 44 | 45 | vclog: 46 | output: 47 | - log/changes.html 48 | - log/history.html 49 | 50 | -------------------------------------------------------------------------------- /work/public.rb: -------------------------------------------------------------------------------- 1 | class C < Module 2 | def initialize(&block) 3 | instance_eval(&block) 4 | end 5 | end 6 | 7 | M = C.new do 8 | private 9 | define_method(:x){ p "x" } 10 | end 11 | 12 | class X 13 | include M 14 | end 15 | 16 | X.new.x 17 | 18 | exit 19 | 20 | 21 | class Module 22 | 23 | alias :publicize :public 24 | alias :privatize :private 25 | alias :protect :protected 26 | 27 | # 28 | def public(name, &code) 29 | define_method(name, &code) if code 30 | publicize(name) 31 | end 32 | 33 | # 34 | def private(name, &code) 35 | define_method(name, &code) if code 36 | privatize(name) 37 | end 38 | 39 | # 40 | def protected(name, &code) 41 | define_method(name, &code) if code 42 | protect(name) 43 | end 44 | 45 | end 46 | 47 | 48 | class X 49 | 50 | public :x do |*a| 51 | p a 52 | end 53 | 54 | private :y do |*a| 55 | p a 56 | end 57 | 58 | protected :z do |*a| 59 | p a 60 | end 61 | 62 | end 63 | 64 | X.new.x("hello") 65 | 66 | -------------------------------------------------------------------------------- /work/newidea/newidea.rb: -------------------------------------------------------------------------------- 1 | require 'ae' 2 | require 'ae/should' 3 | 4 | # After all what is a "mixin"? 5 | 6 | class ParametricMixin < Module 7 | 8 | def self.[](*args) 9 | new(*args) 10 | end 11 | 12 | def initialize(*args, &block) 13 | initialize_parameters(*args, &block) 14 | end 15 | 16 | end 17 | 18 | 19 | # example 20 | 21 | class M < ParametricMixin 22 | 23 | def initialize_parameters(params) 24 | define_method :f do 25 | params[:p] 26 | end 27 | 28 | attr_accessor params[:p] 29 | end 30 | 31 | end 32 | 33 | class C1 34 | include M[:p => "c1"] 35 | end 36 | 37 | class C2 38 | include M[:p => "c2"] 39 | end 40 | 41 | #it "should" do 42 | c = C1.new 43 | c.f.should == "c1" 44 | #end 45 | 46 | #it "should" do 47 | c = C2.new 48 | c.f.should == "c2" 49 | #end 50 | 51 | #it "should" do 52 | c = C1.new 53 | c.c1 = :yes1 54 | c.c1.should == :yes1 55 | #end 56 | 57 | #it "should" do 58 | c = C2.new 59 | c.c2 = :yes2 60 | c.c2.should == :yes2 61 | #end 62 | 63 | -------------------------------------------------------------------------------- /work/deprecated/test_paramix-2008.rb: -------------------------------------------------------------------------------- 1 | require 'paramix' 2 | require 'test/unit' 3 | 4 | class TC_Paramix_Callback < Test::Unit::TestCase 5 | 6 | module M 7 | include Paramix 8 | 9 | def f 10 | mixin_params[M][:p] 11 | end 12 | 13 | def self.included(base) 14 | params = base.mixin_params[self] 15 | base.class_eval do 16 | define_method :check do 17 | params 18 | end 19 | end 20 | end 21 | end 22 | 23 | class C 24 | include M[:p => "check"] 25 | end 26 | 27 | class D 28 | include M[:p => "steak"] 29 | end 30 | 31 | def test_01_001 32 | c = C.new 33 | assert_equal( "check", c.mixin_params[M][:p] ) 34 | assert_equal( "check", c.f ) 35 | end 36 | 37 | def test_01_002 38 | d = D.new 39 | assert_equal( "steak", d.mixin_params[M][:p] ) 40 | assert_equal( "steak", d.f ) 41 | end 42 | 43 | def test_01_003 44 | assert_equal( {M=>{:p => "check"}}, C.mixin_parameters ) 45 | assert_equal( {M=>{:p => "steak"}}, D.mixin_parameters ) 46 | end 47 | 48 | def test_01_004 49 | c = C.new 50 | assert_equal( {:p => "check"}, c.check ) 51 | d = D.new 52 | assert_equal( {:p => "steak"}, d.check ) 53 | end 54 | 55 | end 56 | 57 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | (BSD-2-Clause License) 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, 7 | this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 14 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 15 | AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 16 | COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 17 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 20 | OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 21 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 22 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | -------------------------------------------------------------------------------- /work/deprecated/paramix-2010.rdoc: -------------------------------------------------------------------------------- 1 | = Basic Overviw of Paramix 2 | 3 | Require the library. 4 | 5 | require 'paramix3' 6 | 7 | Create a parametric mixin. 8 | 9 | module MyMixin 10 | include Parametric 11 | 12 | def f 13 | mymixin.name 14 | end 15 | end 16 | 17 | Create a class that uses the mixin and set the parameter. 18 | 19 | class X 20 | include MyMixin[:name => 'x'] 21 | end 22 | 23 | Then the parameter is accessible. 24 | 25 | X.new.f.assert == 'x' 26 | 27 | If we create another parametric mixin which depends on the first. 28 | 29 | module AnotherMixin 30 | include MyMixin[:name => 'x'] 31 | 32 | def g 33 | anothermixin.name 34 | end 35 | end 36 | 37 | And a class for it. 38 | 39 | class Y 40 | include AnotherMixin[:name => 'y'] 41 | end 42 | 43 | We can see that the parameters stay with their respective mixins. 44 | 45 | Y.new.f.assert == 'x' 46 | Y.new.g.assert == 'y' 47 | 48 | However if we do the same, but do not paramterize the first module when 49 | it gets included: 50 | 51 | module ThirdMixin 52 | include MyMixin #[] #[:name => 'x'] 53 | 54 | def g 55 | thirdmixin.name 56 | end 57 | end 58 | 59 | And a class for it. 60 | 61 | class Z 62 | include ThirdMixin[:name => 'y'] 63 | end 64 | 65 | We can see that the value of the parameter has 'propogated up' 66 | to its ancestor parametric modules. 67 | 68 | Z.new.f.assert == 'y' 69 | Z.new.g.assert == 'y' 70 | 71 | 72 | -------------------------------------------------------------------------------- /.index: -------------------------------------------------------------------------------- 1 | --- 2 | revision: 2013 3 | type: ruby 4 | sources: 5 | - var 6 | authors: 7 | - name: Trans 8 | email: transfire@gmail.com 9 | organizations: 10 | - name: Rubyworks 11 | requirements: 12 | - groups: 13 | - build 14 | development: true 15 | name: detroit 16 | - groups: 17 | - build 18 | development: true 19 | name: ergo 20 | - groups: 21 | - test 22 | development: true 23 | name: qed 24 | - groups: 25 | - test 26 | development: true 27 | name: ae 28 | conflicts: [] 29 | alternatives: [] 30 | resources: 31 | - type: home 32 | uri: http://rubyworks.github.com/paramix 33 | label: Homepage 34 | - type: code 35 | uri: http://github.com/rubyworks/paramix 36 | label: Source Code 37 | - type: docs 38 | uri: http://rubydoc.info/gems/paramix 39 | label: Documentation 40 | - type: wiki 41 | uri: http://wiki.github.com/rubyworks/paramix 42 | label: User Guide 43 | - type: bugs 44 | uri: http://github.com/rubyworks/paramix/issues 45 | label: Issue Tracker 46 | - type: mail 47 | uri: http://groups.google.com/group/rubyworks-mailinglist 48 | label: Mailing List 49 | repositories: 50 | - name: upstream 51 | scm: git 52 | uri: git://github.com/rubyworks/paramix.git 53 | categories: [] 54 | copyrights: 55 | - holder: Rubyworks 56 | year: '2006' 57 | license: BSD-2-Clause 58 | customs: [] 59 | paths: 60 | lib: 61 | - lib 62 | created: '2006-01-01' 63 | summary: Parametric Mixins 64 | title: Paramix 65 | version: 2.0.1 66 | name: paramix 67 | description: Parametric Mixins provides parameters for mixin modules. 68 | date: '2013-03-10' 69 | -------------------------------------------------------------------------------- /demo/02_general.md: -------------------------------------------------------------------------------- 1 | # Parametric Include 2 | 3 | Load the library. 4 | 5 | require 'paramix' 6 | 7 | Given a parametric mixin. 8 | 9 | module M 10 | include Paramix::Parametric 11 | 12 | parameterized do |params| 13 | 14 | public :f do 15 | params[:p] 16 | end 17 | 18 | end 19 | end 20 | 21 | We can inlcude the parameteric module in a some classes. 22 | 23 | class I1 24 | include M[:p => "mosh"] 25 | end 26 | 27 | class I2 28 | include M[:p => "many"] 29 | end 30 | 31 | And the result will vary according to the parameter set. 32 | 33 | I1.new.f #=> "mosh" 34 | I2.new.f #=> "many" 35 | 36 | 37 | # Parametric Extension 38 | 39 | We can also extend classes witht the mixin. 40 | 41 | class E1 42 | extend M[:p => "mosh2"] 43 | end 44 | 45 | class E2 46 | extend M[:p => "many2"] 47 | end 48 | 49 | And the results will likewise work as expected. 50 | 51 | E1.f #=> "mosh2" 52 | E2.f #=> "many2" 53 | 54 | 55 | # Dynamically Defined Methods 56 | 57 | Parametric mixins can be used to define dynamic code. 58 | 59 | module N 60 | include Paramix::Parametric 61 | 62 | parameterized do |params| 63 | attr_accessor params[:a] 64 | end 65 | end 66 | 67 | Now if we include this module we will have new attributes based on 68 | the parameter assigned. 69 | 70 | class D1 71 | include N[:a => "m1"] 72 | end 73 | 74 | class D2 75 | include N[:a => "m2"] 76 | end 77 | 78 | d1 = D1.new 79 | d1.m1 = :yes1 80 | 81 | d1.m1 #=> :yes1 82 | 83 | d2 = D2.new 84 | d2.m2 = :yes2 85 | 86 | d2.m2 #=> :yes2 87 | 88 | -------------------------------------------------------------------------------- /work/deprecated/test_paramix-2005.rb: -------------------------------------------------------------------------------- 1 | # Test facets/paramix.rb 2 | 3 | require 'facets/paramix.rb' 4 | 5 | require 'test/unit' 6 | 7 | class TC_Paramix_01 < Test::Unit::TestCase 8 | 9 | module M 10 | def f 11 | M(:p) 12 | end 13 | def self.included_with_parameters( base, parms ) 14 | base.class_eval do 15 | define_method :check do 16 | parms 17 | end 18 | end 19 | end 20 | end 21 | 22 | class C 23 | include M, :p => "check" 24 | end 25 | 26 | class D 27 | include M, :p => "steak" 28 | end 29 | 30 | def test_01_001 31 | c = C.new 32 | assert_equal( "check", c.M(:p) ) 33 | assert_equal( "check", c.f ) 34 | end 35 | 36 | def test_01_002 37 | d = D.new 38 | assert_equal( "steak", d.M(:p) ) 39 | assert_equal( "steak", d.f ) 40 | end 41 | 42 | def test_01_003 43 | assert_equal( {M=>{:p => "check"}}, C.mixin_parameters ) 44 | assert_equal( {M=>{:p => "steak"}}, D.mixin_parameters ) 45 | end 46 | 47 | def test_01_004 48 | c = C.new 49 | assert_equal( {:p => "check"}, c.check ) 50 | d = D.new 51 | assert_equal( {:p => "steak"}, d.check ) 52 | end 53 | 54 | end 55 | 56 | 57 | class TC_Paramix_02 < Test::Unit::TestCase 58 | 59 | module M 60 | def f 61 | M(:p) 62 | end 63 | end 64 | 65 | class C 66 | extend M, :p => "mosh" 67 | end 68 | 69 | class D 70 | extend M, :p => "many" 71 | end 72 | 73 | def test_02_001 74 | assert_equal( "mosh", C.f ) 75 | end 76 | 77 | def test_02_002 78 | assert_equal( "many", D.f ) 79 | end 80 | 81 | def test_02_003 82 | assert_equal( {M=>{:p => "mosh"}}, (class << C; self; end).mixin_parameters ) 83 | assert_equal( {M=>{:p => "many"}}, (class << D; self; end).mixin_parameters ) 84 | end 85 | 86 | end 87 | -------------------------------------------------------------------------------- /demo/01_basic.md: -------------------------------------------------------------------------------- 1 | # Basic Example 2 | 3 | Require the library. 4 | 5 | require 'paramix' 6 | 7 | Create a parametric mixin. 8 | 9 | module MyMixin 10 | include Paramix::Parametric 11 | 12 | parameterized do |params| 13 | 14 | public params[:name] do 15 | params[:value] 16 | end 17 | 18 | end 19 | end 20 | 21 | Create a class that uses the mixin and set the parameter. 22 | 23 | class X 24 | include MyMixin[:name => 'f', :value=>1] 25 | end 26 | 27 | Then the parameter is accessible. 28 | 29 | X.new.f.assert == 1 30 | 31 | 32 | # Nested Parematric Mixins 33 | 34 | If we create another parametric mixin which depends on the first. 35 | 36 | module AnotherMixin 37 | include Paramix::Parametric 38 | include MyMixin[:name => 'f', :value=>1] 39 | 40 | parameterized do |params| 41 | 42 | public params[:name] do 43 | params[:value] 44 | end 45 | 46 | end 47 | end 48 | 49 | And a class for it. 50 | 51 | class Y 52 | include AnotherMixin[:name => 'g', :value=>2] 53 | end 54 | 55 | We can see that the parameters stay with their respective mixins. 56 | 57 | Y.new.f.assert == 1 58 | Y.new.g.assert == 2 59 | 60 | However if we do the same, but do not paramterize the first module then 61 | the including module also become parametric. 62 | 63 | module ThirdMixin 64 | #include Paramix::Parametric 65 | include MyMixin 66 | 67 | parameterized do |params| 68 | 69 | public params[:name].succ do 70 | params[:value] 71 | end 72 | 73 | end 74 | end 75 | 76 | And a class for it. 77 | 78 | class Z 79 | include ThirdMixin[:name => 'q', :value=>3] 80 | end 81 | 82 | We can see that the value of the parameter has propogated up to its 83 | ancestor parametric module. 84 | 85 | Z.new.q.assert == 3 86 | Z.new.r.assert == 3 87 | 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Paramix 2 | 3 | [![Gem Version](https://badge.fury.io/rb/paramix.png)](http://badge.fury.io/rb/paramix) 4 | [![Build Status](https://secure.travis-ci.org/rubyworks/paramix.png)](http://travis-ci.org/rubyworks/paramix)     5 | [![Flattr Me](http://api.flattr.com/button/flattr-badge-large.png)](http://flattr.com/thing/324911/Rubyworks-Ruby-Development-Fund) 6 | 7 | [Website](http://rubyworks.github.com/paramix) · 8 | [YARD API](http://rubydoc.info/gems/paramix) · 9 | [Report Issue](http://github.com/rubyworks/paramix/issues) · 10 | [Source Code](http://github.com/rubyworks/paramix) 11 | 12 | 13 | ## About 14 | 15 | Parametric Mixins provides an easy means to "functionalize" modules. 16 | The module can then be differentiated upon usage according to the 17 | parameters provided. 18 | 19 | 20 | ## Usage 21 | 22 | Here is the most basic example. It simply makes the parametric module's 23 | parameters available at the instance level. 24 | 25 | module M 26 | include Paramix::Parametric 27 | 28 | paramaterized do |params| 29 | define_method :params do 30 | params 31 | end 32 | end 33 | 34 | def hello 35 | "Hello, %s!" % [params[:name]] 36 | end 37 | end 38 | 39 | class X 40 | include M[:name=>'Charlie'] 41 | end 42 | 43 | X.new.hello #=> 'Hello, Charlie!' 44 | 45 | Because the +parameterized+ method defines a block that is evaluated in the 46 | context of a new Parametric::Mixin, it is possible to work with the parameters 47 | in more versitle ways. Here is a simple example that uses a parameter to 48 | define a method and another parameter to define it's return value. 49 | 50 | module M 51 | include Paramix::Parametric 52 | 53 | paramaterized do |params| 54 | define_method params[:name] do 55 | params[:value] 56 | end 57 | end 58 | end 59 | 60 | class X 61 | include M[:name=>'foo', :value='bar'] 62 | end 63 | 64 | X.new.foo #=> 'bar' 65 | 66 | 67 | ## Copyrights 68 | 69 | Copyright (c) 2006 Rubyworks 70 | 71 | This program is ditributed unser the terms of the BSD-2-Clause license. 72 | 73 | See COPYING.rdoc file for details. 74 | 75 | -------------------------------------------------------------------------------- /HISTORY.md: -------------------------------------------------------------------------------- 1 | # RELEASE HISTORY 2 | 3 | ## 2.0.1 // 2011-10-22 4 | 5 | This release simply brings the project uptodate with the latest 6 | build tools, and switches the license to BSD-2-Clause. 7 | 8 | Changes: 9 | 10 | * Modernize build configuration. 11 | * Switch to FreeBSD license. 12 | 13 | 14 | ## 2.0.0 // 2010-04-06 15 | 16 | Thanks to a conversation with Jonathan Rochkind, Paramix has 17 | been completely rewritten. Whereas anonymous modules were 18 | avoided in prior versions, it has become clear that the worries 19 | of memory consumption that would accompany them were largely 20 | unfounded. This new version therefore makes use of them. 21 | The new code is refreshingly concise, and the design fully 22 | comforming to POLS. 23 | 24 | Changes: 25 | 26 | * Use anonymous modules instead of global parameter stores. 27 | * Use paramterized block for dynamic definitions. 28 | 29 | 30 | ## 1.1.0 // 2010-04-05 31 | 32 | The previous versions did not properly support nested parametric 33 | includes, i.e. including one parametirc mixin into another. This 34 | release fixed this issue. However, to do so provided difficult 35 | and required some changes to the API. In particular, instead 36 | of +mixin_params[M][:p]+ one must now use +mixin_param(M,:p)+. 37 | It was not longer possible to simply return a hash, since special 38 | lookup logic is required to handle nested mixins. It should also 39 | be noted that +Module#mixin_parameters+, which stores the actual 40 | parameters is no longer accessible at the instance level, just 41 | as +mixin_param()+ is soley an instance method (at the class level 42 | it is used to access the singleton parameters). 43 | 44 | Changes: 45 | 46 | * Proper support for nested parametric mixins. 47 | * Provide #mixin_param method to lookup parameters. 48 | * The mixin_parameters method is class-level only. 49 | 50 | 51 | ## 1.0.1 // 2010-04-03 52 | 53 | This release simply removed dependencies on Facets. 54 | 55 | Changes: 56 | 57 | * Removed dependencies on Facets module/basename and module/modspace. 58 | * Divided tests into separate files. 59 | 60 | 61 | ## 1.0.0 // 2009-06-29 62 | 63 | This is the initial stand-alone release of Paramix spun-off 64 | from Ruby Facets (and is actually he second major version, the 65 | original being spun of from the Nitro/Og Glue library). 66 | 67 | Changes: 68 | 69 | * Happy Birthday! 70 | 71 | -------------------------------------------------------------------------------- /lib/paramix.rb: -------------------------------------------------------------------------------- 1 | # Paramix 2 | # Copyright 2010 Thomas Sawyer 3 | # Apache 2.0 License 4 | 5 | require 'paramix/version' 6 | 7 | # Paramix namespace. 8 | # 9 | module Paramix 10 | 11 | # = Parametric 12 | # 13 | # Parametric mixins provides parameters for mixin modules. 14 | # Module parameters can be set at the time of inclusion 15 | # or extension using Module#[] method, then parameters 16 | # can be accessed via the #mixin_parameters method. 17 | # 18 | # module MyMixin 19 | # include Paramix::Parametric 20 | # 21 | # parameterized |params| 22 | # define_method :hello do 23 | # puts "Hello from #{params[:name]}!" 24 | # end 25 | # end 26 | # end 27 | # 28 | # class MyClass 29 | # include MyMixin[:name => 'Ruby'] 30 | # end 31 | # 32 | # MyClass.new.hello #=> 'Hello from Ruby!' 33 | # 34 | module Parametric 35 | 36 | # 37 | def self.included(base) 38 | base.extend(Extensions) 39 | end 40 | 41 | # 42 | module Extensions 43 | # 44 | def [](parameters={}) 45 | Mixin.new(self, parameters) 46 | end 47 | 48 | # 49 | def parameterized(&code) 50 | @code ||= [] 51 | if block_given? 52 | @code << code 53 | else 54 | @code 55 | end 56 | end 57 | 58 | def append_features(base) 59 | return super(base) if Mixin === base || Mixin === self 60 | 61 | base.extend(Extensions) 62 | 63 | anc = ancestors.find{ |a| a.respond_to?(:parameterized) } 64 | base.parameterized.concat(anc.parameterized) 65 | 66 | super(base) 67 | end 68 | 69 | # 70 | def extend_object(base) 71 | return super(base) if Mixin === base || Mixin === self 72 | 73 | base.extend(Extensions) 74 | 75 | anc = ancestors.find{ |a| a.respond_to?(:parameterized) } 76 | base.parameterized.concat(anc.parameterized) 77 | 78 | super(base) 79 | end 80 | 81 | end 82 | 83 | # An instance of the Mixin module class is what is porduced 84 | # when parameters are applied to a parametric module. 85 | # 86 | class Mixin < Module 87 | 88 | def initialize(base, parameters) 89 | include(base) 90 | #base.append_features(self) 91 | base.parameterized.each do |code| 92 | instance_exec(parameters, &code) 93 | end 94 | #base.parameterized.clear 95 | end 96 | 97 | # 98 | def public(name, &code) 99 | define_method(name, &code) 100 | super(name) 101 | end 102 | 103 | # 104 | def private(name, &code) 105 | define_method(name, &code) 106 | super(name) 107 | end 108 | 109 | # 110 | def protected(name, &code) 111 | define_method(name, &code) 112 | super(name) 113 | end 114 | 115 | end 116 | 117 | end 118 | 119 | end 120 | -------------------------------------------------------------------------------- /demo/09_nested.md: -------------------------------------------------------------------------------- 1 | # Nested Parametric Mixins 2 | 3 | Given nested modules where inner most module is parametric. 4 | 5 | m = Module.new do 6 | include Paramix::Parametric 7 | 8 | parameterized do |params| 9 | public :f do 10 | params[:p] 11 | end 12 | end 13 | end 14 | 15 | n = Module.new do 16 | include m[:p=>"NMp"] 17 | end 18 | 19 | i = Class.new do 20 | include n 21 | end 22 | 23 | e = Class.new do 24 | extend n 25 | end 26 | 27 | Then 28 | 29 | i.new.f.should == "NMp" 30 | 31 | And 32 | 33 | e.f.should == "NMp" 34 | 35 | Nested parametric mixins with parameters. 36 | 37 | m = Module.new do 38 | include Paramix::Parametric 39 | 40 | parameterized do |params| 41 | public :f do 42 | params[:p] 43 | end 44 | end 45 | end 46 | 47 | n = Module.new do 48 | include Paramix::Parametric 49 | include m[:p=>"NMp"] 50 | 51 | parameterized do |params| 52 | public :g do 53 | params[:p] 54 | end 55 | end 56 | end 57 | 58 | i = Class.new do 59 | include n[:p => "INp"] 60 | end 61 | 62 | e = Class.new do 63 | extend n[:p => "ENp"] 64 | end 65 | 66 | Then 67 | 68 | i.new.f.should == "NMp" 69 | 70 | And 71 | 72 | i.new.g.should == "INp" 73 | 74 | And 75 | 76 | e.f.should == "NMp" 77 | 78 | And 79 | 80 | e.g.should == "ENp" 81 | 82 | Given nested parametric mixins without parameters. 83 | 84 | m = Module.new do 85 | include Paramix::Parametric 86 | 87 | parameterized do |params| 88 | public :f do 89 | params[:p] 90 | end 91 | end 92 | end 93 | 94 | n = Module.new do 95 | include m 96 | 97 | parameterized do |params| 98 | public :g do 99 | params[:p] 100 | end 101 | end 102 | end 103 | 104 | i = Class.new do 105 | include n[:p => "INp"] 106 | end 107 | 108 | e = Class.new do 109 | extend n[:p => "ENp"] 110 | end 111 | 112 | Then 113 | 114 | i.new.f.should == "INp" 115 | 116 | And 117 | 118 | i.new.g.should == "INp" 119 | 120 | And 121 | 122 | e.f.should == "ENp" 123 | 124 | And 125 | 126 | e.g.should == "ENp" 127 | 128 | Given nested parametric mixins where the outer is not parameterized. 129 | 130 | m = Module.new do 131 | include Paramix::Parametric 132 | 133 | parameterized do |params| 134 | public :f do 135 | params[:p] 136 | end 137 | end 138 | end 139 | 140 | n = Module.new do 141 | include Paramix::Parametric 142 | include m[:p=>"NMp"] 143 | end 144 | 145 | i = Class.new do ; include n[] ; end 146 | e = Class.new do ; extend n[] ; end 147 | 148 | ix = Class.new do ; include n[:p=>"IxNp"] ; end 149 | ex = Class.new do ; extend n[:p=>"ExNp"] ; end 150 | 151 | Then 152 | 153 | i.new.f.should == "NMp" 154 | 155 | 156 | And 157 | 158 | e.f.should == "NMp" 159 | 160 | And 161 | 162 | i.new.f.should == "NMp" 163 | 164 | And 165 | 166 | e.f.should == "NMp" 167 | 168 | 169 | Given nested parametric mixins both parameterized. 170 | 171 | m = Module.new do 172 | include Paramix::Parametric 173 | 174 | parameterized do |params| 175 | public :f do 176 | params[:p] 177 | end 178 | end 179 | end 180 | 181 | n = Module.new do 182 | include Paramix::Parametric 183 | include m[:p=>"mood"] 184 | 185 | parameterized do |params| 186 | public :g do 187 | params[:p] 188 | end 189 | end 190 | end 191 | 192 | i = Class.new do 193 | include n[] 194 | end 195 | 196 | e = Class.new do 197 | extend n[] 198 | end 199 | 200 | Then 201 | 202 | i.new.f.should == "mood" 203 | 204 | And 205 | 206 | i.new.g.should == nil # TODO: or error ? 207 | 208 | And 209 | 210 | e.f.should == "mood" 211 | 212 | And 213 | 214 | e.g.should == nil 215 | 216 | -------------------------------------------------------------------------------- /work/deprecated/paramix-2005.rb: -------------------------------------------------------------------------------- 1 | # TITLE: 2 | # 3 | # Parametric Mixins 4 | # 5 | # SUMMARY: 6 | # 7 | # Parametric Mixins provides parameters for mixin modules. 8 | # 9 | # COPYRIGHT: 10 | # 11 | # Copyright (c) 2005 Thomas Sawyer, George Moschovitis 12 | # 13 | # LICENSE: 14 | # 15 | # Ruby License 16 | # 17 | # This module is free software. You may use, modify, and/or redistribute this 18 | # software under the same terms as Ruby. 19 | # 20 | # This program is distributed in the hope that it will be useful, but WITHOUT 21 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 22 | # FOR A PARTICULAR PURPOSE. 23 | # 24 | # AUTHORS: 25 | # 26 | # - Thomas Sawyer 27 | # - George Moschovitis 28 | 29 | require 'facets/module/name' # for basename 30 | 31 | # = Parametric Mixins 32 | # 33 | # Parametric Mixins provides parameters for mixin modules. 34 | # Module parameters can be set at the time of inclusion or extension, 35 | # then accessed via an instance method of the same name as the included 36 | # module. 37 | # 38 | # == Synopsis 39 | # 40 | # module Mixin 41 | # def hello 42 | # puts "Hello from #{Mixin(:name)}" 43 | # end 44 | # end 45 | # 46 | # class MyClass 47 | # include Mixin, :name => 'Ruby' 48 | # end 49 | # 50 | # m = MyClass.new 51 | # m.hello -> 'Hello from Ruby' 52 | # 53 | # You can view the full set of parameters via the #mixin_parameters 54 | # class method, which returns a hash keyed on the included modules. 55 | # 56 | # MyClass.mixin_parameters #=> {Mixin=>{:name=>'Ruby'}} 57 | # MyClass.mixin_parameters[Mixin] #=> {:name=>'Ruby'} 58 | # 59 | # To create _dynamic mixins_ you can use the #included callback 60 | # method along with mixin_parameters method like so: 61 | # 62 | # module Mixin 63 | # def self.included( base ) 64 | # parms = base.mixin_parameters[self] 65 | # base.class_eval { 66 | # def hello 67 | # puts "Hello from #{parms(:name)}" 68 | # end 69 | # } 70 | # end 71 | # end 72 | # 73 | # More conveniently a new callback has been added, #included_with_parameters, 74 | # which passes in the parameters in addition to the base class/module. 75 | # 76 | # module Mixin 77 | # def self.included_with_parameters( base, parms ) 78 | # base.class_eval { 79 | # def hello 80 | # puts "Hello from #{parms(:name)}" 81 | # end 82 | # } 83 | # end 84 | # end 85 | # 86 | # We would prefer to have passed the parameters through the #included callback 87 | # method itself, but implementation of such a feature is much more complicated. 88 | # If a reasonable solution presents itself in the future however, we will fix. 89 | 90 | class Module 91 | 92 | # Store for module parameters. This is local per module 93 | # and indexed on module/class included-into. 94 | def mixin_parameters ; @mixin_parameters ||= {} ; end 95 | 96 | alias_method :include_without_parameters, :include 97 | 98 | def include(*args) 99 | params = args.last.is_a?(Hash) ? args.pop : {} 100 | args.each do |mod| 101 | mixin_parameters[mod] = params 102 | if mod.basename 103 | define_method( mod.basename ) do |key| 104 | if params.key?(key) 105 | params[key] 106 | else 107 | super if defined?( super ) 108 | end 109 | end 110 | end 111 | end 112 | r = include_without_parameters(*args) 113 | for mod in args 114 | if mod.respond_to?(:included_with_parameters) 115 | mod.included_with_parameters( self, params ) 116 | end 117 | end 118 | r 119 | end 120 | 121 | alias_method :extend_without_parameters, :extend 122 | 123 | def extend(*args) 124 | params = args.last.is_a?(Hash) ? args.pop : {} 125 | args.each do |mod| 126 | (class << self; self; end).class_eval do 127 | mixin_parameters[mod] = params 128 | if mod.basename 129 | define_method( mod.basename ) do |key| 130 | if params.key?(key) 131 | params[key] 132 | else 133 | super if defined?( super ) 134 | end 135 | end 136 | end 137 | end 138 | end 139 | r = extend_without_parameters(*args) 140 | for mod in args 141 | if mod.method_defined?(:extended_with_parameters) 142 | mod.extended_with_parameters( self, params ) 143 | end 144 | end 145 | r 146 | end 147 | 148 | end 149 | -------------------------------------------------------------------------------- /.gemspec: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'yaml' 4 | 5 | Gem::Specification.new do |gemspec| 6 | 7 | manifest = Dir.glob('manifest{,.txt}', File::FNM_CASEFOLD).first 8 | 9 | scm = case 10 | when File.directory?('.git') 11 | :git 12 | end 13 | 14 | files = case 15 | when manifest 16 | File.readlines(manifest). 17 | map{ |line| line.strip }. 18 | reject{ |line| line.empty? || line[0,1] == '#' } 19 | when scm == :git 20 | `git ls-files -z`.split("\0") 21 | else 22 | Dir.glob('{**/}{.*,*}') # TODO: be more specific using standard locations ? 23 | end.select{ |path| File.file?(path) } 24 | 25 | patterns = { 26 | :bin_files => 'bin/*', 27 | :lib_files => 'lib/{**/}*.rb', 28 | :ext_files => 'ext/{**/}extconf.rb', 29 | :doc_files => '*.{txt,rdoc,md,markdown,tt,textile}', 30 | :test_files => '{test/{**/}*_test.rb,spec/{**/}*_spec.rb}' 31 | } 32 | 33 | glob_files = lambda { |pattern| 34 | Dir.glob(pattern).select { |path| 35 | File.file?(path) && files.include?(path) 36 | } 37 | } 38 | 39 | #files = glob_files[patterns[:files]] 40 | 41 | executables = glob_files[patterns[:bin_files]].map do |path| 42 | File.basename(path) 43 | end 44 | 45 | extensions = glob_files[patterns[:ext_files]].map do |path| 46 | File.basename(path) 47 | end 48 | 49 | metadata = YAML.load_file('.ruby') 50 | 51 | # build-out the gemspec 52 | 53 | case metadata['revision'] 54 | when 0 55 | gemspec.name = metadata['name'] 56 | gemspec.version = metadata['version'] 57 | gemspec.summary = metadata['summary'] 58 | gemspec.description = metadata['description'] 59 | 60 | metadata['authors'].each do |author| 61 | gemspec.authors << author['name'] 62 | 63 | if author.has_key?('email') 64 | if gemspec.email 65 | gemspec.email << author['email'] 66 | else 67 | gemspec.email = [author['email']] 68 | end 69 | end 70 | end 71 | 72 | gemspec.licenses = metadata['licenses'] 73 | 74 | metadata['requirements'].each do |req| 75 | name = req['name'] 76 | version = req['version'] 77 | groups = req['groups'] || [] 78 | 79 | #development = req['development'] 80 | #if development 81 | # # populate development dependencies 82 | # if gemspec.respond_to?(:add_development_dependency) 83 | # gemspec.add_development_dependency(name,*version) 84 | # else 85 | # gemspec.add_dependency(name,*version) 86 | # end 87 | #else 88 | # # populate runtime dependencies 89 | # if gemspec.respond_to?(:add_runtime_dependency) 90 | # gemspec.add_runtime_dependency(name,*version) 91 | # else 92 | # gemspec.add_dependency(name,*version) 93 | # end 94 | #end 95 | 96 | if groups.empty? or groups.include?('runtime') 97 | # populate runtime dependencies 98 | if gemspec.respond_to?(:add_runtime_dependency) 99 | gemspec.add_runtime_dependency(name,*version) 100 | else 101 | gemspec.add_dependency(name,*version) 102 | end 103 | else 104 | # populate development dependencies 105 | if gemspec.respond_to?(:add_development_dependency) 106 | gemspec.add_development_dependency(name,*version) 107 | else 108 | gemspec.add_dependency(name,*version) 109 | end 110 | end 111 | end 112 | 113 | # convert external dependencies into a requirements 114 | if metadata['external_dependencies'] 115 | ##gemspec.requirements = [] unless metadata['external_dependencies'].empty? 116 | metadata['external_dependencies'].each do |req| 117 | gemspec.requirements << req.to_s 118 | end 119 | end 120 | 121 | # determine homepage from resources 122 | homepage = metadata['resources'].find{ |key, url| key =~ /^home/ } 123 | gemspec.homepage = homepage.last if homepage 124 | 125 | gemspec.require_paths = metadata['load_path'] || ['lib'] 126 | gemspec.post_install_message = metadata['install_message'] 127 | 128 | # RubyGems specific metadata 129 | gemspec.files = files 130 | gemspec.extensions = extensions 131 | gemspec.executables = executables 132 | 133 | if Gem::VERSION < '1.7.' 134 | gemspec.default_executable = gemspec.executables.first 135 | end 136 | 137 | gemspec.test_files = glob_files[patterns[:test_files]] 138 | 139 | unless gemspec.files.include?('.document') 140 | gemspec.extra_rdoc_files = glob_files[patterns[:doc_files]] 141 | end 142 | end 143 | end 144 | -------------------------------------------------------------------------------- /work/deprecated/paramix-2008.rb: -------------------------------------------------------------------------------- 1 | # TITLE: 2 | # 3 | # Parametric Mixins 4 | # 5 | # SUMMARY: 6 | # 7 | # Parametric Mixins provides parameters for mixin modules. 8 | # 9 | # COPYRIGHT: 10 | # 11 | # Copyright (c) 2008 T. Sawyer 12 | # 13 | # LICENSE: 14 | # 15 | # Ruby License 16 | # 17 | # This module is free software. You may use, modify, and/or redistribute this 18 | # software under the same terms as Ruby. 19 | # 20 | # This program is distributed in the hope that it will be useful, but WITHOUT 21 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 22 | # FOR A PARTICULAR PURPOSE. 23 | # 24 | # AUTHORS: 25 | # 26 | # - Thomas Sawyer 27 | 28 | 29 | # = Parametric Mixin 30 | # 31 | # Parametric Mixins provides parameters for mixin modules. 32 | # Module parameters can be set at the time of inclusion 33 | # or extension using Module#[] method, then parameters 34 | # can be accessed via the #mixin_parameters method. 35 | # 36 | # module MyMixin 37 | # include Paramix 38 | # 39 | # def hello 40 | # puts "Hello from #{mixin_parameters[MyMixin][:name]}!" 41 | # end 42 | # end 43 | # 44 | # class MyClass 45 | # include MyMixin[:name => 'Ruby'] 46 | # end 47 | # 48 | # m = MyClass.new 49 | # m.hello #=> 'Hello from Ruby!' 50 | # 51 | # You can view the full set of parameters via the #mixin_parameters 52 | # class method, which returns a hash keyed on the included modules. 53 | # 54 | # MyClass.mixin_parameters #=> {MyMixin=>{:name=>'Ruby'}} 55 | # MyClass.mixin_parameters[MyMixin] #=> {:name=>'ruby'} 56 | # 57 | # The include Paramix is equivalent to: 58 | # 59 | # def [](parameters) 60 | # Paramix.new(self, parameters) 61 | # end 62 | # 63 | # Paramix.new can also take a block that injects code into the class 64 | # or module including the parametric mixin. This is useful as an 65 | # alternative to using the #included callback for creating dynamic 66 | # mixins. For example: 67 | # 68 | # def self.[](parameters) 69 | # Paramix.new(self, parameters) do 70 | # attr_accessor mixin_params[MyMixin][:name] 71 | # end 72 | # end 73 | # 74 | # As opposed to: 75 | # 76 | # module Mixin 77 | # def self.included(base) 78 | # base.class_eval do 79 | # attr_accessor mixin_params[MyMixin][:name] 80 | # end 81 | # end 82 | # end 83 | # 84 | #-- 85 | # More conveniently a new callback has been added, #included_with_parameters, 86 | # which passes in the parameters in addition to the base class/module. 87 | # 88 | # module Mixin 89 | # def self.included_with_parameters( base, parms ) 90 | # base.class_eval { 91 | # def hello 92 | # puts "Hello from #{mixin_parameters[Mixin][:name]}" 93 | # end 94 | # } 95 | # end 96 | # end 97 | # 98 | # We would prefer to have passed the parameters through the #included callback 99 | # method itself, but implementation of such a feature is much more complicated. 100 | # If a reasonable solution presents itself in the future however, we will fix. 101 | #++ 102 | 103 | module Paramix # or PatrametricMixin ? 104 | 105 | def self.append_features(base) 106 | (class << base; self; end).class_eval do 107 | define_method(:[]) do |parameters| # TODO until 1.9 no &block 108 | Delegator.new(base, parameters) 109 | end 110 | end 111 | end 112 | 113 | # It you want to define the module's ::[] method by hand. You 114 | # can use Paramix.new instead of Paramix::Delegator.new. 115 | 116 | def self.new(delegate_module, parameters={}, &base_block) 117 | Delegator.new(delegate_module, parameters, &base_block) 118 | end 119 | 120 | # 121 | 122 | class Delegator < Module 123 | 124 | attr :module_delegate 125 | attr :parameters 126 | attr :base_block 127 | 128 | # 129 | 130 | def initialize(module_delegate, parameters={}, &base_block) 131 | @module_delegate = module_delegate 132 | @parameters = parameters 133 | @base_block = base_block 134 | end 135 | 136 | # 137 | 138 | def append_features(base) 139 | base.extend Parameterize 140 | 141 | base.mixin_parameters[module_delegate] = parameters 142 | 143 | base.module_eval do 144 | define_method(:mixin_parameters) do 145 | base.mixin_parameters 146 | end 147 | alias_method :mixin_params, :mixin_parameters 148 | end 149 | 150 | base.module_eval(&@base_block) if base_block 151 | 152 | base.__send__(:include, module_delegate) 153 | end 154 | 155 | # 156 | 157 | def extend_object(base) 158 | baseclass = (class << base; self; end) 159 | 160 | baseclass.extend Parameterize 161 | 162 | baseclass.mixin_parameters[module_delegate] = parameters 163 | 164 | baseclass.module_eval do 165 | define_method(:mixin_parameters) do 166 | baseclass.mixin_parameters 167 | end 168 | alias_method :mixin_params, :mixin_parameters 169 | end 170 | 171 | baseclass.module_eval(&@base_block) if base_block 172 | 173 | base.__send__(:extend, module_delegate) 174 | end 175 | 176 | def [](name) 177 | @parameters[name] 178 | end 179 | 180 | end 181 | 182 | # 183 | module Parameterize 184 | # Store for parametric mixin parameters. 185 | # 186 | # Returns a hash, the keys of which are the parametric mixin module 187 | # and the values are the parameters associacted with this module/class. 188 | # 189 | # class C 190 | # include P[:x=>1] 191 | # end 192 | # 193 | # C.mixin_parameters[P] #=> {:x=>1} 194 | # 195 | def mixin_parameters 196 | @mixin_parameters ||= {} 197 | end 198 | 199 | alias_method :mixin_params, :mixin_parameters 200 | end 201 | 202 | end 203 | 204 | =begin 205 | class Module 206 | 207 | # Store for parametric mixin parameters. 208 | # 209 | # Returns a hash, the keys of which are the parametric mixin module 210 | # and the values are the parameters associacted with this module/class. 211 | # 212 | # class C 213 | # include P(:x=>1) 214 | # end 215 | # 216 | # C.mixin_parameters[P] #=> {:x=>1} 217 | # 218 | def mixin_parameters 219 | @mixin_parameters ||= {} 220 | end 221 | 222 | alias_method :mixin_params, :mixin_parameters 223 | 224 | end 225 | =end 226 | 227 | -------------------------------------------------------------------------------- /work/oldschool/dynamod.rb: -------------------------------------------------------------------------------- 1 | #-- 2 | # Dynamic Mixins 3 | # 4 | # Copyright (c) 2005 George Moschovitis and Thomas Sawyer 5 | # 6 | # Ruby License 7 | # 8 | # This module is free software. You may use, modify, and/or redistribute this 9 | # software under the same terms as Ruby. 10 | # 11 | # This program is distributed in the hope that it will be useful, but WITHOUT 12 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 | # FOR A PARTICULAR PURPOSE. 14 | # 15 | # ========================================================================== 16 | # Revision History :: 17 | # -------------------------------------------------------------------------- 18 | # 2005.09.19 trans * Cleaned up and renamed. 19 | # 2005.04.28 trans * Added to Calibre. 20 | # ========================================================================== 21 | # 22 | # TODO include parameters may need to be kept separate from include 23 | # parameters. Currently they are clobbering one another --which must be 24 | # fixed. 25 | #++ 26 | 27 | #:title: Dynamic Mixins 28 | # 29 | # Provides a construction mechinism for creating dynamically generated 30 | # module features as well as instance accessible module parameters which 31 | # can be set at the time of inclusion or extension. 32 | # 33 | # == Example 34 | # 35 | # To create a dynamic feature use the #dyanmic_feature method defining a block 36 | # which returns a block or string to by evaluated into the modules body upon 37 | # inclusion or extension. 38 | # 39 | # module Mixin 40 | # 41 | # dynamic_feature do |options| 42 | # 43 | # define_method :hello do 44 | # puts "Hello from #{options[:name]}" 45 | # end 46 | # 47 | # end 48 | # 49 | # end 50 | # 51 | # class MyClass 52 | # include Mixin, :name => 'Ruby' 53 | # end 54 | # 55 | # m = MyClass.new 56 | # m.hello -> 'Hello from Ruby' 57 | # 58 | # Rather then an open code block the block can instead 59 | # return a string to be evaluated. 60 | # 61 | # module Mixin 62 | # 63 | # dynamic_feature do |options| %/ 64 | # 65 | # def hello 66 | # puts "Hello from #{options[:name]}" 67 | # end 68 | # 69 | # /end 70 | # 71 | # end 72 | # 73 | # class MyClass 74 | # include Mixin, :name => 'Ruby' 75 | # end 76 | # 77 | # m = MyClass.new 78 | # m.hello -> 'Hello from Ruby' 79 | # 80 | # == Author(s) 81 | # 82 | # * George Moschovitis 83 | # * Thomas Sawyer 84 | # 85 | 86 | class Module 87 | 88 | def dynamic_feature( &blk ) 89 | (@module_features ||= []) << blk 90 | end 91 | 92 | # Store for a module's dynamic features. 93 | def module_features ; @module_features ||= [] ; end 94 | 95 | # Store for module parameters. This is local per module 96 | # and indexed on module/class included-into. 97 | def module_parameters ; @module_parameters ||= {} ; end 98 | 99 | alias_method :include_without_dynamic_features, :include 100 | 101 | def include(*args) 102 | options = args.last.is_a?(Hash) ? args.pop : {} 103 | for mod in args 104 | module_parameters[mod] = options 105 | mod.append_dynamic_features( self, options ) 106 | end 107 | include_without_dynamic_features(*args) 108 | end 109 | 110 | def append_dynamic_features( base, options ) 111 | # module_options 112 | mod = self 113 | define_method( :module_options ) do |key| 114 | base.module_parameter_get( mod, key ) 115 | end 116 | # dynamic features 117 | module_features.each do |mf| 118 | eingenclass = (class << base; self; end) 119 | eingenclass.class_eval { 120 | define_method( :_explode, &mf ) 121 | } 122 | r = base._explode(options) 123 | eingenclass.class_eval { 124 | remove_method( :_explode ) 125 | } 126 | # if string block 127 | base.class_eval r if r.is_a?(String) 128 | end 129 | end 130 | 131 | alias_method :extend_without_dynamic_features, :extend 132 | 133 | def extend(*args) 134 | options = args.last.is_a?(Hash) ? args.pop : {} 135 | for mod in args 136 | module_parameters[mod] = options 137 | mod.extend_dynamic_object( self, options ) 138 | end 139 | extend_without_dynamic_features(*args) 140 | end 141 | 142 | # Note: Is this the best name for this callback? 143 | def extend_dynamic_object( base, options ) 144 | # module_options 145 | mod = self 146 | eingenclass = (class << base; self; end) 147 | eingenclass.__send__(:define_method, :module_options ) do |key| 148 | base.module_parameter_get( mod, key ) 149 | end 150 | module_features.each do |mf| 151 | eingenclass.class_eval { 152 | (class << self; self; end).__send__(:define_method, :_explode, &mf ) 153 | } 154 | r = eingenclass._explode(options) 155 | eingenclass.class_eval { 156 | (class << self; self; end).__send__(:remove_method, :_explode ) 157 | } 158 | # if it is a string block 159 | eingenclass.class_eval r if r.is_a?(String) 160 | end 161 | end 162 | 163 | # # Defines a instance attribute linked to a specific module parameter. 164 | # def attr_parameter( *opts ) 165 | # hopts = opts.pop if Hash === opts.last 166 | # opts.each { |k| hopts[k] = nil } 167 | # mod = self 168 | # hopts.each { |key, default| 169 | # self.instance_eval { 170 | # define_method( key ) do 171 | # self.class.module_parameter_get( mod, key ) || default 172 | # end 173 | # } 174 | # } 175 | # end 176 | 177 | # Convenice method for looking up a parameter 178 | def module_parameter_get( mod, key ) 179 | if self.module_parameters.key?(mod) 180 | self.module_parameters[mod][key] 181 | else 182 | anc = self.ancestors[1] 183 | if anc 184 | anc.module_parameter_get( mod, key ) 185 | end 186 | end 187 | end 188 | #protected :module_parameter_get 189 | 190 | end 191 | 192 | 193 | 194 | # _____ _ 195 | # |_ _|__ ___| |_ 196 | # | |/ _ \/ __| __| 197 | # | | __/\__ \ |_ 198 | # |_|\___||___/\__| 199 | # 200 | 201 | #=begin testing 202 | 203 | require 'test/unit' 204 | 205 | class TC01 < Test::Unit::TestCase 206 | 207 | module M 208 | dynamic_feature do |opt| 209 | p self 210 | define_method :f do 211 | opt[:p] 212 | end 213 | end 214 | end 215 | class C 216 | include M, :p => "check" 217 | end 218 | 219 | def test_01_001 220 | assert_equal( "check", C.new.f ) 221 | end 222 | end 223 | 224 | class TC02 < Test::Unit::TestCase 225 | module M 226 | def f ; module_options(:s) ; end 227 | end 228 | class C 229 | include M, :s => "check 123" 230 | end 231 | 232 | def test_02_001 233 | assert_equal( "check 123", C.new.f ) 234 | end 235 | end 236 | 237 | class TC03 < Test::Unit::TestCase 238 | module M 239 | def f ; module_options(:q) ; end 240 | end 241 | class C 242 | extend M, :q => "check 123" 243 | end 244 | 245 | def test_03_001 246 | assert_equal( "check 123", C.f ) 247 | end 248 | end 249 | 250 | #=end 251 | -------------------------------------------------------------------------------- /work/oldschool/dynamix.rb: -------------------------------------------------------------------------------- 1 | #-- 2 | # Dynamic Mixins 3 | # 4 | # Copyright (c) 2005 George Moschovitis and Thomas Sawyer 5 | # 6 | # Ruby License 7 | # 8 | # This module is free software. You may use, modify, and/or redistribute this 9 | # software under the same terms as Ruby. 10 | # 11 | # This program is distributed in the hope that it will be useful, but WITHOUT 12 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 | # FOR A PARTICULAR PURPOSE. 14 | # 15 | # ========================================================================== 16 | # Revision History :: 17 | # -------------------------------------------------------------------------- 18 | # 2005.09.19 trans * Cleaned up and renamed. 19 | # 2005.04.28 trans * Added to Calibre. 20 | # ========================================================================== 21 | # 22 | # TODO include parameters may need to be kept separate from include 23 | # parameters. Currently they are clobbering one another --which must be 24 | # fixed. 25 | #++ 26 | 27 | require './paramixins' 28 | 29 | #:title: Dynamic Mixins 30 | # 31 | # Provides a construction mechinism for creating dynamically generated 32 | # module features as well as instance accessible module parameters which 33 | # can be set at the time of inclusion or extension. 34 | # 35 | # == Example 36 | # 37 | # To create a dynamic feature use the #dyanmic_feature method defining a block 38 | # which returns a block or string to by evaluated into the modules body upon 39 | # inclusion or extension. 40 | # 41 | # module Mixin 42 | # 43 | # dynamic_feature do 44 | # 45 | # define_method :hello do 46 | # puts "Hello from #{Mixin(:name)}" 47 | # end 48 | # 49 | # end 50 | # 51 | # end 52 | # 53 | # class MyClass 54 | # include Mixin, :name => 'Ruby' 55 | # end 56 | # 57 | # m = MyClass.new 58 | # m.hello -> 'Hello from Ruby' 59 | # 60 | # Rather then an open code block the block can instead 61 | # return a string to be evaluated. 62 | # 63 | # module Mixin 64 | # 65 | # dynamic_feature do |options| %/ 66 | # 67 | # def hello 68 | # puts "Hello from #{options[:name]}" 69 | # end 70 | # 71 | # /end 72 | # 73 | # end 74 | # 75 | # class MyClass 76 | # include Mixin, :name => 'Ruby' 77 | # end 78 | # 79 | # m = MyClass.new 80 | # m.hello -> 'Hello from Ruby' 81 | # 82 | # == Author(s) 83 | # 84 | # * George Moschovitis 85 | # * Thomas Sawyer 86 | # 87 | 88 | class Module 89 | 90 | # Store for a module's dynamic features. 91 | def dynamic_features ; @dynamic_features ||= [] ; end 92 | 93 | # Create a dynamic feature. 94 | def dynamic_feature( &blk ) 95 | adhoc = (class << self; self; end) 96 | adhoc.class_eval { 97 | define_method (:included) do |base| 98 | base.class_eval &blk 99 | end 100 | } 101 | end 102 | 103 | # Store for module parameters. This is local per module 104 | # and indexed on module/class included-into. 105 | # def mixin_parameters ; @mixin_parameters ||= {} ; end 106 | 107 | # alias_method :include_without_dynamic_features, :include 108 | 109 | # def include(*args) 110 | # options = args.last.is_a?(Hash) ? args.pop : {} 111 | # for mod in args 112 | # mixin_parameters[mod] = options 113 | # #mod.append_dynamic_features( self, options ) 114 | # end 115 | # include_without_dynamic_features(*args) 116 | # end 117 | 118 | end 119 | 120 | =begin 121 | # Store for module parameters. This is local per module 122 | # and indexed on module/class included-into. 123 | def mixin_parameters ; @mixin_parameters ||= {} ; end 124 | 125 | alias_method :include_without_dynamic_features, :include 126 | 127 | def include(*args) 128 | options = args.last.is_a?(Hash) ? args.pop : {} 129 | for mod in args 130 | module_parameters[mod] = options 131 | mod.append_dynamic_features( self, options ) 132 | end 133 | include_without_dynamic_features(*args) 134 | end 135 | 136 | def append_dynamic_features( base, options ) 137 | # module_options 138 | mod = self 139 | define_method( :module_options ) do |key| 140 | base.module_parameter_get( mod, key ) 141 | end 142 | # dynamic features 143 | dynamic_features.each do |mf| 144 | adhoc = (class << base; self; end) 145 | adhoc.class_eval { define_method( :__EVAL__, &mf ) } 146 | result = base.__EVAL__(options) 147 | adhoc.class_eval { remove_method( :__EVAL__ ) } 148 | # if string block 149 | base.class_eval result if result.is_a?(String) 150 | end 151 | end 152 | 153 | alias_method :extend_without_dynamic_features, :extend 154 | 155 | def extend(*args) 156 | options = args.last.is_a?(Hash) ? args.pop : {} 157 | for mod in args 158 | module_parameters[mod] = options 159 | mod.extend_dynamic_object( self, options ) 160 | end 161 | extend_without_dynamic_features(*args) 162 | end 163 | 164 | # Note: Is this the best name for this callback? 165 | def extend_dynamic_object( base, options ) 166 | # module_options 167 | mod = self 168 | eingenclass = (class << base; self; end) 169 | eingenclass.__send__(:define_method, :module_options ) do |key| 170 | base.module_parameter_get( mod, key ) 171 | end 172 | module_features.each do |mf| 173 | eingenclass.class_eval { 174 | (class << self; self; end).__send__(:define_method, :_explode, &mf ) 175 | } 176 | r = eingenclass._explode(options) 177 | eingenclass.class_eval { 178 | (class << self; self; end).__send__(:remove_method, :_explode ) 179 | } 180 | # if it is a string block 181 | eingenclass.class_eval r if r.is_a?(String) 182 | end 183 | end 184 | 185 | # # Defines a instance attribute linked to a specific module parameter. 186 | # def attr_parameter( *opts ) 187 | # hopts = opts.pop if Hash === opts.last 188 | # opts.each { |k| hopts[k] = nil } 189 | # mod = self 190 | # hopts.each { |key, default| 191 | # self.instance_eval { 192 | # define_method( key ) do 193 | # self.class.module_parameter_get( mod, key ) || default 194 | # end 195 | # } 196 | # } 197 | # end 198 | 199 | # Convenice method for looking up a parameter 200 | def module_parameter_get( mod, key ) 201 | if self.module_parameters.key?(mod) 202 | self.module_parameters[mod][key] 203 | else 204 | anc = self.ancestors[1] 205 | if anc 206 | anc.module_parameter_get( mod, key ) 207 | end 208 | end 209 | end 210 | #protected :module_parameter_get 211 | 212 | end 213 | =end 214 | 215 | 216 | # _____ _ 217 | # |_ _|__ ___| |_ 218 | # | |/ _ \/ __| __| 219 | # | | __/\__ \ |_ 220 | # |_|\___||___/\__| 221 | # 222 | 223 | #=begin testing 224 | 225 | require 'test/unit' 226 | 227 | class TC01 < Test::Unit::TestCase 228 | 229 | module M 230 | dynamic_feature do |opt| 231 | p self 232 | define_method(:f){ M(:p) } 233 | end 234 | end 235 | class C 236 | include M, :p => "check" 237 | end 238 | 239 | def test_01_001 240 | assert_equal( "check", C.new.f ) 241 | end 242 | 243 | end 244 | 245 | =begin 246 | 247 | class TC02 < Test::Unit::TestCase 248 | module M 249 | def f ; module_options(:s) ; end 250 | end 251 | class C 252 | include M, :s => "check 123" 253 | end 254 | 255 | def test_02_001 256 | assert_equal( "check 123", C.new.f ) 257 | end 258 | end 259 | 260 | class TC03 < Test::Unit::TestCase 261 | module M 262 | def f ; module_options(:q) ; end 263 | end 264 | class C 265 | extend M, :q => "check 123" 266 | end 267 | 268 | def test_03_001 269 | assert_equal( "check 123", C.f ) 270 | end 271 | end 272 | 273 | =end 274 | --------------------------------------------------------------------------------