rhodes-framework 1.1.1 → 1.2.0
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.
- data/History.txt +3 -0
- data/Manifest.txt +8 -2
- data/README.txt +1 -0
- data/Rakefile +6 -30
- data/lib/builtinME.rb +67 -5
- data/lib/date.rb +121 -80
- data/lib/date/format.rb +44 -42
- data/lib/dateME.rb +2 -1
- data/lib/erb.rb +278 -238
- data/lib/rational.rb +2 -2
- data/lib/rho/rho.rb +59 -24
- data/lib/rho/rhoapplication.rb +13 -4
- data/lib/rho/rhocontroller.rb +7 -3
- data/lib/rho/rhoerror.rb +33 -0
- data/lib/rho/rhoutils.rb +5 -2
- data/lib/rhodes.rb +2 -2
- data/lib/rhom/rhom.rb +24 -11
- data/lib/rhom/rhom_db_adapter.rb +56 -23
- data/lib/rhom/rhom_object.rb +3 -32
- data/lib/rhom/rhom_object_factory.rb +154 -154
- data/lib/rhom/rhom_source.rb +9 -9
- data/lib/singleton.rb +3 -3
- data/lib/time.rb +20 -2
- data/lib/version.rb +2 -2
- data/spec/app/mspec/matchers/raise_error.rb +2 -1
- data/spec/app/spec/fixtures/object_values.txt +2 -2
- data/spec/app/spec/pagination/fixtures/object_values.txt +91 -0
- data/spec/app/spec/rho_controller_spec.rb +2 -2
- data/spec/app/spec/rho_spec.rb +8 -3
- data/spec/app/spec/rhom_db_adapter_spec.rb +27 -0
- data/spec/app/spec/{rhom_object_factory_spec.rb → rhom_object_spec.rb} +125 -10
- data/spec/app/spec/rhom_spec.rb +19 -8
- data/spec/app/spec/rhoruby_spec.rb +31 -0
- data/spec/app/spec/spec_helper.rb +2 -1
- data/spec/app/spec/syncengine_spec.rb +30 -0
- data/spec/app/spec_runner.rb +9 -5
- data/spec/build.yml +3 -2
- data/spec/rhoconfig.txt +2 -0
- metadata +19 -83
- data/lib/rhom/rhom_db_adapterME.rb +0 -92
data/lib/date/format.rb
CHANGED
@@ -3,10 +3,10 @@
|
|
3
3
|
|
4
4
|
if defined? RHO_ME
|
5
5
|
require 'rationalME'
|
6
|
+
else
|
7
|
+
require 'rational'
|
6
8
|
end
|
7
9
|
|
8
|
-
require 'rational'
|
9
|
-
|
10
10
|
class Date
|
11
11
|
|
12
12
|
#SECONDS_IN_DAY = 60*60*24
|
@@ -283,6 +283,7 @@ class Date
|
|
283
283
|
when 'j'; emit_n(yday(), 3, f)
|
284
284
|
when 'k'; emit_a(hour(), 2, f)
|
285
285
|
when 'L'
|
286
|
+
f[:p] = nil
|
286
287
|
w = f[:w] || 3
|
287
288
|
u = 10**w
|
288
289
|
emit_n((sec_fraction * u).floor, w, f)
|
@@ -290,6 +291,7 @@ class Date
|
|
290
291
|
when 'M', 'OM'; emit_n(min(), 2, f)
|
291
292
|
when 'm', 'Om'; emit_n(mon(), 2, f)
|
292
293
|
when 'N'
|
294
|
+
f[:p] = nil
|
293
295
|
w = f[:w] || 9
|
294
296
|
u = 10**w
|
295
297
|
emit_n((sec_fraction * u).floor, w, f)
|
@@ -695,11 +697,11 @@ class Date
|
|
695
697
|
private_class_method :s3e
|
696
698
|
|
697
699
|
def self._parse_day(str, e) # :nodoc:
|
698
|
-
if str.sub!(/\b(#{Format::ABBR_DAYS.keys.join('|')})[^-\d\s]*/
|
700
|
+
if str.sub!(/\b(#{Format::ABBR_DAYS.keys.join('|')})[^-\d\s]*/io, ' ')
|
699
701
|
e.wday = Format::ABBR_DAYS[$1.downcase]
|
700
702
|
true
|
701
703
|
=begin
|
702
|
-
elsif str.sub!(/\b(?!\dth)(su|mo|tu|we|th|fr|sa)\b/
|
704
|
+
elsif str.sub!(/\b(?!\dth)(su|mo|tu|we|th|fr|sa)\b/i, ' ')
|
703
705
|
e.wday = %w(su mo tu we th fr sa).index($1.downcase)
|
704
706
|
true
|
705
707
|
=end
|
@@ -734,7 +736,7 @@ class Date
|
|
734
736
|
[[:alpha:]]+(?:\sdst)?\b
|
735
737
|
)
|
736
738
|
)?
|
737
|
-
/
|
739
|
+
/ix,
|
738
740
|
' ')
|
739
741
|
|
740
742
|
t = $1
|
@@ -746,7 +748,7 @@ class Date
|
|
746
748
|
\s*:?\s*(\d+)(?:[,.](\d+))?s?
|
747
749
|
)?
|
748
750
|
)?
|
749
|
-
(?:\s*([ap])(?:m\b|\.m\.))?/
|
751
|
+
(?:\s*([ap])(?:m\b|\.m\.))?/ix
|
750
752
|
|
751
753
|
e.hour = $1.to_i
|
752
754
|
e.min = $2.to_i if $2
|
@@ -791,7 +793,7 @@ class Date
|
|
791
793
|
\s*
|
792
794
|
('?-?\d+(?:(?:st|nd|rd|th)\b)?)
|
793
795
|
)?
|
794
|
-
/
|
796
|
+
/iox,
|
795
797
|
' ') # '
|
796
798
|
s3e(e, $4, Format::ABBR_MONTHS[$2.downcase], $1,
|
797
799
|
$3 && $3[0,1].downcase == 'b')
|
@@ -810,7 +812,7 @@ class Date
|
|
810
812
|
\s*
|
811
813
|
('?-?\d+)
|
812
814
|
)?
|
813
|
-
/
|
815
|
+
/iox,
|
814
816
|
' ') # '
|
815
817
|
s3e(e, $4, Format::ABBR_MONTHS[$1.downcase], $2,
|
816
818
|
$3 && $3[0,1].downcase == 'b')
|
@@ -819,43 +821,43 @@ class Date
|
|
819
821
|
end
|
820
822
|
|
821
823
|
def self._parse_iso(str, e) # :nodoc:
|
822
|
-
if str.sub!(/('?[-+]?\d+)-(\d+)-('?-?\d+)
|
824
|
+
if str.sub!(/('?[-+]?\d+)-(\d+)-('?-?\d+)/, ' ')
|
823
825
|
s3e(e, $1, $2, $3)
|
824
826
|
true
|
825
827
|
end
|
826
828
|
end
|
827
829
|
|
828
830
|
def self._parse_iso2(str, e) # :nodoc:
|
829
|
-
if str.sub!(/\b(\d{2}|\d{4})?-?w(\d{2})(?:-?(\d))?\b/
|
831
|
+
if str.sub!(/\b(\d{2}|\d{4})?-?w(\d{2})(?:-?(\d))?\b/i, ' ')
|
830
832
|
e.cwyear = $1.to_i if $1
|
831
833
|
e.cweek = $2.to_i
|
832
834
|
e.cwday = $3.to_i if $3
|
833
835
|
true
|
834
|
-
elsif str.sub!(/-w-(\d)\b/
|
836
|
+
elsif str.sub!(/-w-(\d)\b/i, ' ')
|
835
837
|
e.cwday = $1.to_i
|
836
838
|
true
|
837
|
-
elsif str.sub!(/--(\d{2})?-(\d{2})\b
|
839
|
+
elsif str.sub!(/--(\d{2})?-(\d{2})\b/, ' ')
|
838
840
|
e.mon = $1.to_i if $1
|
839
841
|
e.mday = $2.to_i
|
840
842
|
true
|
841
|
-
elsif str.sub!(/--(\d{2})(\d{2})?\b
|
843
|
+
elsif str.sub!(/--(\d{2})(\d{2})?\b/, ' ')
|
842
844
|
e.mon = $1.to_i
|
843
845
|
e.mday = $2.to_i if $2
|
844
846
|
true
|
845
|
-
elsif /[,.](\d{2}|\d{4})-\d{3}\b/
|
846
|
-
str.sub!(/\b(\d{2}|\d{4})-(\d{3})\b
|
847
|
+
elsif /[,.](\d{2}|\d{4})-\d{3}\b/ !~ str &&
|
848
|
+
str.sub!(/\b(\d{2}|\d{4})-(\d{3})\b/, ' ')
|
847
849
|
e.year = $1.to_i
|
848
850
|
e.yday = $2.to_i
|
849
851
|
true
|
850
|
-
elsif /\d-\d{3}\b/
|
851
|
-
str.sub!(/\b-(\d{3})\b
|
852
|
+
elsif /\d-\d{3}\b/ !~ str &&
|
853
|
+
str.sub!(/\b-(\d{3})\b/, ' ')
|
852
854
|
e.yday = $1.to_i
|
853
855
|
true
|
854
856
|
end
|
855
857
|
end
|
856
858
|
|
857
859
|
def self._parse_jis(str, e) # :nodoc:
|
858
|
-
if str.sub!(/\b([mtsh])(\d+)\.(\d+)\.(\d+)/
|
860
|
+
if str.sub!(/\b([mtsh])(\d+)\.(\d+)\.(\d+)/i, ' ')
|
859
861
|
era = { 'm'=>1867,
|
860
862
|
't'=>1911,
|
861
863
|
's'=>1925,
|
@@ -870,46 +872,46 @@ class Date
|
|
870
872
|
|
871
873
|
def self._parse_vms(str, e) # :nodoc:
|
872
874
|
if str.sub!(/('?-?\d+)-(#{Format::ABBR_MONTHS.keys.join('|')})[^-]*
|
873
|
-
-('?-?\d+)/
|
875
|
+
-('?-?\d+)/iox, ' ')
|
874
876
|
s3e(e, $3, Format::ABBR_MONTHS[$2.downcase], $1)
|
875
877
|
true
|
876
878
|
elsif str.sub!(/\b(#{Format::ABBR_MONTHS.keys.join('|')})[^-]*
|
877
|
-
-('?-?\d+)(?:-('?-?\d+))?/
|
879
|
+
-('?-?\d+)(?:-('?-?\d+))?/iox, ' ')
|
878
880
|
s3e(e, $3, Format::ABBR_MONTHS[$1.downcase], $2)
|
879
881
|
true
|
880
882
|
end
|
881
883
|
end
|
882
884
|
|
883
885
|
def self._parse_sla(str, e) # :nodoc:
|
884
|
-
if str.sub!(%r|('?-?\d+)/\s*('?\d+)(?:\D\s*('?-?\d+))
|
886
|
+
if str.sub!(%r|('?-?\d+)/\s*('?\d+)(?:\D\s*('?-?\d+))?|, ' ') # '
|
885
887
|
s3e(e, $1, $2, $3)
|
886
888
|
true
|
887
889
|
end
|
888
890
|
end
|
889
891
|
|
890
892
|
def self._parse_dot(str, e) # :nodoc:
|
891
|
-
if str.sub!(%r|('?-?\d+)\.\s*('?\d+)\.\s*('?-?\d+)
|
893
|
+
if str.sub!(%r|('?-?\d+)\.\s*('?\d+)\.\s*('?-?\d+)|, ' ') # '
|
892
894
|
s3e(e, $1, $2, $3)
|
893
895
|
true
|
894
896
|
end
|
895
897
|
end
|
896
898
|
|
897
899
|
def self._parse_year(str, e) # :nodoc:
|
898
|
-
if str.sub!(/'(\d+)\b
|
900
|
+
if str.sub!(/'(\d+)\b/, ' ')
|
899
901
|
e.year = $1.to_i
|
900
902
|
true
|
901
903
|
end
|
902
904
|
end
|
903
905
|
|
904
906
|
def self._parse_mon(str, e) # :nodoc:
|
905
|
-
if str.sub!(/\b(#{Format::ABBR_MONTHS.keys.join('|')})\S*/
|
907
|
+
if str.sub!(/\b(#{Format::ABBR_MONTHS.keys.join('|')})\S*/io, ' ')
|
906
908
|
e.mon = Format::ABBR_MONTHS[$1.downcase]
|
907
909
|
true
|
908
910
|
end
|
909
911
|
end
|
910
912
|
|
911
913
|
def self._parse_mday(str, e) # :nodoc:
|
912
|
-
if str.sub!(/(\d+)(st|nd|rd|th)\b/
|
914
|
+
if str.sub!(/(\d+)(st|nd|rd|th)\b/i, ' ')
|
913
915
|
e.mday = $1.to_i
|
914
916
|
true
|
915
917
|
end
|
@@ -934,7 +936,7 @@ class Date
|
|
934
936
|
\[[-+]?\d[^\]]*\]
|
935
937
|
)
|
936
938
|
)?
|
937
|
-
/
|
939
|
+
/ix,
|
938
940
|
' ')
|
939
941
|
case $2.size
|
940
942
|
when 2
|
@@ -1060,7 +1062,7 @@ class Date
|
|
1060
1062
|
|
1061
1063
|
e._comp = comp
|
1062
1064
|
|
1063
|
-
str.gsub!(/[^-+',.\/:@[:alnum:]\[\]
|
1065
|
+
str.gsub!(/[^-+',.\/:@[:alnum:]\[\]]+/, ' ')
|
1064
1066
|
|
1065
1067
|
_parse_time(str, e) # || _parse_beat(str, e)
|
1066
1068
|
_parse_day(str, e)
|
@@ -1078,13 +1080,13 @@ class Date
|
|
1078
1080
|
_parse_mday(str, e) ||
|
1079
1081
|
_parse_ddd(str, e)
|
1080
1082
|
|
1081
|
-
if str.sub!(/\b(bc\b|bce\b|b\.c\.|b\.c\.e\.)/
|
1083
|
+
if str.sub!(/\b(bc\b|bce\b|b\.c\.|b\.c\.e\.)/i, ' ')
|
1082
1084
|
if e.year
|
1083
1085
|
e.year = -e.year + 1
|
1084
1086
|
end
|
1085
1087
|
end
|
1086
1088
|
|
1087
|
-
if str.sub!(/\A\s*(\d{1,2})\s*\z
|
1089
|
+
if str.sub!(/\A\s*(\d{1,2})\s*\z/, ' ')
|
1088
1090
|
if e.hour && !e.mday
|
1089
1091
|
v = $1.to_i
|
1090
1092
|
if (1..31) === v
|
@@ -1126,20 +1128,20 @@ class Date
|
|
1126
1128
|
-w-\d)
|
1127
1129
|
(t
|
1128
1130
|
\d{2}:\d{2}(:\d{2}([,.]\d+)?)?
|
1129
|
-
(z|[-+]\d{2}(:?\d{2})?)?)?\s*\z/
|
1131
|
+
(z|[-+]\d{2}(:?\d{2})?)?)?\s*\z/ix =~ str
|
1130
1132
|
_parse(str)
|
1131
1133
|
elsif /\A\s*(([-+]?(\d{2}|\d{4})|--)\d{2}\d{2}|
|
1132
1134
|
([-+]?(\d{2}|\d{4}))?\d{3}|-\d{3}|
|
1133
1135
|
(\d{2}|\d{4})?w\d{2}\d)
|
1134
1136
|
(t?
|
1135
1137
|
\d{2}\d{2}(\d{2}([,.]\d+)?)?
|
1136
|
-
(z|[-+]\d{2}(\d{2})?)?)?\s*\z/
|
1138
|
+
(z|[-+]\d{2}(\d{2})?)?)?\s*\z/ix =~ str
|
1137
1139
|
_parse(str)
|
1138
1140
|
elsif /\A\s*(\d{2}:\d{2}(:\d{2}([,.]\d+)?)?
|
1139
|
-
(z|[-+]\d{2}(:?\d{2})?)?)?\s*\z/
|
1141
|
+
(z|[-+]\d{2}(:?\d{2})?)?)?\s*\z/ix =~ str
|
1140
1142
|
_parse(str)
|
1141
1143
|
elsif /\A\s*(\d{2}\d{2}(\d{2}([,.]\d+)?)?
|
1142
|
-
(z|[-+]\d{2}(\d{2})?)?)?\s*\z/
|
1144
|
+
(z|[-+]\d{2}(\d{2})?)?)?\s*\z/ix =~ str
|
1143
1145
|
_parse(str)
|
1144
1146
|
end
|
1145
1147
|
end
|
@@ -1148,7 +1150,7 @@ class Date
|
|
1148
1150
|
if /\A\s*-?\d{4}-\d{2}-\d{2} # allow minus, anyway
|
1149
1151
|
(t|\s)
|
1150
1152
|
\d{2}:\d{2}:\d{2}(\.\d+)?
|
1151
|
-
(z|[-+]\d{2}:\d{2})\s*\z/
|
1153
|
+
(z|[-+]\d{2}:\d{2})\s*\z/ix =~ str
|
1152
1154
|
_parse(str)
|
1153
1155
|
end
|
1154
1156
|
end
|
@@ -1157,7 +1159,7 @@ class Date
|
|
1157
1159
|
if /\A\s*(-?\d{4,})(?:-(\d{2})(?:-(\d{2}))?)?
|
1158
1160
|
(?:t
|
1159
1161
|
(\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?)?
|
1160
|
-
(z|[-+]\d{2}:\d{2})?\s*\z/
|
1162
|
+
(z|[-+]\d{2}:\d{2})?\s*\z/ix =~ str
|
1161
1163
|
e = Format::Bag.new
|
1162
1164
|
e.year = $1.to_i
|
1163
1165
|
e.mon = $2.to_i if $2
|
@@ -1172,7 +1174,7 @@ class Date
|
|
1172
1174
|
end
|
1173
1175
|
e.to_hash
|
1174
1176
|
elsif /\A\s*(\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?
|
1175
|
-
(z|[-+]\d{2}:\d{2})?\s*\z/
|
1177
|
+
(z|[-+]\d{2}:\d{2})?\s*\z/ix =~ str
|
1176
1178
|
e = Format::Bag.new
|
1177
1179
|
e.hour = $1.to_i if $1
|
1178
1180
|
e.min = $2.to_i if $2
|
@@ -1184,7 +1186,7 @@ class Date
|
|
1184
1186
|
end
|
1185
1187
|
e.to_hash
|
1186
1188
|
elsif /\A\s*(?:--(\d{2})(?:-(\d{2}))?|---(\d{2}))
|
1187
|
-
(z|[-+]\d{2}:\d{2})?\s*\z/
|
1189
|
+
(z|[-+]\d{2}:\d{2})?\s*\z/ix =~ str
|
1188
1190
|
e = Format::Bag.new
|
1189
1191
|
e.mon = $1.to_i if $1
|
1190
1192
|
e.mday = $2.to_i if $2
|
@@ -1203,7 +1205,7 @@ class Date
|
|
1203
1205
|
(?:#{Format::ABBR_MONTHS.keys.join('|')})\s+
|
1204
1206
|
-?(\d{2,})\s+ # allow minus, anyway
|
1205
1207
|
\d{2}:\d{2}(:\d{2})?\s*
|
1206
|
-
(?:[-+]\d{4}|ut|gmt|e[sd]t|c[sd]t|m[sd]t|p[sd]t|[a-ik-z])\s*\z/
|
1208
|
+
(?:[-+]\d{4}|ut|gmt|e[sd]t|c[sd]t|m[sd]t|p[sd]t|[a-ik-z])\s*\z/iox =~ str
|
1207
1209
|
e = _parse(str, false)
|
1208
1210
|
if $1.size < 4
|
1209
1211
|
if e[:year] < 50
|
@@ -1224,20 +1226,20 @@ class Date
|
|
1224
1226
|
(#{Format::ABBR_MONTHS.keys.join('|')})\s+
|
1225
1227
|
-?\d{4}\s+ # allow minus, anyway
|
1226
1228
|
\d{2}:\d{2}:\d{2}\s+
|
1227
|
-
gmt\s*\z/
|
1229
|
+
gmt\s*\z/iox =~ str
|
1228
1230
|
_rfc2822(str)
|
1229
1231
|
elsif /\A\s*(#{Format::DAYS.keys.join('|')})\s*,\s+
|
1230
1232
|
\d{2}\s*-\s*
|
1231
1233
|
(#{Format::ABBR_MONTHS.keys.join('|')})\s*-\s*
|
1232
1234
|
\d{2}\s+
|
1233
1235
|
\d{2}:\d{2}:\d{2}\s+
|
1234
|
-
gmt\s*\z/
|
1236
|
+
gmt\s*\z/iox =~ str
|
1235
1237
|
_parse(str)
|
1236
1238
|
elsif /\A\s*(#{Format::ABBR_DAYS.keys.join('|')})\s+
|
1237
1239
|
(#{Format::ABBR_MONTHS.keys.join('|')})\s+
|
1238
1240
|
\d{1,2}\s+
|
1239
1241
|
\d{2}:\d{2}:\d{2}\s+
|
1240
|
-
\d{4}\s*\z/
|
1242
|
+
\d{4}\s*\z/iox =~ str
|
1241
1243
|
_parse(str)
|
1242
1244
|
end
|
1243
1245
|
end
|
@@ -1246,7 +1248,7 @@ class Date
|
|
1246
1248
|
if /\A\s*[mtsh]?\d{2}\.\d{2}\.\d{2}
|
1247
1249
|
(t
|
1248
1250
|
(\d{2}:\d{2}(:\d{2}([,.]\d*)?)?
|
1249
|
-
(z|[-+]\d{2}(:?\d{2})?)?)?)?\s*\z/
|
1251
|
+
(z|[-+]\d{2}(:?\d{2})?)?)?)?\s*\z/ix =~ str
|
1250
1252
|
if /\A\s*\d/ =~ str
|
1251
1253
|
_parse(str.sub(/\A\s*(\d)/, 'h\1'))
|
1252
1254
|
else
|
data/lib/dateME.rb
CHANGED
data/lib/erb.rb
CHANGED
@@ -10,233 +10,251 @@
|
|
10
10
|
#
|
11
11
|
# You can redistribute it and/or modify it under the same terms as Ruby.
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
#
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
#
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
#
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
#
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
#
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
#
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
#
|
175
|
-
|
176
|
-
|
177
|
-
#
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
#
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
#
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
13
|
+
=begin rdoc
|
14
|
+
= ERB -- Ruby Templating
|
15
|
+
|
16
|
+
== Introduction
|
17
|
+
|
18
|
+
ERB provides an easy to use but powerful templating system for Ruby. Using
|
19
|
+
ERB, actual Ruby code can be added to any plain text document for the
|
20
|
+
purposes of generating document information details and/or flow control.
|
21
|
+
|
22
|
+
A very simple example is this:
|
23
|
+
|
24
|
+
require 'erb'
|
25
|
+
|
26
|
+
x = 42
|
27
|
+
template = ERB.new <<-EOF
|
28
|
+
The value of x is: <%= x %>
|
29
|
+
EOF
|
30
|
+
puts template.result(binding)
|
31
|
+
|
32
|
+
<em>Prints:</em> The value of x is: 42
|
33
|
+
|
34
|
+
More complex examples are given below.
|
35
|
+
|
36
|
+
|
37
|
+
== Recognized Tags
|
38
|
+
|
39
|
+
ERB recognizes certain tags in the provided template and converts them based
|
40
|
+
on the rules below:
|
41
|
+
|
42
|
+
<% Ruby code -- inline with output %>
|
43
|
+
<%= Ruby expression -- replace with result %>
|
44
|
+
<%# comment -- ignored -- useful in testing %>
|
45
|
+
% a line of Ruby code -- treated as <% line %> (optional -- see ERB.new)
|
46
|
+
%% replaced with % if first thing on a line and % processing is used
|
47
|
+
<%% or %%> -- replace with <% or %> respectively
|
48
|
+
|
49
|
+
All other text is passed through ERB filtering unchanged.
|
50
|
+
|
51
|
+
|
52
|
+
== Options
|
53
|
+
|
54
|
+
There are several settings you can change when you use ERB:
|
55
|
+
* the nature of the tags that are recognized;
|
56
|
+
* the value of <tt>$SAFE</tt> under which the template is run;
|
57
|
+
* the binding used to resolve local variables in the template.
|
58
|
+
|
59
|
+
See the ERB.new and ERB#result methods for more detail.
|
60
|
+
|
61
|
+
== Character encodings
|
62
|
+
|
63
|
+
ERB (or ruby code generated by ERB) returns a string in the same
|
64
|
+
character encoding as the input string. When the input string has
|
65
|
+
a magic comment, however, it returns a string in the encoding specified
|
66
|
+
by the magic comment.
|
67
|
+
|
68
|
+
# -*- coding: UTF-8 -*-
|
69
|
+
require 'erb'
|
70
|
+
|
71
|
+
template = ERB.new <<EOF
|
72
|
+
<%#-*- coding: Big5 -*-%>
|
73
|
+
\_\_ENCODING\_\_ is <%= \_\_ENCODING\_\_ %>.
|
74
|
+
EOF
|
75
|
+
puts template.result
|
76
|
+
|
77
|
+
<em>Prints:</em> \_\_ENCODING\_\_ is Big5.
|
78
|
+
|
79
|
+
|
80
|
+
== Examples
|
81
|
+
|
82
|
+
=== Plain Text
|
83
|
+
|
84
|
+
ERB is useful for any generic templating situation. Note that in this example, we use the
|
85
|
+
convenient "% at start of line" tag, and we quote the template literally with
|
86
|
+
<tt>%q{...}</tt> to avoid trouble with the backslash.
|
87
|
+
|
88
|
+
require "erb"
|
89
|
+
|
90
|
+
# Create template.
|
91
|
+
template = %q{
|
92
|
+
From: James Edward Gray II <james@grayproductions.net>
|
93
|
+
To: <%= to %>
|
94
|
+
Subject: Addressing Needs
|
95
|
+
|
96
|
+
<%= to[/\w+/] %>:
|
97
|
+
|
98
|
+
Just wanted to send a quick note assuring that your needs are being
|
99
|
+
addressed.
|
100
|
+
|
101
|
+
I want you to know that my team will keep working on the issues,
|
102
|
+
especially:
|
103
|
+
|
104
|
+
<%# ignore numerous minor requests -- focus on priorities %>
|
105
|
+
% priorities.each do |priority|
|
106
|
+
* <%= priority %>
|
107
|
+
% end
|
108
|
+
|
109
|
+
Thanks for your patience.
|
110
|
+
|
111
|
+
James Edward Gray II
|
112
|
+
}.gsub(/^ /, '')
|
113
|
+
|
114
|
+
message = ERB.new(template, 0, "%<>")
|
115
|
+
|
116
|
+
# Set up template data.
|
117
|
+
to = "Community Spokesman <spokesman@ruby_community.org>"
|
118
|
+
priorities = [ "Run Ruby Quiz",
|
119
|
+
"Document Modules",
|
120
|
+
"Answer Questions on Ruby Talk" ]
|
121
|
+
|
122
|
+
# Produce result.
|
123
|
+
email = message.result
|
124
|
+
puts email
|
125
|
+
|
126
|
+
<i>Generates:</i>
|
127
|
+
|
128
|
+
From: James Edward Gray II <james@grayproductions.net>
|
129
|
+
To: Community Spokesman <spokesman@ruby_community.org>
|
130
|
+
Subject: Addressing Needs
|
131
|
+
|
132
|
+
Community:
|
133
|
+
|
134
|
+
Just wanted to send a quick note assuring that your needs are being addressed.
|
135
|
+
|
136
|
+
I want you to know that my team will keep working on the issues, especially:
|
137
|
+
|
138
|
+
* Run Ruby Quiz
|
139
|
+
* Document Modules
|
140
|
+
* Answer Questions on Ruby Talk
|
141
|
+
|
142
|
+
Thanks for your patience.
|
143
|
+
|
144
|
+
James Edward Gray II
|
145
|
+
|
146
|
+
=== Ruby in HTML
|
147
|
+
|
148
|
+
ERB is often used in <tt>.rhtml</tt> files (HTML with embedded Ruby). Notice the need in
|
149
|
+
this example to provide a special binding when the template is run, so that the instance
|
150
|
+
variables in the Product object can be resolved.
|
151
|
+
|
152
|
+
require "erb"
|
153
|
+
|
154
|
+
# Build template data class.
|
155
|
+
class Product
|
156
|
+
def initialize( code, name, desc, cost )
|
157
|
+
@code = code
|
158
|
+
@name = name
|
159
|
+
@desc = desc
|
160
|
+
@cost = cost
|
161
|
+
|
162
|
+
@features = [ ]
|
163
|
+
end
|
164
|
+
|
165
|
+
def add_feature( feature )
|
166
|
+
@features << feature
|
167
|
+
end
|
168
|
+
|
169
|
+
# Support templating of member data.
|
170
|
+
def get_binding
|
171
|
+
binding
|
172
|
+
end
|
173
|
+
|
174
|
+
# ...
|
175
|
+
end
|
176
|
+
|
177
|
+
# Create template.
|
178
|
+
template = %{
|
179
|
+
<html>
|
180
|
+
<head><title>Ruby Toys -- <%= @name %></title></head>
|
181
|
+
<body>
|
182
|
+
|
183
|
+
<h1><%= @name %> (<%= @code %>)</h1>
|
184
|
+
<p><%= @desc %></p>
|
185
|
+
|
186
|
+
<ul>
|
187
|
+
<% @features.each do |f| %>
|
188
|
+
<li><b><%= f %></b></li>
|
189
|
+
<% end %>
|
190
|
+
</ul>
|
191
|
+
|
192
|
+
<p>
|
193
|
+
<% if @cost < 10 %>
|
194
|
+
<b>Only <%= @cost %>!!!</b>
|
195
|
+
<% else %>
|
196
|
+
Call for a price, today!
|
197
|
+
<% end %>
|
198
|
+
</p>
|
199
|
+
|
200
|
+
</body>
|
201
|
+
</html>
|
202
|
+
}.gsub(/^ /, '')
|
203
|
+
|
204
|
+
rhtml = ERB.new(template)
|
205
|
+
|
206
|
+
# Set up template data.
|
207
|
+
toy = Product.new( "TZ-1002",
|
208
|
+
"Rubysapien",
|
209
|
+
"Geek's Best Friend! Responds to Ruby commands...",
|
210
|
+
999.95 )
|
211
|
+
toy.add_feature("Listens for verbal commands in the Ruby language!")
|
212
|
+
toy.add_feature("Ignores Perl, Java, and all C variants.")
|
213
|
+
toy.add_feature("Karate-Chop Action!!!")
|
214
|
+
toy.add_feature("Matz signature on left leg.")
|
215
|
+
toy.add_feature("Gem studded eyes... Rubies, of course!")
|
216
|
+
|
217
|
+
# Produce result.
|
218
|
+
rhtml.run(toy.get_binding)
|
219
|
+
|
220
|
+
<i>Generates (some blank lines removed):</i>
|
221
|
+
|
222
|
+
<html>
|
223
|
+
<head><title>Ruby Toys -- Rubysapien</title></head>
|
224
|
+
<body>
|
225
|
+
|
226
|
+
<h1>Rubysapien (TZ-1002)</h1>
|
227
|
+
<p>Geek's Best Friend! Responds to Ruby commands...</p>
|
228
|
+
|
229
|
+
<ul>
|
230
|
+
<li><b>Listens for verbal commands in the Ruby language!</b></li>
|
231
|
+
<li><b>Ignores Perl, Java, and all C variants.</b></li>
|
232
|
+
<li><b>Karate-Chop Action!!!</b></li>
|
233
|
+
<li><b>Matz signature on left leg.</b></li>
|
234
|
+
<li><b>Gem studded eyes... Rubies, of course!</b></li>
|
235
|
+
</ul>
|
236
|
+
|
237
|
+
<p>
|
238
|
+
Call for a price, today!
|
239
|
+
</p>
|
240
|
+
|
241
|
+
</body>
|
242
|
+
</html>
|
243
|
+
|
244
|
+
|
245
|
+
== Notes
|
246
|
+
|
247
|
+
There are a variety of templating solutions available in various Ruby projects:
|
248
|
+
* ERB's big brother, eRuby, works the same but is written in C for speed;
|
249
|
+
* Amrita (smart at producing HTML/XML);
|
250
|
+
* cs/Template (written in C for speed);
|
251
|
+
* RDoc, distributed with Ruby, uses its own template engine, which can be reused elsewhere;
|
252
|
+
* and others; search the RAA.
|
253
|
+
|
254
|
+
Rails, the web application framework, uses ERB to create views.
|
255
|
+
=end
|
238
256
|
class ERB
|
239
|
-
Revision = '$Date
|
257
|
+
Revision = '$Date:: 2009-01-17 21:20:08 +0900#$' #'
|
240
258
|
|
241
259
|
# Returns revision information for the erb.rb module.
|
242
260
|
def self.version
|
@@ -304,7 +322,7 @@ class ERB
|
|
304
322
|
def scan(&block)
|
305
323
|
@stag = nil
|
306
324
|
if @percent
|
307
|
-
@src.
|
325
|
+
@src.each_line do |line|
|
308
326
|
percent_line(line, &block)
|
309
327
|
end
|
310
328
|
else
|
@@ -487,10 +505,10 @@ class ERB
|
|
487
505
|
end
|
488
506
|
|
489
507
|
class Buffer # :nodoc:
|
490
|
-
def initialize(compiler)
|
508
|
+
def initialize(compiler, enc=nil)
|
491
509
|
@compiler = compiler
|
492
510
|
@line = []
|
493
|
-
|
511
|
+
@script = enc ? "#coding:#{enc.to_s}\n" : ""
|
494
512
|
@compiler.pre_cmd.each do |x|
|
495
513
|
push(x)
|
496
514
|
end
|
@@ -527,7 +545,11 @@ class ERB
|
|
527
545
|
end
|
528
546
|
|
529
547
|
def compile(s)
|
530
|
-
|
548
|
+
enc = s.encoding
|
549
|
+
raise ArgumentError, "#{enc} is not ASCII compatible" if enc.dummy?
|
550
|
+
s = s.dup.force_encoding("ASCII-8BIT") # don't use constant Enoding::ASCII_8BIT for miniruby
|
551
|
+
enc = detect_magic_comment(s) || enc
|
552
|
+
out = Buffer.new(self, enc)
|
531
553
|
|
532
554
|
content = ''
|
533
555
|
scanner = make_scanner(s)
|
@@ -584,7 +606,7 @@ class ERB
|
|
584
606
|
end
|
585
607
|
out.push("#{@put_cmd} #{content_dump(content)}") if content.size > 0
|
586
608
|
out.close
|
587
|
-
out.script
|
609
|
+
return out.script, enc
|
588
610
|
end
|
589
611
|
|
590
612
|
def prepare_trim_mode(mode)
|
@@ -624,6 +646,18 @@ class ERB
|
|
624
646
|
end
|
625
647
|
attr_reader :percent, :trim_mode
|
626
648
|
attr_accessor :put_cmd, :insert_cmd, :pre_cmd, :post_cmd
|
649
|
+
|
650
|
+
private
|
651
|
+
def detect_magic_comment(s)
|
652
|
+
if /\A<%#(.*)%>/ =~ s or (@percent and /\A%#(.*)/ =~ s)
|
653
|
+
comment = $1
|
654
|
+
comment = $1 if comment[/-\*-\s*(.*?)\s*-*-$/]
|
655
|
+
if %r"coding\s*[=:]\s*([[:alnum:]\-_]+)" =~ comment
|
656
|
+
enc = $1.sub(/-(?:mac|dos|unix)/i, '')
|
657
|
+
enc = Encoding.find(enc)
|
658
|
+
end
|
659
|
+
end
|
660
|
+
end
|
627
661
|
end
|
628
662
|
end
|
629
663
|
|
@@ -699,7 +733,7 @@ class ERB
|
|
699
733
|
@safe_level = safe_level
|
700
734
|
compiler = ERB::Compiler.new(trim_mode)
|
701
735
|
set_eoutvar(compiler, eoutvar)
|
702
|
-
@src = compiler.compile(str)
|
736
|
+
@src, @enc = *compiler.compile(str)
|
703
737
|
@filename = nil
|
704
738
|
end
|
705
739
|
|
@@ -720,12 +754,12 @@ class ERB
|
|
720
754
|
compiler.insert_cmd = "#{eoutvar}.concat"
|
721
755
|
|
722
756
|
cmd = []
|
723
|
-
cmd.push "#{eoutvar} = ''
|
757
|
+
cmd.push "#{eoutvar} = ''"
|
724
758
|
|
725
759
|
compiler.pre_cmd = cmd
|
726
760
|
|
727
761
|
cmd = []
|
728
|
-
cmd.push(eoutvar)
|
762
|
+
cmd.push("#{eoutvar}.force_encoding('utf-8')")
|
729
763
|
|
730
764
|
compiler.post_cmd = cmd
|
731
765
|
end
|
@@ -747,10 +781,10 @@ class ERB
|
|
747
781
|
if @safe_level
|
748
782
|
proc {
|
749
783
|
$SAFE = @safe_level
|
750
|
-
eval(@src, b, (@filename || '(erb)'),
|
784
|
+
eval(@src, b, (@filename || '(erb)'), 0)
|
751
785
|
}.call
|
752
786
|
else
|
753
|
-
eval(@src, b, (@filename || '(erb)'),
|
787
|
+
eval(@src, b, (@filename || '(erb)'), 0)
|
754
788
|
end
|
755
789
|
end
|
756
790
|
|
@@ -762,7 +796,11 @@ class ERB
|
|
762
796
|
# erb.def_method(MyClass, 'render(arg1, arg2)', filename)
|
763
797
|
# print MyClass.new.render('foo', 123)
|
764
798
|
def def_method(mod, methodname, fname='(ERB)')
|
765
|
-
|
799
|
+
src = self.src
|
800
|
+
magic_comment = "#coding:#{@enc}\n"
|
801
|
+
mod.module_eval do
|
802
|
+
eval(magic_comment + "def #{methodname}\n" + src + "\nend\n", binding, fname, -2)
|
803
|
+
end
|
766
804
|
end
|
767
805
|
|
768
806
|
# Create unnamed module, define _methodname_ as instance method of it, and return it.
|
@@ -839,7 +877,9 @@ class ERB
|
|
839
877
|
# Programming%20Ruby%3A%20%20The%20Pragmatic%20Programmer%27s%20Guide
|
840
878
|
#
|
841
879
|
def url_encode(s)
|
842
|
-
s.to_s.gsub(/[^a-zA-Z0-9_\-.]/n){
|
880
|
+
s.to_s.dup.force_encoding("ASCII-8BIT").gsub(/[^a-zA-Z0-9_\-.]/n) {
|
881
|
+
sprintf("%%%02X", $&.unpack("C")[0])
|
882
|
+
}
|
843
883
|
end
|
844
884
|
alias u url_encode
|
845
885
|
module_function :u
|