shared 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,183 @@
1
+ NAME
2
+ shared.rb
3
+
4
+ DESCRIPTION
5
+ super simple super power sharing of instance and class level code
6
+
7
+ INSTALL
8
+ gem install shared
9
+
10
+ URIS
11
+ http://rubyforge.org/projects/codeforpeople
12
+ http://codeforpeople.com/lib/ruby/
13
+
14
+ HISTORY
15
+ 0.4.2
16
+ initial version
17
+
18
+ SAMPLES
19
+
20
+ <========< samples/a.rb >========>
21
+
22
+ ~ > cat samples/a.rb
23
+
24
+ # shared.rb is a very simple and very powerful method of sharing code between
25
+ # classes.
26
+ #
27
+ require 'shared'
28
+
29
+ shared(:code) do
30
+ def classname() self.class.name end
31
+ end
32
+
33
+ class Foo
34
+ include shared(:code)
35
+ end
36
+
37
+ class Bar
38
+ include shared(:code)
39
+ end
40
+
41
+ p Foo.new.classname #=> "Foo"
42
+
43
+ p Bar.new.classname #=> "Bar"
44
+
45
+ ~ > ruby samples/a.rb
46
+
47
+ "Foo"
48
+ "Bar"
49
+
50
+
51
+ <========< samples/b.rb >========>
52
+
53
+ ~ > cat samples/b.rb
54
+
55
+ # shared.rb allows natural declaration of both instance and class-level
56
+ # methods - it's more than simple module inclusion
57
+ #
58
+
59
+ require 'shared'
60
+
61
+ shared('methods') do
62
+ def self.class_method() 40 end
63
+
64
+ def instance_method() 2 end
65
+ end
66
+
67
+ class C
68
+ include shared('methods')
69
+ end
70
+
71
+ p(C.class_method + C.new.instance_method) #=> 42
72
+
73
+
74
+ ~ > ruby samples/b.rb
75
+
76
+ 42
77
+
78
+
79
+ <========< samples/c.rb >========>
80
+
81
+ ~ > cat samples/c.rb
82
+
83
+ # shared.rb works equally well with individual objects in addition to the
84
+ # normal class level usage
85
+ #
86
+
87
+ require 'shared'
88
+
89
+ shared(:meta_tools) do
90
+ def singleton_class &block
91
+ singleton_class =
92
+ class << self
93
+ self
94
+ end
95
+ block ? singleton_class.module_eval(&block) : singleton_class
96
+ end
97
+ end
98
+
99
+ a = %w( a b c )
100
+
101
+ a.extend shared(:meta_tools)
102
+
103
+ a.singleton_class do
104
+ def to_range() first .. last end
105
+ end
106
+
107
+ p a.to_range #=> "a".."c"
108
+
109
+ ~ > ruby samples/c.rb
110
+
111
+ "a".."c"
112
+
113
+
114
+ <========< samples/d.rb >========>
115
+
116
+ ~ > cat samples/d.rb
117
+
118
+ # an example use-case for shared.rb is sharing code bewteen classes that
119
+ # require both class level and instance level behaviour to be shared
120
+ #
121
+
122
+ require 'shared'
123
+
124
+ shared(:acts_as_named) do
125
+ validates_precence_of :name
126
+
127
+ def to_html() "<blink> #{ name } </blink>" end
128
+ end
129
+
130
+ class Model
131
+ def Model.validates_precence_of(*a) end
132
+
133
+ def name() 'zaphod' end
134
+
135
+ include shared(:acts_as_named)
136
+ end
137
+
138
+ p Model.new.to_html #=> "<blink> zaphod </blink>"
139
+
140
+ ~ > ruby samples/d.rb
141
+
142
+ "<blink> zaphod </blink>"
143
+
144
+
145
+ <========< samples/e.rb >========>
146
+
147
+ ~ > cat samples/e.rb
148
+
149
+ # it's important to note that the shared code is injected into the reciever
150
+ # fresh on each call and, in that way, the effect is rather macro like
151
+ #
152
+
153
+ require 'shared'
154
+
155
+ share(:instance_tracker) do
156
+ const_set :Instances, []
157
+
158
+ def self.instances() const_get :Instances end
159
+
160
+ def self.new *a, &b
161
+ obj = super
162
+ ensure
163
+ instances << obj
164
+ end
165
+ end
166
+
167
+ class Foo
168
+ include shared(:instance_tracker)
169
+ end
170
+
171
+ class Bar
172
+ include shared(:instance_tracker)
173
+ end
174
+
175
+ 2.times{ Foo.new }
176
+ 40.times{ Bar.new }
177
+
178
+ p(Foo.instances.size + Bar.instances.size)
179
+
180
+ ~ > ruby samples/e.rb
181
+
182
+ 42
183
+
data/gemspec.rb ADDED
@@ -0,0 +1,38 @@
1
+ #! /usr/bin/env gem build
2
+
3
+ lib, version = File::basename(File::dirname(File::expand_path(__FILE__))).split %r/-/, 2
4
+
5
+ require 'rubygems'
6
+
7
+ Gem::Specification::new do |spec|
8
+ $VERBOSE = nil
9
+
10
+ shiteless = lambda do |list|
11
+ list.delete_if do |file|
12
+ file =~ %r/\.svn/ or
13
+ file =~ %r/\.tmp/
14
+ end
15
+ end
16
+
17
+ spec.name = lib
18
+ spec.version = version
19
+ spec.platform = Gem::Platform::RUBY
20
+ spec.summary = lib
21
+
22
+ spec.files = shiteless[Dir::glob("**/**")]
23
+ spec.executables = shiteless[Dir::glob("bin/*")].map{|exe| File::basename exe}
24
+
25
+ spec.require_path = "lib"
26
+
27
+ spec.has_rdoc = File::exist? "doc"
28
+ spec.test_suite_file = "test/#{ lib }.rb" if File::directory? "test"
29
+ #spec.add_dependency 'lib', '>= version'
30
+ spec.add_dependency 'fattr'
31
+
32
+ spec.extensions << "extconf.rb" if File::exists? "extconf.rb"
33
+
34
+ spec.rubyforge_project = 'codeforpeople'
35
+ spec.author = "Ara T. Howard"
36
+ spec.email = "ara.t.howard@gmail.com"
37
+ spec.homepage = "http://codeforpeople.com/lib/ruby/#{ lib }/"
38
+ end
data/gen_readme.rb ADDED
@@ -0,0 +1,35 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require 'pathname'
4
+
5
+ $VERBOSE=nil
6
+
7
+ def indent s, n = 2
8
+ ws = ' ' * n
9
+ s.gsub %r/^/, ws
10
+ end
11
+
12
+ template = IO::read 'README.tmpl'
13
+
14
+ samples = ''
15
+ prompt = '~ > '
16
+
17
+ Dir['sample*/*'].sort.each do |sample|
18
+ samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
19
+
20
+ cmd = "cat #{ sample }"
21
+ samples << indent(prompt + cmd, 2) << "\n\n"
22
+ samples << indent(`#{ cmd }`, 4) << "\n"
23
+
24
+ cmd = "ruby #{ sample }"
25
+ samples << indent(prompt + cmd, 2) << "\n\n"
26
+
27
+ cmd = "ruby -e'STDOUT.sync=true; exec %(ruby -Ilib #{ sample })'"
28
+ #cmd = "ruby -Ilib #{ sample }"
29
+ samples << indent(`#{ cmd } 2>&1`, 4) << "\n"
30
+ end
31
+
32
+ #samples.gsub! %r/^/, ' '
33
+
34
+ readme = template.gsub %r/^\s*@samples\s*$/, samples
35
+ print readme
data/install.rb ADDED
@@ -0,0 +1,214 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rbconfig'
3
+ require 'find'
4
+ require 'ftools'
5
+ require 'tempfile'
6
+ include Config
7
+
8
+ LIBDIR = "lib"
9
+ LIBDIR_MODE = 0644
10
+
11
+ BINDIR = "bin"
12
+ BINDIR_MODE = 0755
13
+
14
+
15
+ $srcdir = CONFIG["srcdir"]
16
+ $version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
17
+ $libdir = File.join(CONFIG["libdir"], "ruby", $version)
18
+ $archdir = File.join($libdir, CONFIG["arch"])
19
+ $site_libdir = $:.find {|x| x =~ /site_ruby$/}
20
+ $bindir = CONFIG["bindir"] || CONFIG['BINDIR']
21
+ $ruby_install_name = CONFIG['ruby_install_name'] || CONFIG['RUBY_INSTALL_NAME'] || 'ruby'
22
+ $ruby_ext = CONFIG['EXEEXT'] || ''
23
+ $ruby = File.join($bindir, ($ruby_install_name + $ruby_ext))
24
+
25
+ if !$site_libdir
26
+ $site_libdir = File.join($libdir, "site_ruby")
27
+ elsif $site_libdir !~ %r/#{Regexp.quote($version)}/
28
+ $site_libdir = File.join($site_libdir, $version)
29
+ end
30
+
31
+ def install_rb(srcdir=nil, destdir=nil, mode=nil, bin=nil)
32
+ #{{{
33
+ path = []
34
+ dir = []
35
+ Find.find(srcdir) do |f|
36
+ next unless FileTest.file?(f)
37
+ next if (f = f[srcdir.length+1..-1]) == nil
38
+ next if (/CVS$/ =~ File.dirname(f))
39
+ next if (/\.svn/ =~ File.dirname(f))
40
+ next if f =~ %r/\.lnk/
41
+ next if f =~ %r/\.svn/
42
+ next if f =~ %r/\.swp/
43
+ next if f =~ %r/\.svn/
44
+ path.push f
45
+ dir |= [File.dirname(f)]
46
+ end
47
+ for f in dir
48
+ next if f == "."
49
+ next if f == "CVS"
50
+ File::makedirs(File.join(destdir, f))
51
+ end
52
+ for f in path
53
+ next if (/\~$/ =~ f)
54
+ next if (/^\./ =~ File.basename(f))
55
+ unless bin
56
+ File::install(File.join(srcdir, f), File.join(destdir, f), mode, true)
57
+ else
58
+ from = File.join(srcdir, f)
59
+ to = File.join(destdir, f)
60
+ shebangify(from) do |sf|
61
+ $deferr.print from, " -> ", File::catname(from, to), "\n"
62
+ $deferr.printf "chmod %04o %s\n", mode, to
63
+ File::install(sf, to, mode, false)
64
+ end
65
+ end
66
+ end
67
+ #}}}
68
+ end
69
+ def shebangify f
70
+ #{{{
71
+ open(f) do |fd|
72
+ buf = fd.read 42
73
+ if buf =~ %r/^\s*#\s*!.*ruby/o
74
+ ftmp = Tempfile::new("#{ $$ }_#{ File::basename(f) }")
75
+ begin
76
+ fd.rewind
77
+ ftmp.puts "#!#{ $ruby }"
78
+ while((buf = fd.read(8192)))
79
+ ftmp.write buf
80
+ end
81
+ ftmp.close
82
+ yield ftmp.path
83
+ ensure
84
+ ftmp.close!
85
+ end
86
+ else
87
+ yield f
88
+ end
89
+ end
90
+ #}}}
91
+ end
92
+ def ARGV.switch
93
+ #{{{
94
+ return nil if self.empty?
95
+ arg = self.shift
96
+ return nil if arg == '--'
97
+ if arg =~ /^-(.)(.*)/
98
+ return arg if $1 == '-'
99
+ raise 'unknown switch "-"' if $2.index('-')
100
+ self.unshift "-#{$2}" if $2.size > 0
101
+ "-#{$1}"
102
+ else
103
+ self.unshift arg
104
+ nil
105
+ end
106
+ #}}}
107
+ end
108
+ def ARGV.req_arg
109
+ #{{{
110
+ self.shift || raise('missing argument')
111
+ #}}}
112
+ end
113
+ def linkify d, linked = []
114
+ #--{{{
115
+ if test ?d, d
116
+ versioned = Dir[ File::join(d, "*-[0-9].[0-9].[0-9].rb") ]
117
+ versioned.each do |v|
118
+ src, dst = v, v.gsub(%r/\-[\d\.]+\.rb$/, '.rb')
119
+ lnk = nil
120
+ begin
121
+ if test ?l, dst
122
+ lnk = "#{ dst }.lnk"
123
+ puts "#{ dst } -> #{ lnk }"
124
+ File::rename dst, lnk
125
+ end
126
+ unless test ?e, dst
127
+ puts "#{ src } -> #{ dst }"
128
+ File::copy src, dst
129
+ linked << dst
130
+ end
131
+ ensure
132
+ if lnk
133
+ at_exit do
134
+ puts "#{ lnk } -> #{ dst }"
135
+ File::rename lnk, dst
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
141
+ linked
142
+ #--}}}
143
+ end
144
+
145
+
146
+ #
147
+ # main program
148
+ #
149
+
150
+ libdir = $site_libdir
151
+ bindir = $bindir
152
+ no_linkify = false
153
+ linked = nil
154
+ help = false
155
+
156
+ usage = <<-usage
157
+ #{ File::basename $0 }
158
+ -d, --destdir <destdir>
159
+ -l, --libdir <libdir>
160
+ -b, --bindir <bindir>
161
+ -r, --ruby <ruby>
162
+ -n, --no_linkify
163
+ -s, --sudo
164
+ -h, --help
165
+ usage
166
+
167
+ begin
168
+ while switch = ARGV.switch
169
+ case switch
170
+ when '-d', '--destdir'
171
+ libdir = ARGV.req_arg
172
+ when '-l', '--libdir'
173
+ libdir = ARGV.req_arg
174
+ when '-b', '--bindir'
175
+ bindir = ARGV.req_arg
176
+ when '-r', '--ruby'
177
+ $ruby = ARGV.req_arg
178
+ when '-n', '--no_linkify'
179
+ no_linkify = true
180
+ when '-s', '--sudo'
181
+ sudo = 'sudo'
182
+ when '-h', '--help'
183
+ help = true
184
+ else
185
+ raise "unknown switch #{switch.dump}"
186
+ end
187
+ end
188
+ rescue
189
+ STDERR.puts $!.to_s
190
+ STDERR.puts usage
191
+ exit 1
192
+ end
193
+
194
+ if help
195
+ STDOUT.puts usage
196
+ exit
197
+ end
198
+
199
+ system "#{ sudo } #{ $ruby } pre-install.rb" if test(?s, 'pre-install.rb')
200
+
201
+ unless no_linkify
202
+ linked = linkify('lib') + linkify('bin')
203
+ end
204
+
205
+ system "#{ $ruby } extconf.rb && make && #{ sudo } make install" if test(?s, 'extconf.rb')
206
+
207
+ install_rb(LIBDIR, libdir, LIBDIR_MODE)
208
+ install_rb(BINDIR, bindir, BINDIR_MODE, bin=true)
209
+
210
+ if linked
211
+ linked.each{|path| File::rm_f path}
212
+ end
213
+
214
+ system "#{ sudo } #{ $ruby } post-install.rb" if test(?s, 'post-install.rb')
data/lib/shared.rb ADDED
@@ -0,0 +1,59 @@
1
+ module Shared
2
+ Code = {}
3
+
4
+ def shared name, &block
5
+ key = key_for name
6
+
7
+ return Code[key] if block.nil?
8
+
9
+ m = (Code[key] || Module.new)
10
+
11
+ singleton_class(m) do
12
+ unless defined?(@@blocks)
13
+ @@blocks = []
14
+
15
+ define_method(:blocks){ @@blocks }
16
+
17
+ define_method(:included) do |other|
18
+ blocks.each{|b| other.send(:module_eval, &b)}
19
+ end
20
+
21
+ define_method(:extend_object) do |other|
22
+ Shared.singleton_class(other) do
23
+ m.blocks.each{|b| module_eval &b}
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ m.blocks << block
30
+
31
+ Code[key] ||= m
32
+ end
33
+
34
+ alias_method 'share', 'shared'
35
+
36
+ def key_for name
37
+ name.to_s.strip.downcase
38
+ end
39
+
40
+ def singleton_class object, &block
41
+ singleton_class =
42
+ class << object
43
+ self
44
+ end
45
+ block ? singleton_class.module_eval(&block) : singleton_class
46
+ end
47
+
48
+ extend self
49
+ end
50
+
51
+ class Object
52
+ def share *a, &b
53
+ Shared.share *a, &b
54
+ end
55
+
56
+ def shared *a, &b
57
+ Shared.shared *a, &b
58
+ end
59
+ end
data/samples/a.rb ADDED
@@ -0,0 +1,20 @@
1
+ # shared.rb is a very simple and very powerful method of sharing code between
2
+ # classes.
3
+ #
4
+ require 'shared'
5
+
6
+ shared(:code) do
7
+ def classname() self.class.name end
8
+ end
9
+
10
+ class Foo
11
+ include shared(:code)
12
+ end
13
+
14
+ class Bar
15
+ include shared(:code)
16
+ end
17
+
18
+ p Foo.new.classname #=> "Foo"
19
+
20
+ p Bar.new.classname #=> "Bar"
data/samples/b.rb ADDED
@@ -0,0 +1,18 @@
1
+ # shared.rb allows natural declaration of both instance and class-level
2
+ # methods - it's more than simple module inclusion
3
+ #
4
+
5
+ require 'shared'
6
+
7
+ shared('methods') do
8
+ def self.class_method() 40 end
9
+
10
+ def instance_method() 2 end
11
+ end
12
+
13
+ class C
14
+ include shared('methods')
15
+ end
16
+
17
+ p(C.class_method + C.new.instance_method) #=> 42
18
+
data/samples/c.rb ADDED
@@ -0,0 +1,25 @@
1
+ # shared.rb works equally well with individual objects in addition to the
2
+ # normal class level usage
3
+ #
4
+
5
+ require 'shared'
6
+
7
+ shared(:meta_tools) do
8
+ def singleton_class &block
9
+ singleton_class =
10
+ class << self
11
+ self
12
+ end
13
+ block ? singleton_class.module_eval(&block) : singleton_class
14
+ end
15
+ end
16
+
17
+ a = %w( a b c )
18
+
19
+ a.extend shared(:meta_tools)
20
+
21
+ a.singleton_class do
22
+ def to_range() first .. last end
23
+ end
24
+
25
+ p a.to_range #=> "a".."c"
data/samples/d.rb ADDED
@@ -0,0 +1,21 @@
1
+ # an example use-case for shared.rb is sharing code bewteen classes that
2
+ # require both class level and instance level behaviour to be shared
3
+ #
4
+
5
+ require 'shared'
6
+
7
+ shared(:acts_as_named) do
8
+ validates_precence_of :name
9
+
10
+ def to_html() "<blink> #{ name } </blink>" end
11
+ end
12
+
13
+ class Model
14
+ def Model.validates_precence_of(*a) end
15
+
16
+ def name() 'zaphod' end
17
+
18
+ include shared(:acts_as_named)
19
+ end
20
+
21
+ p Model.new.to_html #=> "<blink> zaphod </blink>"
data/samples/e.rb ADDED
@@ -0,0 +1,30 @@
1
+ # it's important to note that the shared code is injected into the reciever
2
+ # fresh on each call and, in that way, the effect is rather macro like
3
+ #
4
+
5
+ require 'shared'
6
+
7
+ share(:instance_tracker) do
8
+ const_set :Instances, []
9
+
10
+ def self.instances() const_get :Instances end
11
+
12
+ def self.new *a, &b
13
+ obj = super
14
+ ensure
15
+ instances << obj
16
+ end
17
+ end
18
+
19
+ class Foo
20
+ include shared(:instance_tracker)
21
+ end
22
+
23
+ class Bar
24
+ include shared(:instance_tracker)
25
+ end
26
+
27
+ 2.times{ Foo.new }
28
+ 40.times{ Bar.new }
29
+
30
+ p(Foo.instances.size + Bar.instances.size)
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shared
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.2
5
+ platform: ruby
6
+ authors:
7
+ - Ara T. Howard
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-11-09 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: fattr
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description:
26
+ email: ara.t.howard@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files: []
32
+
33
+ files:
34
+ - gemspec.rb
35
+ - gen_readme.rb
36
+ - install.rb
37
+ - lib
38
+ - lib/shared.rb
39
+ - README
40
+ - samples
41
+ - samples/a.rb
42
+ - samples/b.rb
43
+ - samples/c.rb
44
+ - samples/d.rb
45
+ - samples/e.rb
46
+ has_rdoc: false
47
+ homepage: http://codeforpeople.com/lib/ruby/shared/
48
+ post_install_message:
49
+ rdoc_options: []
50
+
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ requirements: []
66
+
67
+ rubyforge_project: codeforpeople
68
+ rubygems_version: 1.2.0
69
+ signing_key:
70
+ specification_version: 2
71
+ summary: shared
72
+ test_files: []
73
+