when_exe 0.3.2 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. data/LICENSE.ja.txt +25 -25
  2. data/LICENSE.txt +31 -31
  3. data/bin/locales.rb +2 -1
  4. data/bin/when.rb.config +1 -1
  5. data/lib/when_exe.rb +70 -48
  6. data/lib/when_exe/basictypes.rb +99 -65
  7. data/lib/when_exe/calendartypes.rb +40 -178
  8. data/lib/when_exe/coordinates.rb +156 -62
  9. data/lib/when_exe/core/compatibility.rb +10 -0
  10. data/lib/when_exe/core/extension.rb +40 -0
  11. data/lib/when_exe/ephemeris.rb +112 -50
  12. data/lib/when_exe/icalendar.rb +125 -91
  13. data/lib/when_exe/inspect.rb +100 -48
  14. data/lib/when_exe/locales/ar.rb +48 -48
  15. data/lib/when_exe/locales/bg.rb +1 -1
  16. data/lib/when_exe/locales/bs.rb +4 -2
  17. data/lib/when_exe/locales/ca.rb +1 -1
  18. data/lib/when_exe/locales/en_CA.rb +3 -4
  19. data/lib/when_exe/locales/en_IE.rb +88 -0
  20. data/lib/when_exe/locales/en_US.rb +87 -0
  21. data/lib/when_exe/locales/es_CR.rb +84 -0
  22. data/lib/when_exe/locales/es_EC.rb +85 -0
  23. data/lib/when_exe/locales/es_PA.rb +85 -0
  24. data/lib/when_exe/locales/fr.rb +39 -39
  25. data/lib/when_exe/locales/hu.rb +15 -14
  26. data/lib/when_exe/locales/it.rb +1 -1
  27. data/lib/when_exe/locales/ja.rb +2 -2
  28. data/lib/when_exe/locales/locales.rb +7 -0
  29. data/lib/when_exe/locales/lt.rb +21 -19
  30. data/lib/when_exe/locales/ms.rb +84 -0
  31. data/lib/when_exe/locales/nl.rb +2 -2
  32. data/lib/when_exe/locales/ru.rb +1 -1
  33. data/lib/when_exe/locales/uk.rb +1 -1
  34. data/lib/when_exe/locales/ur.rb +84 -0
  35. data/lib/when_exe/mini_application.rb +44 -43
  36. data/lib/when_exe/parts/enumerator.rb +3 -3
  37. data/lib/when_exe/parts/geometric_complex.rb +6 -1
  38. data/lib/when_exe/parts/locale.rb +49 -18
  39. data/lib/when_exe/parts/method_cash.rb +61 -0
  40. data/lib/when_exe/parts/resource.rb +221 -106
  41. data/lib/when_exe/parts/timezone.rb +70 -33
  42. data/lib/when_exe/region/bahai.rb +2 -2
  43. data/lib/when_exe/region/balinese.rb +40 -43
  44. data/lib/when_exe/region/chinese.rb +93 -33
  45. data/lib/when_exe/region/chinese_calendar.rb +117 -1
  46. data/lib/when_exe/region/chinese_epoch.rb +65 -10
  47. data/lib/when_exe/region/christian.rb +97 -2
  48. data/lib/when_exe/region/ephemeric_notes.rb +353 -0
  49. data/lib/when_exe/region/french.rb +1 -1
  50. data/lib/when_exe/region/geologicalage.rb +171 -171
  51. data/lib/when_exe/region/indian.rb +18 -14
  52. data/lib/when_exe/region/iranian.rb +1 -1
  53. data/lib/when_exe/region/japanese.rb +49 -12
  54. data/lib/when_exe/region/japanese_notes.rb +838 -507
  55. data/lib/when_exe/region/japanese_residues.rb +724 -662
  56. data/lib/when_exe/region/javanese.rb +7 -7
  57. data/lib/when_exe/region/mayan.rb +19 -17
  58. data/lib/when_exe/region/nihon_shoki.rb +3 -3
  59. data/lib/when_exe/region/residue.rb +29 -28
  60. data/lib/when_exe/region/shire.rb +2 -2
  61. data/lib/when_exe/region/tibetan.rb +87 -5
  62. data/lib/when_exe/region/world.rb +1 -1
  63. data/lib/when_exe/timestandard.rb +85 -7
  64. data/lib/when_exe/tmobjects.rb +32 -4
  65. data/lib/when_exe/tmposition.rb +104 -55
  66. data/lib/when_exe/tmreference.rb +157 -60
  67. data/lib/when_exe/version.rb +2 -2
  68. data/test/examples/JapanHolidays.ics +3 -3
  69. data/test/examples/JapanHolidaysRFC6350.ics +499 -0
  70. data/test/examples/Residue.m17n +3 -2
  71. data/test/examples/Spatial.m17n +3 -3
  72. data/test/examples/USA-DST.ics +27 -27
  73. data/test/examples/today.rb +1 -1
  74. data/test/test.rb +4 -2
  75. data/test/test/basictypes.rb +40 -15
  76. data/test/test/coordinates.rb +9 -4
  77. data/test/test/icalendar.rb +24 -14
  78. data/test/test/inspect.rb +5 -3
  79. data/test/test/parts.rb +11 -2
  80. data/test/test/region/chinese.rb +4 -4
  81. data/test/test/region/civil.rb +124 -0
  82. data/test/test/region/geologicalage.rb +5 -2
  83. data/test/test/region/indian.rb +2 -0
  84. data/test/test/region/japanese.rb +156 -1
  85. data/test/test/region/jewish.rb +3 -3
  86. data/test/test/region/m17n.rb +9 -9
  87. data/test/test/region/mayan.rb +122 -5
  88. data/test/test/region/residue.rb +1 -1
  89. data/test/test/tmobjects.rb +27 -64
  90. data/test/test/tmposition.rb +48 -1
  91. data/test/test/tmreference.rb +66 -4
  92. data/when_exe.gemspec +1 -1
  93. metadata +15 -6
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  =begin
3
- Copyright (C) 2011-2013 Takashi SUGA
3
+ Copyright (C) 2011-2014 Takashi SUGA
4
4
 
5
5
  You may use and/or modify this file according to the license described in the LICENSE.txt file included in this archive.
6
6
  =end
@@ -19,16 +19,33 @@ module When::Parts
19
19
  LabelProperty = nil
20
20
 
21
21
  # @private
22
- class Element
23
- attr_reader :predicate
24
- attr_reader :object
25
- attr_reader :attribute
22
+ class ContentLine
23
+
24
+ RFC6350 = {
25
+ "\\\\" => "\\",
26
+ "\\n" => "\n",
27
+ "\\N" => "\n",
28
+ "\\;" => ";",
29
+ "\\:" => ":"
30
+ }
31
+
32
+ RFC6868 = {
33
+ "^n" => "\n",
34
+ "^^" => "^",
35
+ "^'" => '"'
36
+ }
37
+
38
+ attr_reader :predicate
39
+ attr_accessor :object
40
+ attr_reader :attribute
26
41
  attr_accessor :namespace
27
- attr_reader :marked
42
+ attr_accessor :same_altid
43
+ attr_reader :marked
28
44
 
29
45
  def initialize(key, object=nil, marked=nil)
30
46
  key = key.downcase.gsub(/-/,'_') if (key==key.upcase)
31
47
  @predicate, @namespace = key.split(/:/).reverse
48
+ object = object.gsub(/\^./) {|escape| RFC6868[escape] || escape} if object.instance_of?(String)
32
49
  @object = object
33
50
  @marked = marked
34
51
  @attribute = {}
@@ -80,21 +97,16 @@ module When::Parts
80
97
  #
81
98
  def [](label)
82
99
 
83
- # nil label
100
+ # nil label の場合
84
101
  return _pool[label] unless label
85
102
 
86
- # 階層構造の確認
87
- unless label =~ /\?/
88
- terms = label.split(/::/)
89
- terms.shift if terms[0] == ''
90
- return terms.inject(self) {|obj,term| obj = obj[term]} if terms.length >= 2
91
- end
103
+ # 階層がある場合
104
+ terms = Resource._encode(label).split(/::/)
105
+ terms.shift if terms[0] == ''
106
+ return terms.inject(self) {|obj,term| obj = obj[Resource._decode(term)]} if terms.length >= 2
92
107
 
93
108
  # 階層がない場合
94
- path, options = label.split(/\?/, 2)
95
- label = Resource._extract_prefix(path)
96
- label += '?' + options if options
97
- _pool[label.gsub(/%3A%3A/, '::')]
109
+ _pool[Resource._decode(Resource._extract_prefix(terms[0]))]
98
110
  end
99
111
 
100
112
  # オブジェクト登録
@@ -192,13 +204,17 @@ module When::Parts
192
204
  return iri unless iri.instance_of?(String)
193
205
 
194
206
  # 階層がある場合は、階層をたどる
207
+ iri = Resource._decode(iri)
208
+ iri = $1 while iri =~ /^\((.*)\)$/
195
209
  iri = namespace + iri if namespace && iri !~ /^[_a-z\d]+:[^:]/i
196
- root, *leaves= iri.split(/::/)
197
- return leaves.inject(_instance(root)) {|obj,leaf| obj[leaf]} unless leaves==[] || iri =~ /\?/
210
+ root, *leaves= Resource._encode(iri).split(/::/)
211
+ if leaves.size > 0
212
+ return leaves.inject(_instance(Resource._decode(root))) {|obj,leaf| obj[Resource._decode(leaf)]}
213
+ end
198
214
 
199
215
  # 登録ずみなら、参照
200
- path, query = _extract_prefix(iri).split(/\?/, 2)
201
- iri = query ? (path + '?' + query) : path
216
+ iri = _extract_prefix(iri)
217
+ path, query = iri.split(/\?/, 2)
202
218
  if When.multi_thread
203
219
  my_mutex = nil
204
220
  @_lock_.synchronize do
@@ -236,21 +252,26 @@ module When::Parts
236
252
  def _parse(line, type=nil)
237
253
  return line unless line.kind_of?(String)
238
254
  line.sub!(/\s#.*$/, '')
239
- return Locale._split($1) if type && line =~ /^#{type}:(.+)$/i
240
- return Locale._split(line) unless line =~ /^(\*)?([A-Z][-A-Z_]{0,255})(?:;(.*?))?:(.*)$/i
241
-
242
- marked, key, property, value = $~[1..4]
243
- element = Element.new(key, value, marked)
244
- if (property)
245
- element.attribute['.'] = property+':'+value
246
- property.split(/;/) do |pr|
247
- prop = Element.new(*pr.split(/=/, 2))
248
- element.attribute[prop.predicate] = prop
255
+ return Locale._split($1) if type && /^#{type}:(.+)$/i =~ line
256
+ tokens = line.scan(/((?:[^\\:]|\\.)+)(?::(?!\z))?|:/).flatten
257
+ return Locale._split(line) unless tokens.size > 1 && /^(\*)?([A-Z][-A-Z_]{0,255})(?:;(.+))?$/i =~ tokens[0]
258
+ marked, key, property = $~[1..3]
259
+ values = tokens[1..-1]
260
+ value = values.join(':') unless values == [nil]
261
+ content = ContentLine.new(key, value, marked)
262
+ value ||= ''
263
+ if property
264
+ content.attribute['.'] = property + ':' + value
265
+ property.scan(/((?:[^\\;]|\\.)+)(?:;(?!\z))?|;/).flatten.each do |pr|
266
+ pr ||= ''
267
+ pr.gsub!(/\\./) {|escape| ContentLine::RFC6350[escape] || escape}
268
+ prop = ContentLine.new(*pr.split(/=/, 2))
269
+ content.attribute[prop.predicate] = prop
249
270
  end
250
271
  else
251
- element.attribute['.'] = value
272
+ content.attribute['.'] = value
252
273
  end
253
- return element
274
+ return content
254
275
  end
255
276
 
256
277
  # @private
@@ -270,16 +291,72 @@ module When::Parts
270
291
  return path
271
292
  end
272
293
 
294
+ # @private
295
+ def _replace_tags(source, tags)
296
+ case source
297
+ when String
298
+ target = source.dup
299
+ tags.each_pair do |key, value|
300
+ target.gsub!(/#\{(\?[^=#}]+?=)?#{key}(:.*?)?\}/, '\1' + value) if value.kind_of?(String)
301
+ end
302
+ target.gsub(/#\{.+?(:(.*?))?\}/, '\2')
303
+ when Array
304
+ source.map {|target| _replace_tags(target, tags)}
305
+ when Hash
306
+ target = {}
307
+ source.each_pair do |key, value|
308
+ target[key] = tags[key].kind_of?(Numeric) ? tags[key] : _replace_tags(value, tags)
309
+ end
310
+ target
311
+ else
312
+ source
313
+ end
314
+ end
315
+
316
+ # @private
317
+ def _encode(iri)
318
+ return iri unless iri =~ /\(/
319
+
320
+ iri = iri.dup
321
+ begin
322
+ unless iri.gsub!(/\([^()]*\)/) {|token|
323
+ token.gsub(/[():?&%]/) {|char|'%' + char.ord.to_s(16)}
324
+ }
325
+ raise ArgumentError, 'Brackets do not correspond: ' + iri
326
+ end
327
+ end while iri =~ /\(/
328
+ iri
329
+ end
330
+
331
+ # @private
332
+ def _decode(iri)
333
+ return iri unless iri =~ /%28/
334
+
335
+ iri = iri.dup
336
+ begin
337
+ unless iri.gsub!(/%28.*?%29/) {|token|
338
+ token.gsub(/%([\dA-F]{2})/i) {$1.to_i(16).chr}
339
+ }
340
+ raise ArgumentError, 'Brackets do not correspond: ' + iri
341
+ end
342
+ end while iri =~ /%28/
343
+ iri = $1 if iri =~ /^\((.*)\)$/
344
+ iri
345
+ end
346
+
273
347
  private
274
348
 
275
349
  def _create_object(iri, path, query)
276
350
  options = {}
277
351
  replace = {}
278
352
  if query
279
- options = Hash[*query.split(/&/).map{ |pair| pair.split(/=/, 2) }.flatten]
353
+ options = Hash[*Resource._encode(query).split(/&/).map{|pair|
354
+ key, value = pair.split(/=/, 2)
355
+ [key, Resource._decode(value)]
356
+ }.flatten]
280
357
  keys = options.keys
281
358
  keys.each do |key|
282
- replace[$1] = options.delete(key) if key =~ /^!(.+)/
359
+ replace[$1] = options.delete(key) if key =~ /^([A-Z].*)/
283
360
  end
284
361
  end
285
362
  options['..'] = iri
@@ -292,6 +369,14 @@ module When::Parts
292
369
  when Class
293
370
  obj = list[0].new(options)
294
371
  when Array
372
+ top = list[0][0]
373
+ if top.kind_of?(Hash)
374
+ top.each_pair do |key, value|
375
+ replace.update(value[replace.delete(key)]) if value.kind_of?(Hash) && value.key?(replace[key])
376
+ end
377
+ list[0] = list[0][1..-1]
378
+ list[0] = _replace_tags(list[0], top.merge(replace))
379
+ end
295
380
  if list[0][0].kind_of?(Class)
296
381
  # 配列の先頭がクラスである場合
297
382
  klass, *list = list[0]
@@ -317,11 +402,10 @@ module When::Parts
317
402
  parsed = nil
318
403
  OpenURI
319
404
  begin
320
- open(path, "1".respond_to?(:force_encoding) ? 'r:utf-8' : 'r') do |file|
321
- resource = file.read
322
- replace.keys.each do |key|
323
- resource.gsub!(/#\{#{key}\}/, replace[key])
324
- end
405
+ args = [path, "1".respond_to?(:force_encoding) ? 'r:utf-8' : 'r']
406
+ args << {:ssl_verify_mode=>OpenSSL::SSL::VERIFY_NONE} if path =~ /^https:/
407
+ open(*args) do |file|
408
+ resource = _replace_tags(file.read, replace)
325
409
  parsed = (resource[0..5]=='BEGIN:') ? _ics(resource.split(/[\n\r]+/)) :
326
410
  _xml(REXML::Document.new(resource).root)
327
411
  end
@@ -339,9 +423,9 @@ module When::Parts
339
423
  end
340
424
 
341
425
  def _class(path)
342
- return nil unless (path =~ /^http:\/\/hosi\.org\/When\/(.*)/)
343
- list = [When]
344
- $1.split(/\//).each do |mod|
426
+ return nil unless path.index(Resource.base_uri) == 0
427
+ list = [When]
428
+ path[Resource.base_uri.length..-1].split(/\//).each do |mod|
345
429
  if list[0].const_defined?(mod)
346
430
  list.unshift(list[0].const_get(mod))
347
431
  else
@@ -362,19 +446,19 @@ module When::Parts
362
446
  key = '' if expanded_name == 'xmlns'
363
447
  namespace[key] = value.to_s
364
448
  end
365
- obj << Element.new('xmlns:namespace', namespace) if (namespace.size>0)
449
+ obj << ContentLine.new('xmlns:namespace', namespace) if (namespace.size>0)
366
450
  xml.each do |e|
367
451
  next unless defined? e.name
368
452
  if (e.attributes['type'])
369
453
  obj << _xml(e, namespace)
370
454
  else
371
- element = Element.new(e.expanded_name, e.attributes['ref']||e.text)
455
+ content = ContentLine.new(e.expanded_name, e.attributes['ref']||e.text)
372
456
  e.attributes.each_pair do |key,value|
373
- attr = Element.new(value.name, value)
457
+ attr = ContentLine.new(value.name, value)
374
458
  attr.namespace = value.prefix
375
- element.attribute[key] = attr
459
+ content.attribute[key] = attr
376
460
  end
377
- obj << element
461
+ obj << content
378
462
  end
379
463
  end
380
464
  return obj
@@ -461,7 +545,6 @@ module When::Parts
461
545
  return @iri if @iri
462
546
  root = @_pool['..']
463
547
  path = root.instance_of?(String) ? root : label.to_s
464
- path = path.gsub(/::/, '%3A%3A')
465
548
  if root.respond_to?(:iri)
466
549
  prefix = root.iri
467
550
  path = prefix + '::' + path if prefix
@@ -482,15 +565,15 @@ module When::Parts
482
565
  return child[iri * 1]
483
566
  when String
484
567
  obj = self
485
- iri.split(/::/).each do |label|
568
+ Resource._encode(iri).split(/::/).each do |label|
486
569
  return obj.child if label == '*'
487
570
  if obj == Resource
488
- obj = Resource._instance(label)
571
+ obj = Resource._instance(Resource._decode(label))
489
572
  else
490
573
  case label
491
574
  when '' ; obj = Resource
492
575
  when '.' # obj = obj
493
- else ; obj = obj._pool[label.gsub(/%3A%3A/, '::')]
576
+ else ; obj = obj._pool[Resource._decode(label)]
494
577
  end
495
578
  end
496
579
  raise ArgumentError, "IRI not found: #{iri}" unless obj
@@ -703,13 +786,7 @@ module When::Parts
703
786
  def _set_variables(options)
704
787
  @options = options[:options] || {} if options.key?(:options)
705
788
  options.each_pair do |key,value|
706
- unless (key =~ /^options$|^[_.]/)
707
- # スキームの":"がエンコーディングされていたら、valueをデコード
708
- if (value =~ /^\w+%3A/i)
709
- value.gsub!(/%[0-9A-F]{2}/i) do |c|
710
- c.sub(/%/,'0x').hex.chr
711
- end
712
- end
789
+ unless (key =~ /^options$|^\.|^[A-Z]/)
713
790
  case "#{key}"
714
791
  when 'namespace' ; value = Locale._namespace(value)
715
792
  when 'locale' ; value = Locale._locale(value)
@@ -721,67 +798,97 @@ module When::Parts
721
798
 
722
799
  # 配下のオブジェクトの生成
723
800
  def _child(options)
724
- @child = []
725
- query = options.dup
726
- options['..'] = self
727
- leaf = options['.']
801
+ @child = []
802
+ query = options.dup
803
+ options['..'] = self
804
+ leaves = options.delete('.').map {|leaf| Resource._parse(leaf)}
805
+ key_list = []
806
+ properties = {}
728
807
  label_candidates = nil
729
808
 
730
- leaf.each_index do |i|
731
- element = Resource._parse(leaf[i])
732
- case element
733
- when Array
734
- if element[0].kind_of?(Class)
735
- list = []
736
- element.each do |e|
737
- if e.kind_of?(Hash)
738
- list += e.keys.map {|key| Resource::Element.new(key, e[key])}
739
- else
740
- list << e
741
- end
742
- end
743
- options['.'] = list
744
- @child << element[0].new(options.dup)
809
+ # ContentLine の処理(namespace, locale, altidの前処理)
810
+ leaves.each do |content|
811
+ next unless content.kind_of?(ContentLine)
812
+ key = content.predicate
813
+ value = content.object
814
+ next options.delete(key) unless value
815
+ case key
816
+ when 'namespace'
817
+ options[key] ||= {}
818
+ if content.attribute['altid']
819
+ options[key][content.attribute['prefix'].object] = content.object
745
820
  else
746
- options.delete('.')
747
- @child << self.class.new(*(element + [options]))
821
+ options[key] = options[key].update(Locale._namespace(value))
748
822
  end
823
+ when 'locale'
824
+ options[key] = Locale._locale(value)
825
+ else
826
+ _parse_altid(properties, content)
827
+ key_list << key unless key_list.include?(key)
828
+ end
829
+ end
749
830
 
750
- when Resource::Element
751
- key = element.predicate
752
- value = element.object
753
- if (value)
754
- case key
755
- when 'namespace'
756
- options[key] ||= {}
757
- options[key] = options[key].merge(Locale._namespace(value))
758
- when 'locale'
759
- options[key] = Locale._locale(value)
831
+ # ContentLine の処理(一般)
832
+ key_list.each do |key|
833
+ content = properties[key][0]
834
+ value = content.same_altid ? When::BasicTypes::M17n.new(content, options['namespace'], []) : content.object
835
+ value = When::BasicTypes::M17n.new(value, nil, nil, options) if value.instance_of?(String) && value =~ /^\s*\[/
836
+ @_pool[value.to_s] = value if value.kind_of?(When::BasicTypes::M17n)
837
+ if content.marked || key == self.class::LabelProperty
838
+ @label = value
839
+ else
840
+ options[key] = value
841
+ label_candidates ||= value
842
+ end
843
+ end
844
+
845
+ # Array の処理(子オブジェクトの生成)
846
+ leaves.each do |content|
847
+ next unless content.kind_of?(Array)
848
+ if content[0].kind_of?(Class)
849
+ list = []
850
+ content.each do |e|
851
+ if e.kind_of?(Hash)
852
+ list += e.keys.map {|key| Resource::ContentLine.new(key, e[key])}
760
853
  else
761
- if (value.instance_of?(String) && value =~ /^\[/)
762
- options.delete('.')
763
- value = m17n(value, nil, nil, options.dup)
764
- @_pool[value.to_s] = value
765
- end
766
- if element.marked || key == self.class::LabelProperty
767
- @label = value
768
- else
769
- options[key] = value
770
- label_candidates ||= value
771
- end
854
+ list << e
772
855
  end
773
- else
774
- options.delete(key)
775
856
  end
857
+ options['.'] = list
858
+ @child << content[0].new(options.dup)
859
+ else
860
+ options.delete('.')
861
+ @child << self.class.new(*(content + [options]))
776
862
  end
777
863
  end
864
+
865
+ # 代表ラベルの設定
778
866
  options.update(query)
779
867
  unless @label
780
- raise ArgumentError, "label attribute not found: #{leaf}" unless label_candidates
868
+ raise ArgumentError, "label attribute not found: #{options['.']}" unless label_candidates
781
869
  @label = label_candidates
782
870
  end
783
871
  end
784
872
 
873
+ # ALTIDを持つ ContentLine の解析
874
+ def _parse_altid(properties, content)
875
+ key = content.predicate
876
+ properties[key] ||= []
877
+ if content.attribute['altid']
878
+ found = false
879
+ (0...properties[key].length).to_a.each do |i|
880
+ prev = properties[key][i]
881
+ if prev.attribute['altid'] && prev.attribute['altid'].object == content.attribute['altid'].object
882
+ content.same_altid = prev
883
+ properties[key][i] = content
884
+ found = true
885
+ break
886
+ end
887
+ end
888
+ end
889
+ properties[key] << content unless found
890
+ end
891
+
785
892
  # 配下のオブジェクトの前後関係の設定
786
893
  def _sequence
787
894
  return unless @child
@@ -800,12 +907,20 @@ module When::Parts
800
907
  end
801
908
  end
802
909
 
910
+ alias :__method_missing :method_missing
911
+
803
912
  # その他のメソッド
804
- # When::Parts::GeometricComplex で定義されていないメソッドは
913
+ # When::Parts::Resource で定義されていないメソッドは
805
914
  # 処理を @child (type: Array) に委譲する
806
915
  #
807
916
  def method_missing(name, *args, &block)
808
- @child.send(name.to_sym, *args, &block)
917
+ return __method_missing(name, *args, &block) if When::Parts::MethodCash::Escape.key?(name)
918
+ self.class.module_eval %Q{
919
+ def #{name}(*args, &block)
920
+ @child.send("#{name}", *args, &block)
921
+ end
922
+ } unless When::Parts::MethodCash.escape(name)
923
+ @child.send(name, *args, &block)
809
924
  end
810
925
 
811
926
  #