ramaze 0.0.6

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 (174) hide show
  1. data/Rakefile +360 -0
  2. data/bin/ramaze +152 -0
  3. data/doc/CHANGELOG +2021 -0
  4. data/doc/COPYING +56 -0
  5. data/doc/COPYING.ja +51 -0
  6. data/doc/README +275 -0
  7. data/doc/TODO +33 -0
  8. data/doc/allison/LICENSE +184 -0
  9. data/doc/allison/README +37 -0
  10. data/doc/allison/allison.css +300 -0
  11. data/doc/allison/allison.gif +0 -0
  12. data/doc/allison/allison.js +307 -0
  13. data/doc/allison/allison.rb +287 -0
  14. data/doc/allison/cache/BODY +588 -0
  15. data/doc/allison/cache/CLASS_INDEX +4 -0
  16. data/doc/allison/cache/CLASS_PAGE +1 -0
  17. data/doc/allison/cache/FILE_INDEX +4 -0
  18. data/doc/allison/cache/FILE_PAGE +1 -0
  19. data/doc/allison/cache/FONTS +1 -0
  20. data/doc/allison/cache/FR_INDEX_BODY +1 -0
  21. data/doc/allison/cache/IMGPATH +1 -0
  22. data/doc/allison/cache/INDEX +1 -0
  23. data/doc/allison/cache/JAVASCRIPT +307 -0
  24. data/doc/allison/cache/METHOD_INDEX +4 -0
  25. data/doc/allison/cache/METHOD_LIST +1 -0
  26. data/doc/allison/cache/SRC_PAGE +1 -0
  27. data/doc/allison/cache/STYLE +322 -0
  28. data/doc/allison/cache/URL +1 -0
  29. data/examples/blog/main.rb +16 -0
  30. data/examples/blog/public/screen.css +106 -0
  31. data/examples/blog/src/controller.rb +50 -0
  32. data/examples/blog/src/element.rb +53 -0
  33. data/examples/blog/src/model.rb +29 -0
  34. data/examples/blog/template/edit.xhtml +6 -0
  35. data/examples/blog/template/index.xhtml +24 -0
  36. data/examples/blog/template/new.xhtml +5 -0
  37. data/examples/blog/template/view.xhtml +15 -0
  38. data/examples/blog/test/tc_entry.rb +18 -0
  39. data/examples/caching.rb +23 -0
  40. data/examples/element.rb +40 -0
  41. data/examples/hello.rb +23 -0
  42. data/examples/simple.rb +60 -0
  43. data/examples/templates/template/external.haml +21 -0
  44. data/examples/templates/template/external.liquid +28 -0
  45. data/examples/templates/template/external.mab +27 -0
  46. data/examples/templates/template/external.rhtml +29 -0
  47. data/examples/templates/template/external.rmze +24 -0
  48. data/examples/templates/template_erubis.rb +50 -0
  49. data/examples/templates/template_haml.rb +48 -0
  50. data/examples/templates/template_liquid.rb +64 -0
  51. data/examples/templates/template_markaby.rb +52 -0
  52. data/examples/templates/template_ramaze.rb +49 -0
  53. data/examples/whywiki/main.rb +56 -0
  54. data/examples/whywiki/template/edit.xhtml +14 -0
  55. data/examples/whywiki/template/show.xhtml +17 -0
  56. data/lib/proto/conf/benchmark.yaml +35 -0
  57. data/lib/proto/conf/debug.yaml +34 -0
  58. data/lib/proto/conf/live.yaml +33 -0
  59. data/lib/proto/conf/silent.yaml +31 -0
  60. data/lib/proto/conf/stage.yaml +33 -0
  61. data/lib/proto/main.rb +18 -0
  62. data/lib/proto/public/404.jpg +0 -0
  63. data/lib/proto/public/css/coderay.css +105 -0
  64. data/lib/proto/public/css/ramaze_error.css +42 -0
  65. data/lib/proto/public/error.xhtml +74 -0
  66. data/lib/proto/public/favicon.ico +0 -0
  67. data/lib/proto/public/js/jquery.js +1923 -0
  68. data/lib/proto/public/ramaze.png +0 -0
  69. data/lib/proto/src/controller/main.rb +7 -0
  70. data/lib/proto/src/element/page.rb +16 -0
  71. data/lib/proto/src/model.rb +5 -0
  72. data/lib/proto/template/index.xhtml +6 -0
  73. data/lib/ramaze.rb +317 -0
  74. data/lib/ramaze/adapter/mongrel.rb +111 -0
  75. data/lib/ramaze/adapter/webrick.rb +161 -0
  76. data/lib/ramaze/cache.rb +11 -0
  77. data/lib/ramaze/cache/memcached.rb +52 -0
  78. data/lib/ramaze/cache/memory.rb +6 -0
  79. data/lib/ramaze/cache/yaml_store.rb +37 -0
  80. data/lib/ramaze/controller.rb +10 -0
  81. data/lib/ramaze/dispatcher.rb +315 -0
  82. data/lib/ramaze/error.rb +11 -0
  83. data/lib/ramaze/gestalt.rb +108 -0
  84. data/lib/ramaze/global.rb +120 -0
  85. data/lib/ramaze/helper.rb +32 -0
  86. data/lib/ramaze/helper/aspect.rb +189 -0
  87. data/lib/ramaze/helper/auth.rb +120 -0
  88. data/lib/ramaze/helper/cache.rb +52 -0
  89. data/lib/ramaze/helper/feed.rb +135 -0
  90. data/lib/ramaze/helper/form.rb +204 -0
  91. data/lib/ramaze/helper/link.rb +80 -0
  92. data/lib/ramaze/helper/redirect.rb +48 -0
  93. data/lib/ramaze/helper/stack.rb +67 -0
  94. data/lib/ramaze/http_status.rb +66 -0
  95. data/lib/ramaze/inform.rb +166 -0
  96. data/lib/ramaze/snippets.rb +5 -0
  97. data/lib/ramaze/snippets/hash/keys_to_sym.rb +19 -0
  98. data/lib/ramaze/snippets/kernel/aquire.rb +22 -0
  99. data/lib/ramaze/snippets/kernel/autoreload.rb +79 -0
  100. data/lib/ramaze/snippets/kernel/caller_lines.rb +58 -0
  101. data/lib/ramaze/snippets/kernel/constant.rb +24 -0
  102. data/lib/ramaze/snippets/kernel/rescue_require.rb +12 -0
  103. data/lib/ramaze/snippets/kernel/self_method.rb +41 -0
  104. data/lib/ramaze/snippets/kernel/silently.rb +13 -0
  105. data/lib/ramaze/snippets/object/traits.rb +60 -0
  106. data/lib/ramaze/snippets/openstruct/temp.rb +10 -0
  107. data/lib/ramaze/snippets/string/DIVIDE.rb +16 -0
  108. data/lib/ramaze/snippets/string/camel_case.rb +14 -0
  109. data/lib/ramaze/snippets/string/snake_case.rb +12 -0
  110. data/lib/ramaze/snippets/symbol/to_proc.rb +14 -0
  111. data/lib/ramaze/snippets/thread/deadQUESTIONMARK.rb +11 -0
  112. data/lib/ramaze/store/default.rb +48 -0
  113. data/lib/ramaze/template.rb +102 -0
  114. data/lib/ramaze/template/amrita2.rb +40 -0
  115. data/lib/ramaze/template/erubis.rb +58 -0
  116. data/lib/ramaze/template/haml.rb +65 -0
  117. data/lib/ramaze/template/haml/actionview_stub.rb +20 -0
  118. data/lib/ramaze/template/liquid.rb +74 -0
  119. data/lib/ramaze/template/markaby.rb +68 -0
  120. data/lib/ramaze/template/ramaze.rb +177 -0
  121. data/lib/ramaze/template/ramaze/element.rb +166 -0
  122. data/lib/ramaze/template/ramaze/morpher.rb +156 -0
  123. data/lib/ramaze/tool/create.rb +70 -0
  124. data/lib/ramaze/tool/tidy.rb +71 -0
  125. data/lib/ramaze/trinity.rb +38 -0
  126. data/lib/ramaze/trinity/request.rb +244 -0
  127. data/lib/ramaze/trinity/response.rb +41 -0
  128. data/lib/ramaze/trinity/session.rb +129 -0
  129. data/lib/ramaze/version.rb +14 -0
  130. data/spec/spec_all.rb +73 -0
  131. data/spec/spec_helper.rb +215 -0
  132. data/spec/tc_adapter_mongrel.rb +24 -0
  133. data/spec/tc_adapter_webrick.rb +22 -0
  134. data/spec/tc_cache.rb +79 -0
  135. data/spec/tc_controller.rb +39 -0
  136. data/spec/tc_element.rb +100 -0
  137. data/spec/tc_error.rb +23 -0
  138. data/spec/tc_gestalt.rb +90 -0
  139. data/spec/tc_global.rb +46 -0
  140. data/spec/tc_helper_aspect.rb +65 -0
  141. data/spec/tc_helper_auth.rb +61 -0
  142. data/spec/tc_helper_cache.rb +81 -0
  143. data/spec/tc_helper_feed.rb +129 -0
  144. data/spec/tc_helper_form.rb +146 -0
  145. data/spec/tc_helper_link.rb +58 -0
  146. data/spec/tc_helper_redirect.rb +51 -0
  147. data/spec/tc_helper_stack.rb +55 -0
  148. data/spec/tc_morpher.rb +90 -0
  149. data/spec/tc_params.rb +84 -0
  150. data/spec/tc_request.rb +111 -0
  151. data/spec/tc_session.rb +56 -0
  152. data/spec/tc_store.rb +25 -0
  153. data/spec/tc_template_amrita2.rb +34 -0
  154. data/spec/tc_template_erubis.rb +41 -0
  155. data/spec/tc_template_haml.rb +44 -0
  156. data/spec/tc_template_liquid.rb +98 -0
  157. data/spec/tc_template_markaby.rb +74 -0
  158. data/spec/tc_template_ramaze.rb +54 -0
  159. data/spec/tc_tidy.rb +14 -0
  160. data/spec/template/amrita2/data.html +6 -0
  161. data/spec/template/amrita2/index.html +1 -0
  162. data/spec/template/amrita2/sum.html +1 -0
  163. data/spec/template/erubis/sum.rhtml +1 -0
  164. data/spec/template/haml/index.haml +5 -0
  165. data/spec/template/haml/with_vars.haml +4 -0
  166. data/spec/template/liquid/index.liquid +1 -0
  167. data/spec/template/liquid/products.liquid +45 -0
  168. data/spec/template/markaby/external.mab +8 -0
  169. data/spec/template/markaby/sum.mab +1 -0
  170. data/spec/template/ramaze/file_only.rmze +1 -0
  171. data/spec/template/ramaze/index.rmze +1 -0
  172. data/spec/template/ramaze/nested.rmze +1 -0
  173. data/spec/template/ramaze/sum.rmze +1 -0
  174. metadata +317 -0
@@ -0,0 +1,120 @@
1
+ # Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
2
+ # All files in this distribution are subject to the terms of the Ruby license.
3
+
4
+ require 'digest/sha1'
5
+
6
+ module Ramaze
7
+
8
+ # A really, really, totally stupid way to do authentication. It has no
9
+ # roles and only a single password without usernames.
10
+ #
11
+ # It is intended to be a simple way to protect various partions of a page
12
+ # when you start working on it. Also it is a nice way to see how you could
13
+ # implement your own authentication.
14
+
15
+ module AuthHelper
16
+ def self.included(klass)
17
+ klass.class_eval do
18
+ helper :aspect, :stack
19
+ end
20
+ end
21
+
22
+ # The default Element to use (if any)
23
+
24
+ AUTH_ELEMENT = 'Page'
25
+
26
+ # action for login, takes a password
27
+ # ( ?password=passwort or /login/passwort or via a form )
28
+ # if no password given, shows a simple form to input it.
29
+
30
+ def login
31
+ if check_auth(request['username'], request['password'])
32
+ session[:logged_in] = true
33
+ inside_stack? ? answer : redirect( R(self) )
34
+ else
35
+ %{
36
+ <#{AUTH_ELEMENT}>
37
+ <form method="POST" action="#{R(self, :login)}"
38
+ <ul style="list-style:none;">
39
+ <li>Username: <input type="text" name="username" /></li>
40
+ <li>Password: <input type="password" name="password" /></li>
41
+ <li><input type="submit" /></li>
42
+ </ul>
43
+ </form>
44
+ </#{AUTH_ELEMENT}>
45
+ }
46
+ end
47
+ end
48
+
49
+ # clear the session and redirect to the index action of the mapping of the
50
+ # current controller.
51
+
52
+ def logout
53
+ session.clear
54
+ redirect_referer
55
+ end
56
+
57
+ private
58
+
59
+ # call( R(self, :login) ) if not logged in
60
+
61
+ def login_required
62
+ call(R(self, :login)) unless logged_in?
63
+ end
64
+
65
+ # checks if the user is already logged in.
66
+ # session[:logged_in] is not nil/false
67
+
68
+ def logged_in?
69
+ !!session[:logged_in]
70
+ end
71
+
72
+ # check the authentication (username and password) against the auth_table.
73
+ #
74
+ # auth_table is a trait, it may be the name of a method, a Proc or a simple
75
+ # Hash.
76
+ # If it is neither of the above it has at least to respond to #[]
77
+ # which will pass it the username as key and it should answer with the
78
+ # password as a SHA1.hexdigest.
79
+ #
80
+ # The method and Proc are both called on demand.
81
+ #
82
+ # If you want to change the way the password is hashed, change
83
+ # trait[:auth_hashify]
84
+ #
85
+ # The default looks like:
86
+ # lambda{ |pass| Digest::SHA1.hexdigest(pass.to_s) }
87
+ #
88
+ # As with the auth_table, this has to be an object that responds to #[]
89
+ #
90
+ # If you want all your controllers to use the same mechanism set the trait
91
+ # on one of the ancestors, the traits are looked up by #ancestral_trait
92
+ #
93
+ # Examples:
94
+ #
95
+ # # The method to be called.
96
+ # trait :auth_table => :auth_table
97
+ # trait :auth_tagle => 'auth_table'
98
+ #
99
+ # # Lambda that will be called upon demand
100
+ # trait :auth_table => lambda{ {'manveru' => SHA1.hexdigest 'password'} }
101
+ #
102
+ # # Hash holding the data.
103
+ # trait :auth_table => {'manveru' => SHA1.hexdigest('password')}
104
+
105
+ def check_auth user, pass
106
+ auth_table = ancestral_trait[:auth_table] ||= {}
107
+
108
+ auth_table = method(auth_table) if auth_table.is_a?(Symbol)
109
+ auth_table = method(auth_table) if auth_table.respond_to?(:to_str)
110
+ auth_table = auth_table.call if auth_table.respond_to?(:call)
111
+
112
+ default_hashify = lambda{ |pass| Digest::SHA1.hexdigest(pass.to_s) }
113
+
114
+ hashify = (ancestral_trait[:auth_hashify] ||= default_hashify)
115
+ password = hashify[pass.to_s]
116
+
117
+ auth_table[user.to_s] == password
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,52 @@
1
+ # Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
2
+ # All files in this distribution are subject to the terms of the Ruby license.
3
+ module Ramaze
4
+ module CacheHelper
5
+ private
6
+
7
+ # a simple cache for values based on Global.cache
8
+
9
+ def value_cache
10
+ @@cache ||= Global.cache.new
11
+ end
12
+
13
+ # forget about one cached action
14
+
15
+ def uncache action
16
+ Global.cached_actions[self.class].each do |e|
17
+ e.include?(action.to_s)
18
+ end
19
+ end
20
+
21
+ # uncache all actions
22
+
23
+ def uncache_all
24
+ Global.cached_actions.delete(self.class)
25
+ end
26
+ alias uncache_all_actions uncache_all
27
+
28
+ # cache all given methods
29
+
30
+ def cache(*actions)
31
+ self.class.cache(*actions)
32
+ end
33
+ alias cache_actions cache
34
+
35
+ # define the cache class-method on inclusion
36
+
37
+ def self.included(klass)
38
+ klass.class_eval do
39
+ class << self
40
+
41
+ # mark actions for caching
42
+
43
+ def cache(*actions)
44
+ Global.cache_actions[self].merge(*actions.flatten.map{|a| a.to_s })
45
+ end
46
+ alias cache_actions cache
47
+
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,135 @@
1
+ # Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
2
+ # All files in this distribution are subject to the terms of the Ruby license.
3
+
4
+ module Ramaze
5
+ module FeedHelper
6
+
7
+ # just a stub, for the moment, doing nothing more than calling
8
+ # #to_xml on the object you pass
9
+
10
+ def feed object
11
+ object.to_xml
12
+ end
13
+ end
14
+ end
15
+
16
+ module ReFeed
17
+
18
+ # Does a couple of things on include.
19
+ #
20
+ # defines #xml_accessor, which in turn offers a way to define
21
+ # both an attr_accessor and xml-annotation.
22
+ # xml_accessor :name, :age
23
+ #
24
+ # defines #xml, a little DSLy way to add an attribute that
25
+ # is later used to generate/read XML
26
+ # xml :name, :age
27
+ #
28
+ # defines #from_xml, which takes XML and maps the structure of the
29
+ # XML to your instances accessors.
30
+ # Foo.new.from_xml('<name>manveru</name><age>22</age>')
31
+ # # #<Foo @name='manveru', @age=22>
32
+
33
+ def self.included(klass)
34
+ klass.class_eval do
35
+ const_set('XML_ATTRIBUTES', {})
36
+
37
+ class << self
38
+
39
+ # Offers a way to define
40
+ # both an attr_accessor and xml-annotation.
41
+ # xml_accessor :name, :age
42
+
43
+ def xml_accessor(*args)
44
+ args = xml(*args)
45
+ attr_accessor(*args)
46
+ end
47
+
48
+ # A little DSLy way to add an attribute that
49
+ # is later used to generate/read XML
50
+ # xml :name, :age
51
+
52
+ def xml(*arguments)
53
+ args = []
54
+ hash = nil
55
+ klass = Object.const_get(self.to_s)
56
+
57
+ arguments.each do |arg|
58
+ if arg.respond_to?(:to_sym)
59
+ args << arg.to_sym
60
+ elsif arg.respond_to?(:to_hash)
61
+ hash = arg
62
+ end
63
+ end
64
+
65
+ args.each do |arg|
66
+ klass::XML_ATTRIBUTES[arg] = hash
67
+ end
68
+ end
69
+
70
+ # Which takes XML and maps the structure of the
71
+ # XML to your instances accessors.
72
+ # Foo.new.from_xml('<name>manveru</name><age>22</age>')
73
+ # # #<Foo @name='manveru', @age=22>
74
+
75
+ def from_xml(text)
76
+ instance = self.new
77
+
78
+ require 'hpricot'
79
+
80
+ xml = Hpricot(text.to_s)
81
+ attributes = instance.xml_attributes
82
+
83
+ attributes.each do |attribute, opts|
84
+ value = xml.at(attribute)
85
+ instance.send("#{attribute}=", value.inner_html) if value
86
+ end
87
+ instance
88
+ rescue LoadError => ex
89
+ error ex
90
+ ensure
91
+ instance
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ # return the XML_ATTRIBUTES of self.class
98
+
99
+ def xml_attributes
100
+ self.class::XML_ATTRIBUTES
101
+ end
102
+
103
+ # convert this instance to XML
104
+
105
+ def to_xml
106
+ name = self.class.name
107
+ xml = xml_attributes.map do |key, opts|
108
+ value = send(key)
109
+
110
+ next unless value
111
+ next if (opts[:type] == :attribute rescue false)
112
+
113
+ if opts and not opts.empty?
114
+ case opts[:type]
115
+ when nil, :text : "<#{key}>#{value}</#{key}>"
116
+ when :cdata : "<#{key}><![CDATA[#{value}]]></#{key}>"
117
+ when :collection : value.map{|v| v.to_xml }
118
+ end
119
+ elsif value.respond_to?(:to_xml)
120
+ value.to_xml
121
+ elsif value.respond_to?(:all?) and value.all?{|v| v.respond_to?(:to_xml) }
122
+ value.map{|v| v.to_xml }
123
+ end
124
+ end
125
+
126
+ attributes = xml_attributes.select{|k, o| o && o[:type] == :attribute}
127
+ attributes.map!{|k, o| %{#{k}="#{send(k)}"} }
128
+
129
+ unless attributes or attributes.empty?
130
+ "<#{name}>#{xml}</#{name}>"
131
+ else
132
+ "<#{name} #{attributes.join(' ')}><#{xml}></#{name}>"
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,204 @@
1
+ # Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
2
+ # All files in this distribution are subject to the terms of the Ruby license.
3
+
4
+ module Ramaze
5
+ module FormHelper
6
+
7
+ # Mapping different classes to an specific method on FormHelper::Control.
8
+
9
+ ClassMap = {
10
+ String => :text,
11
+ Time => :time,
12
+ Date => :date,
13
+ Fixnum => :number,
14
+ }
15
+
16
+ # Create the contents of a <form> for Og-objects.
17
+ # This can be an instance or the class itself. Depending if you
18
+ # want to edit an object or create a new one.
19
+ #
20
+ # Please note that the enclosing <form> itself is not (yet) generated.
21
+ #
22
+ # attributes that have no mapping in ClassMap are silently ignored.
23
+
24
+ def form obj, options = {}
25
+ default = {:deny => /oid/, :submit => true}
26
+ options = default.merge(options)
27
+
28
+ if obj.respond_to? :serializable_attributes
29
+ instance = obj.new
30
+ else
31
+ instance = obj
32
+ obj = obj.class
33
+ end
34
+
35
+ attributes = obj.serializable_attributes
36
+ out = []
37
+
38
+ chosen_attributes(attributes, options).each do |attribute|
39
+
40
+ o = OpenStruct.new :klass => obj.ann[attribute].class,
41
+ :value => (instance.send(attribute) rescue nil),
42
+ :name => attribute.to_s,
43
+ :title => (options.has_key?(attribute) ? options[attribute] : attribute)
44
+
45
+ control = obj.ann[attribute].control
46
+ control = ClassMap[o.klass] unless control.is_a?(Symbol)
47
+
48
+ out << Control.send(control, o) unless control.nil? or control == :none
49
+ end
50
+ if options[:submit] == true
51
+ out << %{<input type="submit" />}
52
+ elsif options[:submit]
53
+ out << %{<input type="submit" value="#{options[:submit]}" />}
54
+ end
55
+ out.join("<br />\n")
56
+ end
57
+
58
+ # options #=>
59
+ # { :deny => /oid/ }
60
+ # { :deny => [/time/, /oid/]}
61
+
62
+ def chosen_attributes(attributes, options)
63
+ attributes.reject do |attribute|
64
+ attribute = attribute.to_s
65
+ [options[:deny]].flatten.find do |d|
66
+ first_comp = attribute =~ d rescue attribute == d
67
+ first_comp || attribute == d
68
+ end
69
+ end
70
+ end
71
+
72
+ # Home of all the methods that output a tag for a specific
73
+ # attribute.
74
+ # They take objects that respond to :value and :name, preferably
75
+ # an modified OpenStruct that responds to :temp to allow for easy
76
+ # forking. ( lib/ramaze/snippets/openstruct/temp.rb )
77
+
78
+ module Control
79
+ class << self
80
+
81
+ # A simple text-control, default to 0
82
+
83
+ def number o
84
+ o.value ||= 0
85
+ text(o)
86
+ end
87
+
88
+ # <input type="text" />
89
+
90
+ def text o
91
+ o.value ||= ""
92
+ tag = ''
93
+ tag << "#{o.title}: " if o.title
94
+ tag << %{<input type="text" name="#{o.name}" value="#{o.value}" />}
95
+ end
96
+
97
+ # <textarea></textarea>
98
+
99
+ def textarea o
100
+ o.value ||= ""
101
+ %{<textarea name="#{o.name}">#{o.value}</textarea>}
102
+ end
103
+
104
+ # compound of #date_day, #date_month, #date_year, #time_hour,
105
+ # #time_minute and #time_second
106
+
107
+ def time o
108
+ o.value ||= Time.now
109
+ [
110
+ date_day(o.temp(:value => o.value.day)),
111
+ date_month(o.temp(:value => o.value.month)),
112
+ date_year(o.temp(:value => o.value.year)),
113
+ time_hour(o.temp(:value => o.value.hour)),
114
+ time_minute(o.temp(:value => o.value.min)),
115
+ time_second(o.temp(:value => o.value.sec)),
116
+ ].join("\n")
117
+ end
118
+
119
+ # <select name="xxx[sec]">
120
+ # <option value="0">0</option>
121
+ # ...
122
+ # <option value="60">60</option>
123
+ # </select>
124
+
125
+ def time_second(o)
126
+ select(o.name + '[sec]', (0...60), o.value)
127
+ end
128
+
129
+ # <select name="xxx[min]">
130
+ # <option value="0">0</option>
131
+ # ...
132
+ # <option value="60">60</option>
133
+ # </select>
134
+
135
+ def time_minute(o)
136
+ select(o.name + '[min]', (0...60), o.value)
137
+ end
138
+
139
+ # <select name="xxx[hour]">
140
+ # <option value="1">1</option>
141
+ # ...
142
+ # <option value="23">23</option>
143
+ # </select>
144
+
145
+ def time_hour(o)
146
+ select(o.name + '[hour]', (0...23), o.value)
147
+ end
148
+
149
+ # compound of #date_day, #date_month and #date_year
150
+
151
+ def date o
152
+ o.value ||= Date.today
153
+ [
154
+ date_day(o.temp(:value => o.value.day)),
155
+ date_month(o.temp(:value => o.value.month)),
156
+ date_year(o.temp(:value => o.value.year)),
157
+ ].join("\n")
158
+ end
159
+
160
+ # <select name="xxx[day]">
161
+ # <option value="1">1</option>
162
+ # ...
163
+ # <option value="31">31</option>
164
+ # </select>
165
+
166
+ def date_day(o)
167
+ select(o.name + '[day]', (1..31), o.value)
168
+ end
169
+
170
+ # <select name="xxx[month]">
171
+ # <option value="1">1950</option>
172
+ # ...
173
+ # <option value="12">12</option>
174
+ # </select>
175
+
176
+ def date_month(o)
177
+ select(o.name + '[month]', (1..12), o.value)
178
+ end
179
+
180
+ # <select name="xxx[year]">
181
+ # <option value="1950">1950</option>
182
+ # ...
183
+ # <option value="2050">2050</option>
184
+ # </select>
185
+
186
+ def date_year(o)
187
+ select(o.name + '[year]', (1950..2050), o.value)
188
+ end
189
+
190
+ # <select>
191
+ # <option></option>
192
+ # </select>
193
+
194
+ def select name, range, default
195
+ out = %{<select name="#{name}">\n}
196
+ range.each do |i|
197
+ out << %{<option value="#{i}"#{' selected="selected"' if default == i}>#{i}</option>\n}
198
+ end
199
+ out << "</select>\n"
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end