ramaze 2012.04.14 → 2012.12.08b

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 (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