ramaze 2012.04.14 → 2012.12.08b

Sign up to get free protection for your applications and to get access to all the features.
Files changed (146) hide show
  1. data/.gems +28 -35
  2. data/.gitignore +4 -0
  3. data/.travis.yml +3 -3
  4. data/Gemfile +3 -0
  5. data/README.md +1 -5
  6. data/Rakefile +9 -20
  7. data/examples/app/blog/app.rb +5 -14
  8. data/examples/app/todolist/start.rb +1 -5
  9. data/guide/AUTHORS +8 -3
  10. data/guide/CHANGELOG +587 -0
  11. data/guide/general/cache.md +1 -0
  12. data/guide/general/configuration.md +2 -1
  13. data/guide/general/contributing.md +1 -0
  14. data/guide/general/controllers.md +105 -10
  15. data/guide/general/helpers.md +6 -7
  16. data/guide/general/installation.md +2 -1
  17. data/guide/general/logging.md +1 -4
  18. data/guide/general/middlewares.md +15 -23
  19. data/guide/general/models.md +1 -0
  20. data/guide/general/principles.md +1 -0
  21. data/guide/general/ramaze_command.md +9 -54
  22. data/guide/general/routes.md +1 -0
  23. data/guide/general/sessions.md +3 -2
  24. data/guide/general/special_thanks.md +1 -0
  25. data/guide/general/testing.md +1 -0
  26. data/guide/general/views.md +35 -22
  27. data/lib/proto/Gemfile +4 -0
  28. data/lib/proto/README.md +35 -0
  29. data/lib/proto/Rakefile +1 -0
  30. data/lib/proto/app.rb +2 -6
  31. data/lib/proto/spec/helper.rb +39 -0
  32. data/lib/proto/task/ramaze.rake +57 -0
  33. data/lib/ramaze.rb +12 -39
  34. data/lib/ramaze/bin/create.rb +1 -3
  35. data/lib/ramaze/bin/runner.rb +0 -14
  36. data/lib/ramaze/cache.rb +21 -0
  37. data/lib/ramaze/cache/memcache.rb +1 -3
  38. data/lib/ramaze/cache/redis.rb +2 -4
  39. data/lib/ramaze/cache/sequel.rb +4 -5
  40. data/lib/ramaze/controller.rb +10 -3
  41. data/lib/ramaze/default_middleware.rb +24 -0
  42. data/lib/ramaze/files.rb +5 -5
  43. data/lib/ramaze/gestalt.rb +10 -10
  44. data/lib/ramaze/helper/blue_form.rb +33 -6
  45. data/lib/ramaze/helper/csrf.rb +22 -30
  46. data/lib/ramaze/helper/flash.rb +1 -1
  47. data/lib/ramaze/helper/upload.rb +5 -3
  48. data/lib/ramaze/helper/user.rb +1 -0
  49. data/lib/ramaze/log.rb +0 -5
  50. data/lib/ramaze/log/informer.rb +3 -3
  51. data/lib/ramaze/log/logging.rb +4 -4
  52. data/lib/ramaze/log/syslog.rb +2 -2
  53. data/lib/ramaze/response.rb +1 -1
  54. data/lib/ramaze/snippets.rb +0 -20
  55. data/lib/ramaze/spec/bacon.rb +5 -13
  56. data/lib/ramaze/version.rb +1 -1
  57. data/lib/ramaze/view/erector.rb +1 -3
  58. data/lib/ramaze/view/erubis.rb +1 -3
  59. data/lib/ramaze/view/ezamar.rb +1 -3
  60. data/lib/ramaze/view/haml.rb +1 -4
  61. data/lib/ramaze/view/liquid.rb +1 -3
  62. data/lib/ramaze/view/lokar.rb +1 -3
  63. data/lib/ramaze/view/mustache.rb +1 -3
  64. data/lib/ramaze/view/nagoro.rb +1 -4
  65. data/lib/ramaze/view/remarkably.rb +1 -4
  66. data/lib/ramaze/view/sass.rb +2 -5
  67. data/lib/ramaze/view/slim.rb +1 -3
  68. data/lib/ramaze/view/slippers.rb +1 -3
  69. data/lib/ramaze/view/tagz.rb +1 -3
  70. data/lib/ramaze/view/tenjin.rb +1 -3
  71. data/ramaze.gemspec +45 -16
  72. data/spec/helper.rb +0 -1
  73. data/spec/ramaze/cache/localmemcache.rb +0 -4
  74. data/spec/ramaze/controller/mapping.rb +17 -0
  75. data/spec/ramaze/dispatcher/directory.rb +6 -5
  76. data/spec/ramaze/dispatcher/file.rb +7 -4
  77. data/spec/ramaze/files.rb +0 -2
  78. data/spec/ramaze/helper/csrf.rb +0 -26
  79. data/spec/ramaze/helper/upload.rb +1 -0
  80. data/spec/ramaze/helper/user.rb +12 -0
  81. data/spec/ramaze/log/syslog.rb +5 -1
  82. data/spec/ramaze/view/lokar.rb +1 -1
  83. data/spec/ramaze/view/nagoro.rb +1 -1
  84. data/tasks/bacon.rake +1 -1
  85. data/tasks/gems.rake +15 -0
  86. data/tasks/release.rake +37 -8
  87. metadata +106 -139
  88. data/guide/_static/ramaze_console.png +0 -0
  89. data/guide/tutorials/introduction.md +0 -263
  90. data/lib/proto/model/init.rb +0 -6
  91. data/lib/proto/public/.htaccess +0 -24
  92. data/lib/proto/public/dispatch.fcgi +0 -11
  93. data/lib/proto/spec/main.rb +0 -20
  94. data/lib/proto/start.rb +0 -20
  95. data/lib/ramaze/app_graph.rb +0 -105
  96. data/lib/ramaze/bin/console.rb +0 -87
  97. data/lib/ramaze/bin/helper.rb +0 -107
  98. data/lib/ramaze/bin/restart.rb +0 -95
  99. data/lib/ramaze/bin/start.rb +0 -221
  100. data/lib/ramaze/bin/status.rb +0 -152
  101. data/lib/ramaze/bin/stop.rb +0 -112
  102. data/lib/ramaze/dependencies.rb +0 -84
  103. data/lib/ramaze/helper/disqus.rb +0 -27
  104. data/lib/ramaze/helper/ultraviolet.rb +0 -49
  105. data/lib/ramaze/log/analogger.rb +0 -50
  106. data/lib/ramaze/log/growl.rb +0 -55
  107. data/lib/ramaze/log/knotify.rb +0 -31
  108. data/lib/ramaze/log/xosd.rb +0 -94
  109. data/lib/ramaze/middleware_compiler.rb +0 -36
  110. data/lib/ramaze/plugin.rb +0 -69
  111. data/lib/ramaze/setup.rb +0 -210
  112. data/lib/ramaze/snippets/array/put_within.rb +0 -38
  113. data/lib/ramaze/snippets/binding/locals.rb +0 -20
  114. data/lib/ramaze/snippets/fiber.rb +0 -41
  115. data/lib/ramaze/snippets/kernel/pretty_inspect.rb +0 -18
  116. data/lib/ramaze/snippets/metaid.rb +0 -17
  117. data/lib/ramaze/snippets/numeric/filesize_format.rb +0 -30
  118. data/lib/ramaze/snippets/numeric/time.rb +0 -59
  119. data/lib/ramaze/snippets/object/instance_variable_defined.rb +0 -16
  120. data/lib/ramaze/snippets/object/pretty.rb +0 -12
  121. data/lib/ramaze/snippets/object/scope.rb +0 -16
  122. data/lib/ramaze/snippets/ordered_set.rb +0 -51
  123. data/lib/ramaze/snippets/proc/locals.rb +0 -19
  124. data/lib/ramaze/snippets/ramaze/acquire.rb +0 -32
  125. data/lib/ramaze/snippets/ramaze/dictionary.rb +0 -400
  126. data/lib/ramaze/snippets/ramaze/fiber.rb +0 -24
  127. data/lib/ramaze/snippets/ramaze/struct.rb +0 -43
  128. data/lib/ramaze/snippets/string/end_with.rb +0 -17
  129. data/lib/ramaze/snippets/string/ord.rb +0 -16
  130. data/lib/ramaze/snippets/string/start_with.rb +0 -14
  131. data/lib/ramaze/snippets/thread/into.rb +0 -16
  132. data/lib/ramaze/spec.rb +0 -4
  133. data/spec/ramaze/bin/start.rb +0 -34
  134. data/spec/ramaze/log/growl.rb +0 -45
  135. data/spec/ramaze/struct.rb +0 -50
  136. data/spec/snippets/array/put_within.rb +0 -38
  137. data/spec/snippets/binding/locals.rb +0 -12
  138. data/spec/snippets/numeric/filesize_format.rb +0 -15
  139. data/spec/snippets/numeric/time.rb +0 -15
  140. data/spec/snippets/ordered_set.rb +0 -66
  141. data/spec/snippets/ramaze/acquire.rb +0 -80
  142. data/spec/snippets/ramaze/dictionary.rb +0 -113
  143. data/spec/snippets/ramaze/struct.rb +0 -15
  144. data/spec/snippets/thread/into.rb +0 -12
  145. data/tasks/gem.rake +0 -21
  146. data/tasks/setup.rake +0 -14
@@ -1,38 +0,0 @@
1
- # Copyright (c) 2008 Michael Fellinger m.fellinger@gmail.com
2
- # All files in this distribution are subject to the terms of the MIT license.
3
-
4
- module Ramaze
5
- module CoreExtensions
6
- # Extensions for Array
7
- module Array
8
- # a = [1, 2, 3]
9
- # a.put_within(4, :after => 2, :before => 3)
10
- # a # => [1, 2, 4, 3]
11
- def put_within(object, constrain)
12
- pre, post = constrain.values_at(:after, :before)
13
-
14
- return put_after(pre, object) if rindex(post) - index(pre) == 1
15
-
16
- raise ArgumentError, "Too many elements within constrain"
17
- end
18
-
19
- # a = [1, 2, 3]
20
- # a.put_after(2, 4)
21
- # a # => [1, 2, 4, 3]
22
- def put_after(element, object)
23
- return self[index(element) + 1, 0] = object if include?(element)
24
-
25
- raise ArgumentError, "The given element doesn't exist"
26
- end
27
-
28
- # a = [1, 2, 3]
29
- # a.put_before(2, 4)
30
- # a # => [1, 4, 2, 3]
31
- def put_before(element, object)
32
- return self[rindex(element), 0] = object if include?(element)
33
-
34
- raise ArgumentError, "The given element doesn't exist"
35
- end
36
- end # Array
37
- end # CoreExtensions
38
- end # Ramaze
@@ -1,20 +0,0 @@
1
- module Ramaze
2
- module CoreExtensions
3
- # Extensions for Binding
4
- module Binding
5
- # Returns a hash of localvar/localvar-values from binding, useful for
6
- # template engines that do not accept bindings and force passing locals
7
- # via hash
8
- #
9
- # @example
10
- # x = 42; p binding.locals #=> {'x'=> 42}
11
- def locals
12
- ::Kernel::eval '
13
- local_variables.inject({}){|h,v|
14
- k = v.to_s
15
- h.merge!(k => eval(k))
16
- }', self
17
- end
18
- end # Binding
19
- end # CoreExtensions
20
- end # Ramaze
@@ -1,41 +0,0 @@
1
- unless defined? Fiber
2
- require 'thread'
3
-
4
- class FiberError < StandardError; end
5
-
6
- class Fiber
7
- def initialize
8
- raise ArgumentError, 'new Fiber requires a block' unless block_given?
9
-
10
- @yield = Queue.new
11
- @resume = Queue.new
12
-
13
- @thread = Thread.new{ @yield.push [*yield(*wait)] }
14
- @thread.abort_on_exception = true
15
- @thread[:fiber] = self
16
- end
17
- attr_reader :yield, :thread
18
-
19
- def resume *args
20
- raise FiberError, 'dead fiber called' unless @thread.alive?
21
- @resume.push(args)
22
- result = @yield.pop
23
- result.size > 1 ? result : result.first
24
- end
25
-
26
- def wait
27
- @resume.pop
28
- end
29
-
30
- def self.yield *args
31
- raise FiberError, "can't yield from root fiber" unless fiber = Thread.current[:fiber]
32
- fiber.yield.push(args)
33
- result = fiber.wait
34
- result.size > 1 ? result : result.first
35
- end
36
-
37
- def inspect
38
- "#<#{self.class}:0x#{self.object_id.to_s(16)}>"
39
- end
40
- end
41
- end
@@ -1,18 +0,0 @@
1
- # Copyright (c) 2008 Michael Fellinger m.fellinger@gmail.com
2
- # All files in this distribution are subject to the terms of the MIT license.
3
-
4
- require 'pp'
5
-
6
- module Ramaze
7
- module CoreExtensions
8
- # Extensions for Kernel
9
- module Kernel
10
- unless defined?(pretty_inspect)
11
- # returns a pretty printed object as a string.
12
- def pretty_inspect
13
- PP.pp(self, '')
14
- end
15
- end
16
- end # Kernel
17
- end # CoreExtensions
18
- end # Ramaze
@@ -1,17 +0,0 @@
1
- # from http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html
2
-
3
- class Object
4
- # The hidden singleton lurks behind everyone
5
- def metaclass; class << self; self; end; end
6
- def meta_eval &blk; metaclass.instance_eval(&blk); end
7
-
8
- # Adds methods to a metaclass
9
- def meta_def name, &blk
10
- meta_eval { define_method name, &blk }
11
- end
12
-
13
- # Defines an instance method within a class
14
- def class_def name, &blk
15
- class_eval { define_method name, &blk }
16
- end
17
- end
@@ -1,30 +0,0 @@
1
- # Copyright (c) 2008 Michael Fellinger m.fellinger@gmail.com
2
- # All files in this distribution are subject to the terms of the MIT license.
3
-
4
- module Ramaze
5
- module CoreExtensions
6
- # Extensions for Numeric
7
- module Numeric
8
- FILESIZE_FORMAT = [
9
- ['%.1fT', 1 << 40],
10
- ['%.1fG', 1 << 30],
11
- ['%.1fM', 1 << 20],
12
- ['%.1fK', 1 << 10],
13
- ]
14
-
15
- # Output this number as easily readable filesize.
16
- # Usage:
17
- # 100_000.filesize_format # => "97.7K"
18
- # 100_000_000.filesize_format # => "95.4M"
19
- # 100_000_000_000.filesize_format # => "93.1G"
20
- # 100_000_000_000_000.filesize_format # => "90.9T"
21
- def filesize_format
22
- FILESIZE_FORMAT.each do |format, size|
23
- return format % (self.to_f / size) if self >= size
24
- end
25
-
26
- self.to_s
27
- end
28
- end # Numeric
29
- end # CoreExtensions
30
- end # Ramaze
@@ -1,59 +0,0 @@
1
- module Ramaze
2
- module CoreExtensions
3
- # Extensions for Numeric
4
- module Numeric
5
- def seconds
6
- self
7
- end
8
- alias second seconds
9
-
10
- # 60 seconds in a minute
11
- def minutes
12
- self * 60
13
- end
14
- alias minute minutes
15
-
16
- # 60 minutes in an hour
17
- def hours
18
- self * 3600
19
- end
20
- alias hour hours
21
-
22
- # 24 hours in a day
23
- def days
24
- self * 86400
25
- end
26
- alias day days
27
-
28
- # 7 days in a week
29
- def weeks
30
- self * 604800
31
- end
32
- alias week weeks
33
-
34
- # 30 days in a month
35
- def months
36
- self * 2592000
37
- end
38
- alias month months
39
-
40
- # 365.25 days in a year
41
- def years
42
- self * 31557600
43
- end
44
- alias year years
45
-
46
- # Time in the past, i.e. 3.days.ago
47
- def ago t = Time.now
48
- t - self
49
- end
50
- alias before ago
51
-
52
- # Time in the future, i.e. 3.days.from_now
53
- def from_now t = Time.now
54
- t + self
55
- end
56
- alias since from_now
57
- end # Numeric
58
- end # CoreExtensions
59
- end # Ramaze
@@ -1,16 +0,0 @@
1
- # Copyright (c) 2008 Michael Fellinger m.fellinger@gmail.com
2
- # All files in this distribution are subject to the terms of the MIT license.
3
-
4
- module Ramaze
5
- module CoreExtensions
6
- # Extensions for Object
7
- module Object
8
- # Available in 1.8.6 and later.
9
- unless ::Object.method_defined?(:instance_variable_defined?)
10
- def instance_variable_defined?(variable)
11
- instance_variables.include?(variable.to_s)
12
- end
13
- end
14
- end # Object
15
- end # CoreExtensions
16
- end # Ramaze
@@ -1,12 +0,0 @@
1
- module Ramaze
2
- module CoreExtensions
3
- # Extensions for Object
4
- module Object
5
- # Returns the string that #pretty_inspect would yield
6
- def pretty s = ''
7
- PP.pp(self, s)
8
- s
9
- end
10
- end # Object
11
- end # CoreExtensions
12
- end # Ramaze
@@ -1,16 +0,0 @@
1
- module Ramaze
2
- module CoreExtensions
3
- # Extensions for Object
4
- module Object
5
- # returns a new clean binding for this object
6
- #
7
- # Usage:
8
- #
9
- # eval 'self', object.scope #=> returns object
10
- #
11
- def scope
12
- lambda{}
13
- end
14
- end # Object
15
- end # CoreExtensions
16
- end # Ramaze
@@ -1,51 +0,0 @@
1
- # Copyright (c) 2008 Michael Fellinger m.fellinger@gmail.com
2
- # All files in this distribution are subject to the terms of the MIT license.
3
-
4
- require(File.join(File.dirname(__FILE__), 'blankslate'))
5
-
6
- # Basically an Set, but with Order, ain't that obivous?
7
- class OrderedSet < BlankSlate
8
- def self.[](*args)
9
- new(*args)
10
- end
11
-
12
- # Create new instances, optionally pass the first set
13
- def initialize(*args)
14
- if args.size == 1
15
- @set = args.shift
16
- else
17
- @set = *args
18
- end
19
-
20
- @set ||= []
21
- @set = [@set] unless ::Array === @set
22
- @set.uniq!
23
- end
24
-
25
- %w[ push unshift << ].each do |meth|
26
- class_eval %[
27
- def #{meth} *args
28
- @set.delete(*args)
29
- @set.#{meth}(*args)
30
- end
31
- ]
32
- end
33
-
34
- def []= *args
35
- @set.map! do |e|
36
- if ::Array === args.last
37
- args.last.include?(e) ? nil : e
38
- else
39
- args.last == e ? nil : e
40
- end
41
- end
42
- @set.__send__(:[]=, *args)
43
- @set.compact!
44
- end
45
-
46
- # Delegate everything, but controlled, keep elements unique.
47
- # Warning, this is not really atomic.
48
- def method_missing(meth, *args, &block)
49
- @set.__send__(meth, *args, &block)
50
- end
51
- end
@@ -1,19 +0,0 @@
1
- module Ramaze
2
- module CoreExtensions
3
- # Extensions for Proc
4
- module Proc
5
- ##
6
- # Returns a hash of localvar/localvar-values from proc, useful for
7
- # template engines that do not accept bindings/proc and force passing
8
- # locals via hash
9
- #
10
- # Usage:
11
- #
12
- # x = 42; p Proc.new.locals #=> {'x'=> 42}
13
- #
14
- def locals
15
- instance_eval('binding').locals
16
- end
17
- end # Proc
18
- end # CoreExtensions
19
- end # Ramaze
@@ -1,32 +0,0 @@
1
- # Copyright (c) 2008 Michael Fellinger m.fellinger@gmail.com
2
- # All files in this distribution are subject to the terms of the MIT license.
3
-
4
- module Ramaze
5
- # Require all .rb and .so files on the given globs, utilizes Dir::[].
6
- #
7
- # Examples:
8
- #
9
- # # Given following directory structure:
10
- # # src/foo.rb
11
- # # src/bar.so
12
- # # src/foo.yaml
13
- # # src/foobar/baz.rb
14
- # # src/foobar/README
15
- #
16
- # # requires all files in 'src':
17
- # Ramaze.acquire 'src/*'
18
- #
19
- # # requires all files in 'src' recursive:
20
- # Ramaze.acquire 'src/**/*'
21
- #
22
- # # require 'src/foo.rb' and 'src/bar.so' and 'src/foobar/baz.rb'
23
- # Ramaze.acquire 'src/*', 'src/foobar/*'
24
- #
25
- def self.acquire(*globs)
26
- globs.flatten.each do |glob|
27
- Dir[glob].each do |file|
28
- require file if file =~ /\.(rb|so)$/
29
- end
30
- end
31
- end
32
- end # Ramaze
@@ -1,400 +0,0 @@
1
- # = dictionary.rb
2
- #
3
- # == Copyright (c) 2005 Jan Molic, Thomas Sawyer
4
- #
5
- # Ruby License
6
- #
7
- # This module is free software. You may use, modify, and/or redistribute this
8
- # software under the same terms as Ruby.
9
- #
10
- # This program is distributed in the hope that it will be useful, but WITHOUT
11
- # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12
- # FOR A PARTICULAR PURPOSE.
13
- #
14
- # == Special Thanks
15
- #
16
- # Ported from OrderHash 2.0, Copyright (c) 2005 jan molic
17
- #
18
- # Thanks to Andrew Johnson for his suggestions and fixes of Hash[],
19
- # merge, to_a, inspect and shift.
20
- #
21
- # == Authors & Contributors
22
- #
23
- # * Jan Molic
24
- # * Thomas Sawyer
25
-
26
- # Author:: Jan Molic
27
- # Copyright:: Copyright (c) 2006 Jan Molic
28
- # License:: Ruby License
29
-
30
- # = Dictionary
31
- #
32
- # The Dictionary class is a Hash that preserves order.
33
- # So it has some array-like extensions also. By defualt
34
- # a Dictionary object preserves insertion order, but any
35
- # order can be specified including alphabetical key order.
36
- #
37
- # == Usage
38
- #
39
- # Just require this file and use Dictionary instead of Hash.
40
- #
41
- # # You can do simply
42
- # hsh = Dictionary.new
43
- # hsh['z'] = 1
44
- # hsh['a'] = 2
45
- # hsh['c'] = 3
46
- # p hsh.keys #=> ['z','a','c']
47
- #
48
- # # or using Dictionary[] method
49
- # hsh = Dictionary['z', 1, 'a', 2, 'c', 3]
50
- # p hsh.keys #=> ['z','a','c']
51
- #
52
- # # but this don't preserve order
53
- # hsh = Dictionary['z'=>1, 'a'=>2, 'c'=>3]
54
- # p hsh.keys #=> ['a','c','z']
55
- #
56
- # # Dictionary has useful extensions: push, pop and unshift
57
- # p hsh.push('to_end', 15) #=> true, key added
58
- # p hsh.push('to_end', 30) #=> false, already - nothing happen
59
- # p hsh.unshift('to_begin', 50) #=> true, key added
60
- # p hsh.unshift('to_begin', 60) #=> false, already - nothing happen
61
- # p hsh.keys #=> ["to_begin", "a", "c", "z", "to_end"]
62
- # p hsh.pop #=> ["to_end", 15], if nothing remains, return nil
63
- # p hsh.keys #=> ["to_begin", "a", "c", "z"]
64
- # p hsh.shift #=> ["to_begin", 30], if nothing remains, return nil
65
- #
66
- # == Usage Notes
67
- #
68
- # * You can use #order_by to set internal sort order.
69
- # * #<< takes a two element [k,v] array and inserts.
70
- # * Use ::auto which creates Dictionay sub-entries as needed.
71
- # * And ::alpha which creates a new Dictionary sorted by key.
72
-
73
- module Ramaze
74
- class Dictionary
75
-
76
- class << self
77
-
78
- #--
79
- # TODO is this needed? Doesn't the super class do this?
80
- #++
81
-
82
- def []( *args )
83
- hsh = new
84
- if Hash === args[0]
85
- hsh.replace(args[0])
86
- elsif (args.size % 2) != 0
87
- raise ArgumentError, "odd number of elements for Hash"
88
- else
89
- while !args.empty?
90
- hsh[args.shift] = args.shift
91
- end
92
- end
93
- hsh
94
- end
95
-
96
- # Like #new but the block sets the order.
97
- #
98
- def new_by( *args, &blk )
99
- new(*args).order_by(&blk)
100
- end
101
-
102
- # Alternate to #new which creates a dictionary sorted by key.
103
- #
104
- # d = Dictionary.alpha
105
- # d["z"] = 1
106
- # d["y"] = 2
107
- # d["x"] = 3
108
- # d #=> {"x"=>3,"y"=>2,"z"=>2}
109
- #
110
- # This is equivalent to:
111
- #
112
- # Dictionary.new.order_by { |key,value| key }
113
-
114
- def alpha( *args, &block )
115
- new( *args, &block ).order_by_key
116
- end
117
-
118
- # Alternate to #new which auto-creates sub-dictionaries as needed.
119
- #
120
- # d = Dictionary.auto
121
- # d["a"]["b"]["c"] = "abc" #=> { "a"=>{"b"=>{"c"=>"abc"}}}
122
- #
123
- def auto( *args )
124
- #AutoDictionary.new(*args)
125
- leet = lambda { |hsh, key| hsh[key] = new( &leet ) }
126
- new(*args, &leet)
127
- end
128
- end
129
-
130
- def initialize( *args, &blk )
131
- @order = []
132
- @order_by = nil
133
- @hash = Hash.new( *args, &blk )
134
- end
135
-
136
- def order
137
- reorder if @order_by
138
- @order
139
- end
140
-
141
- # Keep dictionary sorted by a specific sort order.
142
-
143
- def order_by( &block )
144
- @order_by = block
145
- order
146
- self
147
- end
148
-
149
- # Keep dictionary sorted by key.
150
- #
151
- # d = Dictionary.new.order_by_key
152
- # d["z"] = 1
153
- # d["y"] = 2
154
- # d["x"] = 3
155
- # d #=> {"x"=>3,"y"=>2,"z"=>2}
156
- #
157
- # This is equivalent to:
158
- #
159
- # Dictionary.new.order_by { |key,value| key }
160
- #
161
- # The initializer Dictionary#alpha also provides this.
162
-
163
- def order_by_key
164
- @order_by = lambda { |k,v| k }
165
- order
166
- self
167
- end
168
-
169
- # Keep dictionary sorted by value.
170
- #
171
- # d = Dictionary.new.order_by_value
172
- # d["z"] = 1
173
- # d["y"] = 2
174
- # d["x"] = 3
175
- # d #=> {"x"=>3,"y"=>2,"z"=>2}
176
- #
177
- # This is equivalent to:
178
- #
179
- # Dictionary.new.order_by { |key,value| value }
180
-
181
- def order_by_value
182
- @order_by = lambda { |k,v| v }
183
- order
184
- self
185
- end
186
-
187
- #
188
-
189
- def reorder
190
- if @order_by
191
- assoc = @order.collect{ |k| [k,@hash[k]] }.sort_by( &@order_by )
192
- @order = assoc.collect{ |k,v| k }
193
- end
194
- @order
195
- end
196
-
197
- #def ==( hsh2 )
198
- # return false if @order != hsh2.order
199
- # super hsh2
200
- #end
201
-
202
- def ==( hsh2 )
203
- if hsh2.is_a?( Dictionary )
204
- @order == hsh2.order &&
205
- @hash == hsh2.instance_variable_get("@hash")
206
- else
207
- false
208
- end
209
- end
210
-
211
- def [] k
212
- @hash[ k ]
213
- end
214
-
215
- def fetch( k )
216
- @hash.fetch( k )
217
- end
218
-
219
- # Store operator.
220
- #
221
- # h[key] = value
222
- #
223
- # Or with additional index.
224
- #
225
- # h[key,index] = value
226
-
227
- def []=(k, i=nil, v=nil)
228
- if v
229
- insert(i,k,v)
230
- else
231
- store(k,i)
232
- end
233
- end
234
-
235
- def insert( i,k,v )
236
- @order.insert( i,k )
237
- @hash.store( k,v )
238
- end
239
-
240
- def store( a,b )
241
- @order.push( a ) unless @hash.has_key?( a )
242
- @hash.store( a,b )
243
- end
244
-
245
- def clear
246
- @order = []
247
- @hash.clear
248
- end
249
-
250
- def delete( key )
251
- @order.delete( key )
252
- @hash.delete( key )
253
- end
254
-
255
- def each_key
256
- order.each { |k| yield( k ) }
257
- self
258
- end
259
-
260
- def each_value
261
- order.each { |k| yield( @hash[k] ) }
262
- self
263
- end
264
-
265
- def each
266
- order.each { |k| yield( k,@hash[k] ) }
267
- self
268
- end
269
- alias each_pair each
270
-
271
- def delete_if
272
- order.clone.each { |k| delete k if yield }
273
- self
274
- end
275
-
276
- def values
277
- ary = []
278
- order.each { |k| ary.push @hash[k] }
279
- ary
280
- end
281
-
282
- def keys
283
- order
284
- end
285
-
286
- def invert
287
- hsh2 = self.class.new
288
- order.each { |k| hsh2[@hash[k]] = k }
289
- hsh2
290
- end
291
-
292
- def reject( &block )
293
- self.dup.delete_if(&block)
294
- end
295
-
296
- def reject!( &block )
297
- hsh2 = reject(&block)
298
- self == hsh2 ? nil : hsh2
299
- end
300
-
301
- def replace( hsh2 )
302
- @order = hsh2.order
303
- @hash = hsh2.hash
304
- end
305
-
306
- def shift
307
- key = order.first
308
- key ? [key,delete(key)] : super
309
- end
310
-
311
- def unshift( k,v )
312
- unless @hash.include?( k )
313
- @order.unshift( k )
314
- @hash.store( k,v )
315
- true
316
- else
317
- false
318
- end
319
- end
320
-
321
- def <<(kv)
322
- push(*kv)
323
- end
324
-
325
- def push( k,v )
326
- unless @hash.include?( k )
327
- @order.push( k )
328
- @hash.store( k,v )
329
- true
330
- else
331
- false
332
- end
333
- end
334
-
335
- def pop
336
- key = order.last
337
- key ? [key,delete(key)] : nil
338
- end
339
-
340
- def to_a
341
- ary = []
342
- each { |k,v| ary << [k,v] }
343
- ary
344
- end
345
-
346
- def to_s
347
- self.to_a.to_s
348
- end
349
-
350
- def inspect
351
- ary = []
352
- each {|k,v| ary << k.inspect + "=>" + v.inspect}
353
- '{' + ary.join(", ") + '}'
354
- end
355
-
356
- def dup
357
- self.class[*to_a.flatten]
358
- end
359
-
360
- def update( hsh2 )
361
- hsh2.each { |k,v| self[k] = v }
362
- reorder
363
- self
364
- end
365
- alias merge! update
366
-
367
- def merge( hsh2 )
368
- self.dup.update(hsh2)
369
- end
370
-
371
- def select
372
- ary = []
373
- each { |k,v| ary << [k,v] if yield k,v }
374
- ary
375
- end
376
-
377
- def find
378
- each{|k,v| return k, v if yield(k,v) }
379
- return nil
380
- end
381
-
382
- def first
383
- @hash[order.first]
384
- end
385
-
386
- def last
387
- @hash[order.last]
388
- end
389
-
390
- def length
391
- @order.length
392
- end
393
- alias size length
394
-
395
- def empty?
396
- @hash.empty?
397
- end
398
-
399
- end
400
- end