ruby-ext 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. data/.git/COMMIT_EDITMSG +1 -0
  2. data/.git/HEAD +1 -0
  3. data/.git/config +12 -0
  4. data/.git/description +1 -0
  5. data/.git/hooks/applypatch-msg.sample +15 -0
  6. data/.git/hooks/commit-msg.sample +24 -0
  7. data/.git/hooks/post-commit.sample +8 -0
  8. data/.git/hooks/post-receive.sample +15 -0
  9. data/.git/hooks/post-update.sample +8 -0
  10. data/.git/hooks/pre-applypatch.sample +14 -0
  11. data/.git/hooks/pre-commit.sample +46 -0
  12. data/.git/hooks/pre-rebase.sample +169 -0
  13. data/.git/hooks/prepare-commit-msg.sample +36 -0
  14. data/.git/hooks/update.sample +128 -0
  15. data/.git/index +0 -0
  16. data/.git/info/exclude +6 -0
  17. data/.git/logs/HEAD +6 -0
  18. data/.git/logs/refs/heads/master +6 -0
  19. data/.git/logs/refs/remotes/origin/master +5 -0
  20. data/.git/objects/01/a6ccb4f4fb0c6cfdf9ec1bb23779721cf503e9 +5 -0
  21. data/.git/objects/05/18bc8be5c58a5bd9d7fc82c75c87478aa361e9 +5 -0
  22. data/.git/objects/05/b76a8d022e0e0fbca5b69b9f7b4d2a132fcc89 +0 -0
  23. data/.git/objects/06/864a068d188ab7ae17e39d58d6c25dc49a8ff3 +2 -0
  24. data/.git/objects/0e/13cf36bc744c90f576c0a31c3f76dcf1fd2485 +0 -0
  25. data/.git/objects/0f/add343d54917efbd138ee2d7c092a52b12ebd5 +0 -0
  26. data/.git/objects/10/53306d48d434b477991f5fb64a6d8d3aca84a0 +0 -0
  27. data/.git/objects/17/70296a7ba0a9aaadd3e857ae34d92d2e13e935 +0 -0
  28. data/.git/objects/20/c2ee1bb9f6749181e464a4ce444092fc1a1ecb +0 -0
  29. data/.git/objects/26/4d70a16bbad0c5b3b16fb7a92bcc6178f2cca2 +2 -0
  30. data/.git/objects/27/eb5694d78540b1a489a1aff5415d4713d5fca9 +0 -0
  31. data/.git/objects/29/88f150ee1623b97d234b2742b30caad382775b +0 -0
  32. data/.git/objects/29/8cb590f97362cc7a326815dac3289a88b69153 +0 -0
  33. data/.git/objects/2b/edc3eb69408a817194c28d14fb2dbfed5a21c0 +2 -0
  34. data/.git/objects/2e/3e3fc8e46949a9b944da3c36207c444aa2c9b7 +0 -0
  35. data/.git/objects/2f/74073c8d1580f5a8fc59389b4c1b6d89e4d85f +0 -0
  36. data/.git/objects/34/a418e8c4b43510124491ff3be262edd8008043 +3 -0
  37. data/.git/objects/38/91f271b22f2a1caee6910a34139076e27ade00 +0 -0
  38. data/.git/objects/38/bf6dbb2520b448e08ac9cb353523bbc72118db +0 -0
  39. data/.git/objects/44/73d59f32a2806eca098ba6bf10cdc2e6453542 +0 -0
  40. data/.git/objects/44/e92f51b4c9a44497c7f170598fae64564052eb +0 -0
  41. data/.git/objects/4b/2ac3de91e560277749f749ed47230ef080d36c +0 -0
  42. data/.git/objects/54/4fb213faf0c1b4cc459ada84120823d204ae3a +4 -0
  43. data/.git/objects/55/a433dd00ba298006a2fc028964eb0cde7c2e5b +0 -0
  44. data/.git/objects/55/f338afb8c82f8cad38b28d0e8cf887f9bda1ce +1 -0
  45. data/.git/objects/57/cf2479bb9c6e31118c42c5cceaffada1862c72 +0 -0
  46. data/.git/objects/59/60bdbdc3be504b89371c2b4b09d22754251260 +0 -0
  47. data/.git/objects/59/653cefe5b174e4a7002100f024448cdb337373 +0 -0
  48. data/.git/objects/5c/28c251bb201232470340d73ed4cc4926cd241d +0 -0
  49. data/.git/objects/5c/536c5d712f7cf34e21be5526aa3e826888810f +0 -0
  50. data/.git/objects/5d/37379f1b929c7b82f96382fc256895a50e97fd +0 -0
  51. data/.git/objects/60/a681e873ca0ae0b7da3f37dbc5701f6e42b970 +1 -0
  52. data/.git/objects/61/d4509b8fc63e53b8e5d417ace33919e8a7a8f2 +0 -0
  53. data/.git/objects/6b/dcac704e4f8abe1928e8f3f5d9b7e17e4992de +0 -0
  54. data/.git/objects/6c/18afba63861887fb7ac53fee1b24c181b2a8e4 +0 -0
  55. data/.git/objects/70/222d828221b1884b6b8ce124b7f22eea5d420d +0 -0
  56. data/.git/objects/74/bf8f37d70d9818474e1fb5081f04c496741a28 +0 -0
  57. data/.git/objects/77/141a7a91a61baff283e5f16e55a720d0bc65e0 +2 -0
  58. data/.git/objects/81/6bb8c35fe2169fa9ecbcd40941c440e5d032e1 +2 -0
  59. data/.git/objects/81/a5373f6837b02ace55c07cebf4a60fb6d4b084 +0 -0
  60. data/.git/objects/82/8cab0a228a826cb346b6cf4ffffac84c674e4b +3 -0
  61. data/.git/objects/84/2a9747ce87d8b90ee360f7252b557ff8e19352 +0 -0
  62. data/.git/objects/90/eea923ef08bb39013e7cd5be777b7539733638 +0 -0
  63. data/.git/objects/93/276f74ef0e157c5f81eeec7844f30d4eceda7a +0 -0
  64. data/.git/objects/9e/a37d9fc7e1ad1504b50da2a1ec639c523fb8b7 +2 -0
  65. data/.git/objects/ab/daaab37771475482389bdfcb2021b1651ba399 +0 -0
  66. data/.git/objects/ad/e1a70e7cf984a2f518d19ef625362d78a5fbd0 +3 -0
  67. data/.git/objects/b6/17a8cc2ae7f6ea496051db493aa56edc178073 +0 -0
  68. data/.git/objects/b6/863b5d4c0a4d87b81a9bbc29e786fcf7ef0df2 +0 -0
  69. data/.git/objects/bc/ee5c51061bdb9ab5a5aea4f00245a8ab3689b2 +0 -0
  70. data/.git/objects/c3/faad9ba42388a50a57acf9df88f6d2a64a4122 +1 -0
  71. data/.git/objects/d4/8b935ca7e38d2434ceb1711544293f4baf8203 +0 -0
  72. data/.git/objects/dd/e851a435431f0c03b12f7a9ca6e5dd5ce80617 +0 -0
  73. data/.git/objects/e0/c54997bfab8a0bf135d0de79ddee431b9112ad +0 -0
  74. data/.git/objects/e9/d385c1913656b7ce15a1ac1424361d2e065a6c +0 -0
  75. data/.git/objects/f0/c37cf78e53e6f859111f35d9dbf52cbfbc633d +0 -0
  76. data/.git/objects/f1/2346269ed5287267f0271f57546291c013b318 +0 -0
  77. data/.git/objects/f3/655e33b96e5b8b25990a2ae88fcdfed415074b +0 -0
  78. data/.git/objects/f7/c0fa5621b81aca548c738c08907055696e1956 +0 -0
  79. data/.git/objects/f8/c960b12cbddb90f18123673e6778efdc822058 +2 -0
  80. data/.git/objects/fb/85b5793dcebae826b04cd8c37406504540d8a4 +2 -0
  81. data/.git/objects/fd/d3ef7ec06e804f3688491e21caaa4d89796b16 +0 -0
  82. data/.git/objects/pack/pack-304aec40b1be62a8e3c105c6423354d9e62bd089.idx +0 -0
  83. data/.git/objects/pack/pack-304aec40b1be62a8e3c105c6423354d9e62bd089.pack +0 -0
  84. data/.git/packed-refs +2 -0
  85. data/.git/refs/heads/master +1 -0
  86. data/.git/refs/remotes/origin/HEAD +1 -0
  87. data/.git/refs/remotes/origin/master +1 -0
  88. data/.gitignore +5 -0
  89. data/README.rdoc +3 -0
  90. data/Rakefile +64 -0
  91. data/lib/ruby_ext/declarative_cache.rb +167 -0
  92. data/lib/ruby_ext/file.rb +23 -0
  93. data/lib/ruby_ext/kernel.rb +21 -0
  94. data/lib/ruby_ext/module.rb +84 -0
  95. data/lib/ruby_ext/not_defined.rb +2 -0
  96. data/lib/ruby_ext/object.rb +7 -0
  97. data/lib/ruby_ext/open_constructor.rb +51 -0
  98. data/lib/ruby_ext/prepare_arguments.rb +105 -0
  99. data/lib/ruby_ext/should.rb +150 -0
  100. data/lib/ruby_ext/string.rb +21 -0
  101. data/lib/ruby_ext/symbol.rb +21 -0
  102. data/lib/ruby_ext/synchronizer.rb +31 -0
  103. data/lib/ruby_ext.rb +17 -0
  104. data/spec/assert_spec.rb +27 -0
  105. data/spec/declarative_cache_spec.rb +97 -0
  106. data/spec/kernel_spec.rb +16 -0
  107. data/spec/module_spec.rb +127 -0
  108. data/spec/open_constructor_spec.rb +39 -0
  109. data/spec/prepare_arguments_spec.rb +50 -0
  110. data/spec/spec.opts +3 -0
  111. data/spec/spec_require.rb +10 -0
  112. data/spec/synchronizer_spec.rb +69 -0
  113. metadata +166 -0
@@ -0,0 +1,2 @@
1
+ x��N�0ƽݞ�d^p!�-�I���;c�n;d5�Ŷ� ��v�}]�2�}���k!uYv�^|k�A�-��8���9��DF��o�|uw����&��NS���a�Kel*E15M��q�v���h%>�$q��U#H^�\UhK#
2
+ ���ۘ@��(�ޝF����mY�FQz��ѐ{P��;ghT^������fΗ���p
@@ -0,0 +1,3 @@
1
+ x]QmK�0�k�+�Mt�Va� *�����7�B��X Mf������-�hz�{��N����h����a�pVG�9/\^��O�枲_�9�V�2G�����Ж3�:�!L0�]Xw8c9� ���n�B�ĺ0C��;XZY��1i�� ��}|��듐��������eos� !��P�e��xI��I�eʕ6�o(>�4�t�i�� 8�%��_�к7l(TP^/"��=�N�J�j�] ak���z�
2
+ EW�9ڼ����K-������"Ew��%$uЫ�)�硐�$Tg hf��!J�Pt�����L9cP�jY,��,�S������;v�]�FLZ��5/��Z�N�0�=��[��W�:��𧋞
3
+ ��
@@ -0,0 +1,2 @@
1
+ x��A
2
+ �0@Q�9E���$q:E�(�d�BkK������=�e��G�(t蛙o�Fk� cH-s��EUSe�2�[u�g�![-�2IV�%��Sˡ�f�����~_6���G�{��4-E���@�(Fa��������yu.�<�
@@ -0,0 +1,3 @@
1
+ x�MN�0��&��E�n²j��h%$V���I���k���wg�$��
2
  R"g�}��\H]@�]g_aFv��(�+a`k!��Q�-B��o�Vy����@���#yL~e�JQL�^���J|�I�x��F"�7�~���B[Q $��*G�p� �.��[ 7e�E��FC�A �9C�
3
+
4
+ @?N�g>��(ʼn u)���Gw�^�P�S2o��nd�L�4O�`�Ӄ�W�mK�ι����jޮ�s�~Sz?mp2�
@@ -0,0 +1 @@
1
+ x}QMK�@���+��B�Ң�<X�y,e�m]�n�&K�w6&�h��0��{�m���������x����:�<72X�)�Nm�\<=?J�;nt~ �(B�l��/4M�5Z���K���*K�UDX�����P�b� �LE=�;�O��H���40�j�su�(s���z�V�b~L�2%J���W"�5g]�3����P�;^L�v:VB�]~�,K`���@f����e��܀NS��r��lEP��dB�J��ƽr�� ��(���=Ir�.g����-5��<$��,W��5�Ͷ�sF�8�F�J�F�F{�!��݈hO�1�W���_
@@ -0,0 +1,2 @@
1
+ x}�OK1Žn?��^ZXO���A��
2
+ ���&��hvS�l����N�V���余oi���./��ãU�����c�0�Km0���`�)8��u�^)��(8d�]�.?�m`����X��g��$���S>��Ϧ�~�ϣ)�h$�`���⍨ѯ�@YؿG�}'Nt ?�#Cv��%�[� ����VĆ��?w�a��:�^lT7�t; ��D�#�ޠ���
@@ -0,0 +1,2 @@
1
+ x��MK1��n~�P�PR؋X��(�x[J�fG6�&5�U����l�Tڃ�
2
+ ��z��Ie\�Wř��V{�<,Q������ �O+BL�`}��|}�QJ[�������j�h�r6�o9?���U�E��ΗC�X�� �0�2m�ik����D^H�0�a�P�0~��E��f,�k\kj�V��F"H��-a�g�p/C�Q�(�����w�.��0��<��{���I��� �<��8�[���>3���Y�ز#���Y�����H�^k��[Rѓ���8'��rK�5t��B�-!��X\�M��'�s���)�p@����`r�������}5 �o�}�`ў���h�3K
data/.git/packed-refs ADDED
@@ -0,0 +1,2 @@
1
+ # pack-refs with: peeled
2
+ 1196367828af7cc11276833728accd41428b60df refs/remotes/origin/master
@@ -0,0 +1 @@
1
+ 06864a068d188ab7ae17e39d58d6c25dc49a8ff3
@@ -0,0 +1 @@
1
+ ref: refs/remotes/origin/master
@@ -0,0 +1 @@
1
+ 06864a068d188ab7ae17e39d58d6c25dc49a8ff3
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *~
2
+ .DS_Store
3
+ .idea
4
+ .idea/**/*
5
+ Thumbs.db
data/README.rdoc ADDED
@@ -0,0 +1,3 @@
1
+ Set of common Ruby language extensions.
2
+
3
+ For docs go to spec.
data/Rakefile ADDED
@@ -0,0 +1,64 @@
1
+ require 'rake'
2
+ require 'spec/rake/spectask'
3
+
4
+ Dir.chdir File.dirname(__FILE__)
5
+
6
+ # Specs
7
+ task :default => :spec
8
+
9
+ Spec::Rake::SpecTask.new('spec') do |t|
10
+ t.spec_files = FileList["spec/**/*_spec.rb"]
11
+ t.libs = ["lib", "spec"]
12
+ end
13
+
14
+ # Gem
15
+ require 'rake/clean'
16
+ require 'rake/gempackagetask'
17
+ require 'fileutils'
18
+
19
+ spec = Gem::Specification.new do |s|
20
+ s.name = "ruby-ext"
21
+ s.version = "0.2.0"
22
+ s.summary = "Set of common Ruby language extensions"
23
+ s.description = "Set of common Ruby language extensions"
24
+ s.author = "Alexey Petrushin"
25
+ # s.email = ""
26
+ s.homepage = "http://www.bos-tec.com"
27
+ # s.rubyforge_project = "RubyExt"
28
+
29
+ s.platform = Gem::Platform::RUBY
30
+ s.has_rdoc = true
31
+ s.extra_rdoc_files = ["README.rdoc"]
32
+
33
+ s.files = (%w{Rakefile README.rdoc .gitignore} + Dir.glob("{lib,spec,.git}/**/*"))
34
+ # s.executables = ['restclient']
35
+ # s.add_dependency("BlueCloth", ">= 0.0.4")
36
+ # s.add_dependency "facets"
37
+
38
+ s.require_path = "lib"
39
+ end
40
+
41
+ PACKAGE_DIR = "#{File.expand_path File.dirname(__FILE__)}/build"
42
+
43
+ Rake::GemPackageTask.new(spec) do |p|
44
+ package_dir = PACKAGE_DIR
45
+ # FileUtils.mkdir package_dir unless File.exist? package_dir
46
+ p.need_tar = true if RUBY_PLATFORM !~ /mswin/
47
+ p.need_zip = true
48
+ p.package_dir = package_dir
49
+ end
50
+
51
+ # CLEAN.include [ 'pkg', '*.gem']
52
+
53
+ task :push do
54
+ dir = Dir.chdir PACKAGE_DIR do
55
+ gem_file = Dir.glob("ruby-ext*.gem").first
56
+ system "gem push #{gem_file}"
57
+ end
58
+ end
59
+
60
+ task :clean do
61
+ system "rm -r #{PACKAGE_DIR}"
62
+ end
63
+
64
+ task :release => [:gem, :push, :clean]
@@ -0,0 +1,167 @@
1
+ require 'monitor'
2
+
3
+ module DeclarativeCache
4
+ DISABLED = false
5
+
6
+ warn "CASHE DISABLED" if DISABLED
7
+
8
+ # It's not a good idea to mix Business Logic and Performance optimization,
9
+ # so i think these methods should be never used.
10
+ # def cached *methods
11
+ # DeclarativeCache.cached self, *methods
12
+ # end
13
+ #
14
+ # def cached_with_params *methods
15
+ # DeclarativeCache.cached_with_params self, *methods
16
+ # end
17
+
18
+ @versions, @alias_counter, @monitor = Hash.new{should! :be_never_called}, 0, Monitor.new
19
+ class << self
20
+
21
+ def alias_counter
22
+ @alias_counter += 1
23
+ return :"m#{@alias_counter}"
24
+ end
25
+
26
+ def cached *arg
27
+ vnames, klass, methods = parse_and_check_arguments *arg
28
+
29
+ return if DISABLED
30
+ methods.each do |m|
31
+ als = (m.to_s =~ /^[_a-zA-Z0-9]+$/) ? m : DeclarativeCache.alias_counter.to_sym
32
+
33
+ klass.class_eval{alias_method :"cached_#{als}", :"#{m}"}
34
+ unless vnames.is_a? Array
35
+ script = single_version_without_args.substitute binding
36
+ @versions[vnames] = 0 unless @versions.include? vnames
37
+ else
38
+ vnames_str = vnames.collect{|vname| "'#{vname}' => nil"}.join(', ')
39
+ script = multiple_version_without_args.substitute binding
40
+ vnames.each{|vname| @versions[vname] = 0 unless @versions.include? vname}
41
+ end
42
+ klass.class_eval script, __FILE__, __LINE__
43
+ end
44
+ end
45
+
46
+ def cached_with_params *arg
47
+ vnames, klass, methods = parse_and_check_arguments *arg
48
+
49
+ return if DISABLED
50
+ methods.each do |m|
51
+ als = (m.to_s =~ /^[_a-zA-Z0-9]+$/) ? m : DeclarativeCache.alias_counter
52
+
53
+ klass.class_eval{alias_method :"cached_#{als}", :"#{m}"}
54
+ unless vnames.is_a? Array
55
+ script = single_version_with_args.substitute binding
56
+ @versions[vnames] = 0 unless @versions.include? vnames
57
+ else
58
+ vnames_str = vnames.collect{|vname| "'#{vname}' => nil"}.join(', ')
59
+ script = multiple_version_with_args.substitute binding
60
+ vnames.each{|vname| @versions[vname] = 0 unless @versions.include? vname}
61
+ end
62
+ klass.class_eval script, __FILE__, __LINE__
63
+ end
64
+ end
65
+
66
+ def version name
67
+ @versions[name]
68
+ end
69
+
70
+ def update *names
71
+ names.each do |n|
72
+ n = n.to_s
73
+ @versions[n] = 0 unless @versions.include? n
74
+ @versions[n] += 1
75
+ end
76
+ end
77
+
78
+ attr_reader :monitor
79
+
80
+ protected
81
+ def parse_and_check_arguments *arg
82
+ arg.size.should! :>=, 3
83
+
84
+ version_names = arg[0]
85
+ if version_names.is_a? Array
86
+ version_names.size.should! :>, 0
87
+ version_names = version_names.collect{|n| n.to_s}
88
+ else
89
+ version_names = version_names.to_s
90
+ end
91
+
92
+ klass = arg[1]
93
+ klass.class.should! :be, [Class, Module]
94
+
95
+ methods = arg[2..arg.size]
96
+ defined = klass.instance_methods
97
+ methods.each do |m|
98
+ raise "Invalid method_name '#{m}'!" unless defined.include? m.to_s
99
+ end
100
+ return version_names, klass, methods
101
+ end
102
+
103
+ def multiple_version_with_args
104
+ <<-RUBY
105
+ def \#{m} *params
106
+ DeclarativeCache.monitor.synchronize do
107
+ @cache_versions_\#{als} ||= {\#{vnames_str}}
108
+ @cache_value_\#{als} ||= {}
109
+ if @cache_versions_\#{als}.all?{|vname, v| v == DeclarativeCache.version(vname)} and @cache_value_\#{als}.include?(params)
110
+ return @cache_value_\#{als}[params]
111
+ else
112
+ @cache_versions_\#{als}.keys.each{|vname| @cache_versions_\#{als}[vname] = DeclarativeCache.version(vname)}
113
+ return @cache_value_\#{als}[params] = cached_\#{als}(*params)
114
+ end
115
+ end
116
+ end
117
+ RUBY
118
+ end
119
+
120
+ def multiple_version_without_args
121
+ <<-RUBY
122
+ def \#{m}
123
+ DeclarativeCache.monitor.synchronize do
124
+ @cache_versions_\#{als} ||= {\#{vnames_str}}
125
+ if @cache_versions_\#{als}.all?{|vname, v| v == DeclarativeCache.version(vname)}
126
+ return @cache_value_\#{als}
127
+ else
128
+ @cache_versions_\#{als}.keys.each{|vname| @cache_versions_\#{als}[vname] = DeclarativeCache.version(vname)}
129
+ return @cache_value_\#{als} = cached_\#{als}
130
+ end
131
+ end
132
+ end
133
+ RUBY
134
+ end
135
+
136
+ def single_version_with_args
137
+ <<-RUBY
138
+ def \#{m} *params
139
+ DeclarativeCache.monitor.synchronize do
140
+ @cache_value_\#{als} ||= {}
141
+ if @cache_version_\#{als} == DeclarativeCache.version("\#{vnames}") and @cache_value_\#{als}.include?(params)
142
+ return @cache_value_\#{als}[params]
143
+ else
144
+ @cache_version_\#{als} = DeclarativeCache.version("\#{vnames}")
145
+ return @cache_value_\#{als}[params] = cached_\#{als}(*params)
146
+ end
147
+ end
148
+ end
149
+ RUBY
150
+ end
151
+
152
+ def single_version_without_args
153
+ <<-RUBY
154
+ def \#{m}
155
+ DeclarativeCache.monitor.synchronize do
156
+ if @cache_version_\#{als} == DeclarativeCache.version("\#{vnames}")
157
+ return @cache_value_\#{als}
158
+ else
159
+ @cache_version_\#{als} = DeclarativeCache.version("\#{vnames}")
160
+ return @cache_value_\#{als} = cached_\#{als}
161
+ end
162
+ end
163
+ end
164
+ RUBY
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,23 @@
1
+ class File
2
+ class << self
3
+ def write(path, data)
4
+ File.open(path, "wb") do |file|
5
+ return file.write(data)
6
+ end
7
+ end
8
+
9
+ def read(path)
10
+ File.open(path, "rb") do |file|
11
+ return file.read
12
+ end
13
+ end
14
+
15
+ def create_directory dir
16
+ Dir.mkdir dir unless File.exist? dir
17
+ end
18
+
19
+ def delete_directory dir
20
+ FileUtils.rm_r dir, :force => true if File.exist? dir
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ module Kernel
2
+ def respond_to sym, *args
3
+ return nil if not respond_to? sym
4
+ send sym, *args
5
+ end
6
+
7
+ # def _ &b
8
+ # raise "Block isn't provided!" unless b
9
+ # return b
10
+ # end
11
+
12
+ def singleton_class(&block)
13
+ if block_given?
14
+ (class << self; self; end).class_eval(&block)
15
+ self
16
+ else
17
+ (class << self; self; end)
18
+ end
19
+ end
20
+ alias_method :metaclass, :singleton_class
21
+ end
@@ -0,0 +1,84 @@
1
+ require 'set'
2
+
3
+ class Module
4
+ def is?(base)
5
+ ancestors.include?(base)
6
+ end
7
+
8
+ def wrap_method( sym, prefix = "old_", &blk )
9
+ old_method = "#{prefix}_#{sym}".to_sym
10
+ alias_method old_method, sym
11
+ define_method(sym) do |*args|
12
+ instance_exec(old_method, *args, &blk)
13
+ end
14
+ end
15
+
16
+ def inherited_instance_methods
17
+ im = Set.new
18
+ ancestors.each do |a|
19
+ next if a == self
20
+ im.merge a.instance_methods
21
+ end
22
+ return im.to_a
23
+ end
24
+
25
+ def namespace
26
+ if @module_namespace_defined
27
+ @module_namespace
28
+ else
29
+ @module_namespace_defined = true
30
+ @module_namespace = Module.namespace_for name
31
+ end
32
+ end
33
+
34
+ def each_namespace &block
35
+ current = namespace
36
+ while current do
37
+ block.call current
38
+ current = current.namespace
39
+ end
40
+ end
41
+
42
+ def each_ancestor include_standard = false, &block
43
+ if include_standard
44
+ ancestors.each{|a| block.call a unless a == self}
45
+ else
46
+ exclude = [self, Object, Kernel]
47
+ ancestors.each do |a|
48
+ block.call a unless exclude.include? a
49
+ end
50
+ end
51
+ end
52
+
53
+ def self_ancestors_and_namespaces &b
54
+ b.call self
55
+ each_ancestor &b
56
+ each_namespace &b
57
+ end
58
+
59
+ def self.namespace_for class_name
60
+ list = class_name.split("::")
61
+ if list.size > 1
62
+ list.pop
63
+ return eval list.join("::"), TOPLEVEL_BINDING, __FILE__, __LINE__
64
+ else
65
+ return nil
66
+ end
67
+ end
68
+
69
+ def inherit *modules
70
+ modules.each do |amodule|
71
+ include amodule
72
+
73
+ processed = []
74
+ amodule.ancestors.each do |a|
75
+ if a.const_defined? :ClassMethods
76
+ class_methods = a.const_get :ClassMethods
77
+ next if processed.include? class_methods
78
+ processed << class_methods
79
+ extend class_methods
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,2 @@
1
+ module NotDefined
2
+ end
@@ -0,0 +1,7 @@
1
+ class Object
2
+ def self; self end
3
+
4
+ # def copy
5
+ # Marshal.load(Marshal.dump self) # Stub
6
+ # end
7
+ end
@@ -0,0 +1,51 @@
1
+ module OpenConstructor
2
+ def set values, list = nil
3
+ unless list
4
+ if values.is_a? Hash
5
+ values.each do |k, v|
6
+ self.respond_to k.to_writer, v
7
+ end
8
+ else
9
+ values.instance_variables.each do |name|
10
+ accessor = name[1..name.size].to_writer
11
+ if self.respond_to? accessor
12
+ self.send accessor, values.instance_variable_get(name)
13
+ end
14
+ end
15
+ end
16
+ else
17
+ if values.is_a? Hash
18
+ values.each do |k, v|
19
+ self.respond_to k.to_writer, v if list.include? k
20
+ end
21
+ else
22
+ values.instance_variables.each do |name|
23
+ accessor = name[1..name.size]
24
+ if list.include?(accessor.to_sym)
25
+ accessor = accessor.to_writer
26
+ if self.respond_to?(accessor)
27
+ self.send accessor, values.instance_variable_get(name)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ return self
34
+ end
35
+
36
+ def set_with_check values
37
+ values.each do |k, v|
38
+ self.send k.to_writer, v
39
+ end
40
+ return self
41
+ end
42
+ alias_method :set!, :set_with_check
43
+
44
+ def to_hash
45
+ hash = {}
46
+ instance_variables.each do |name|
47
+ hash[name[1..name.size].to_sym] = instance_variable_get name
48
+ end
49
+ return hash
50
+ end
51
+ end
@@ -0,0 +1,105 @@
1
+ class ArgumentsParser
2
+ class << self
3
+ def register method, arguments
4
+ # check and prepare metadata
5
+ arguments.collect!{|meta| meta.is_a?(Hash) ? meta : {:type => meta}}
6
+ arguments.each{|meta| meta.should! :include, :type}
7
+
8
+ # register
9
+ @registry ||= {}
10
+ @registry[method] = arguments
11
+ end
12
+
13
+ def parse_arguments_for method, *args, &block
14
+ metadata = @registry[method]
15
+ index = 0
16
+ parsed_args = metadata.collect do |options|
17
+ send options[:type], args, block, options, index, (index == metadata.size - 1)
18
+ end
19
+ args.should_be! :empty
20
+ return parsed_args
21
+ end
22
+
23
+ protected
24
+ def string args, block, options, index, last
25
+ object(args, block, options, index, last) || ""
26
+ end
27
+
28
+ def object args, block, options, index, last
29
+ a = if range = options[:range]
30
+ if range == :except_last_hash
31
+ if args.size == 1 and args.last.is_a? Hash
32
+ nil
33
+ else
34
+ args.shift
35
+ end
36
+ else
37
+ should_be! :never_called
38
+ end
39
+ else
40
+ args.shift
41
+ end
42
+
43
+ a = _common_options a, options
44
+ a
45
+ end
46
+
47
+ def array args, block, options, index, last
48
+ a = if last
49
+ args
50
+ elsif range = options[:range]
51
+ if range == :except_last_hash
52
+ if args.last.is_a? Hash
53
+ tmp = args[0..-2]
54
+ args[0..-2] = nil
55
+ tmp
56
+ else
57
+ tmp = args[0..-1]
58
+ args.clear
59
+ tmp
60
+ end
61
+ else
62
+ should_be! :never_called
63
+ end
64
+ else
65
+ args.shift
66
+ end
67
+
68
+ a = _common_options a, options
69
+ a ||= []
70
+ a = [a] unless a.is_a?(Array)
71
+ a
72
+ end
73
+
74
+ def hash args, block, options, index, last
75
+ a = object(args, block, options, index, last) || {}
76
+ a.should! :be_a, Hash
77
+ a
78
+ end
79
+
80
+ def _common_options a, options
81
+ a.should_not! :be_nil if options[:require]
82
+ if (default = options[:default]) and a.eql?(nil)
83
+ a = default
84
+ end
85
+ a
86
+ end
87
+ end
88
+ end
89
+
90
+ class Object
91
+ def self.prepare_arguments_for method, *args
92
+ # Register parsers
93
+ ArgumentsParser.register method, args
94
+
95
+ # Wrap method
96
+ old_method = :"#{method}_wparg"
97
+ alias_method old_method, method
98
+ code = <<END
99
+ def #{method} *args, &block
100
+ #{old_method} *ArgumentsParser.parse_arguments_for(:#{method}, *args), &block
101
+ end
102
+ END
103
+ class_eval code, __FILE__, __LINE__
104
+ end
105
+ end