rails_errors2html 1.0.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/README.md ADDED
@@ -0,0 +1,115 @@
1
+ --------------------------------
2
+ NAME
3
+ --------------------------------
4
+ rails_errors2html
5
+
6
+ --------------------------------
7
+ DESCRIPTION
8
+ --------------------------------
9
+
10
+ sane html rendering of active_model errors
11
+
12
+ --------------------------------
13
+ SYNOPSIS
14
+ --------------------------------
15
+
16
+ ````erb
17
+
18
+ <%= form_for @post do %>
19
+
20
+ <!-- these are all the same -->
21
+ <%= @post.errors %>
22
+ <%= @post.errors.to_s %>
23
+ <%= @post.errors.to_html %>
24
+
25
+ <% end %>
26
+
27
+ <!-- you can merge errors from different objects -->
28
+
29
+ <%= Errors2Html.to_html(@post.errors, @comment.errors) %>
30
+
31
+ ````
32
+
33
+ you can override the built-in template like so
34
+
35
+ ````ruby
36
+
37
+ # file : config/initializers/errors2html.rb
38
+
39
+ Errors2Html.template = 'shared/errors'
40
+
41
+ ````
42
+
43
+ here is an example template.
44
+
45
+ note that errors are partioned into global and field based errors.
46
+
47
+
48
+ ````erb
49
+ <!-- file : app/views/shared/errors.html.erb -->
50
+
51
+ <div class="errors2html errors-summary">
52
+ <h4 class="errors-caption">Sorry, we encountered some errors:</h4>
53
+
54
+ <% unless errors.global.empty? %>
55
+ <ul class="errors-global-list">
56
+ <% errors.global.each do |message| %>
57
+ <li class="errors-message">
58
+ <%= message %>
59
+ </li>
60
+ <% end %>
61
+ </ul>
62
+ <% end %>
63
+
64
+ <% unless errors.fields.empty? %>
65
+ <dl class="errors-fields-list">
66
+ <%
67
+ errors.fields.each do |key, messages|
68
+ title = Array(key).join(" ").titleize
69
+ %>
70
+ <dt class="errors-title">
71
+ <%= title %>
72
+ </dt>
73
+
74
+ <% Array(messages).each do |message| %>
75
+ <dd class="errors-message">
76
+ <%= message %>
77
+ </dd>
78
+ <% end %>
79
+ <% end %>
80
+ </dl>
81
+ <% end %>
82
+ </div>
83
+ ````
84
+
85
+
86
+ you might want some css like this
87
+
88
+ ````css
89
+
90
+ .errors-summary {
91
+ box-sizing: border-box;
92
+ width: 100%;
93
+ height: auto;
94
+ color: #333;
95
+ background-color: #fffff6;
96
+ padding: 1em;
97
+ }
98
+ .errors-caption {
99
+ font-weight: bold;
100
+ }
101
+ .errors-title {
102
+ }
103
+ .errors-message {
104
+ }
105
+
106
+ ````
107
+
108
+ --------------------------------
109
+ INSTALL
110
+ --------------------------------
111
+
112
+ gem install rails_errors2html
113
+
114
+ gem 'rails_errors2html'
115
+ bundle install
data/Rakefile ADDED
@@ -0,0 +1,446 @@
1
+ This.name =
2
+ "Errors2Html"
3
+
4
+ This.synopsis =
5
+ "<%= form_for @post do %> <%= @post.errors.to_html %>"
6
+
7
+ This.rubyforge_project = 'codeforpeople'
8
+ This.author = "Ara T. Howard"
9
+ This.email = "ara.t.howard@gmail.com"
10
+ This.homepage = "https://github.com/ahoward/#{ This.lib }"
11
+
12
+ This.setup!
13
+
14
+
15
+
16
+ task :default do
17
+ puts((Rake::Task.tasks.map{|task| task.name.gsub(/::/,':')} - ['default']).sort)
18
+ end
19
+
20
+ task :test do
21
+ This.run_tests!
22
+ end
23
+
24
+ namespace :test do
25
+ task(:unit){ This.run_tests!(:unit) }
26
+ task(:functional){ This.run_tests!(:functional) }
27
+ task(:integration){ This.run_tests!(:integration) }
28
+ end
29
+
30
+ def This.run_tests!(which = nil)
31
+ which ||= '**'
32
+ test_dir = File.join(This.dir, "test")
33
+ test_glob ||= File.join(test_dir, "#{ which }/**_test.rb")
34
+ test_rbs = Dir.glob(test_glob).sort
35
+
36
+ div = ('=' * 119)
37
+ line = ('-' * 119)
38
+
39
+ test_rbs.each_with_index do |test_rb, index|
40
+ testno = index + 1
41
+ command = "#{ File.basename(This.ruby) } -I ./lib -I ./test/lib #{ test_rb }"
42
+
43
+ puts
44
+ This.say(div, :color => :cyan, :bold => true)
45
+ This.say("@#{ testno } => ", :bold => true, :method => :print)
46
+ This.say(command, :color => :cyan, :bold => true)
47
+ This.say(line, :color => :cyan, :bold => true)
48
+
49
+ system(command)
50
+
51
+ This.say(line, :color => :cyan, :bold => true)
52
+
53
+ status = $?.exitstatus
54
+
55
+ if status.zero?
56
+ This.say("@#{ testno } <= ", :bold => true, :color => :white, :method => :print)
57
+ This.say("SUCCESS", :color => :green, :bold => true)
58
+ else
59
+ This.say("@#{ testno } <= ", :bold => true, :color => :white, :method => :print)
60
+ This.say("FAILURE", :color => :red, :bold => true)
61
+ end
62
+ This.say(line, :color => :cyan, :bold => true)
63
+
64
+ exit(status) unless status.zero?
65
+ end
66
+ end
67
+
68
+
69
+ task :gemspec do
70
+ ignore_extensions = ['git', 'svn', 'tmp', /sw./, 'bak', 'gem']
71
+ ignore_directories = ['pkg', 'db']
72
+ ignore_files = ['test/log', 'test/db.yml', 'a.rb', 'b.rb'] + Dir['db/*'] + %w'db'
73
+
74
+ shiteless =
75
+ lambda do |list|
76
+ list.delete_if do |entry|
77
+ next unless test(?e, entry)
78
+ extension = File.basename(entry).split(%r/[.]/).last
79
+ ignore_extensions.any?{|ext| ext === extension}
80
+ end
81
+ list.delete_if do |entry|
82
+ next unless test(?d, entry)
83
+ dirname = File.expand_path(entry)
84
+ ignore_directories.any?{|dir| File.expand_path(dir) == dirname}
85
+ end
86
+ list.delete_if do |entry|
87
+ next unless test(?f, entry)
88
+ filename = File.expand_path(entry)
89
+ ignore_files.any?{|file| File.expand_path(file) == filename}
90
+ end
91
+ end
92
+
93
+ lib = This.lib
94
+ object = This.object
95
+ version = This.version
96
+ files = shiteless[Dir::glob("**/**")]
97
+ executables = shiteless[Dir::glob("bin/*")].map{|exe| File.basename(exe)}
98
+ #has_rdoc = true #File.exist?('doc')
99
+ test_files = test(?e, "test/#{ lib }.rb") ? "test/#{ lib }.rb" : nil
100
+ summary = This.summary || This.synopsis || "#{ lib } kicks the ass"
101
+ description = This.description || summary
102
+
103
+ if This.extensions.nil?
104
+ This.extensions = []
105
+ extensions = This.extensions
106
+ %w( Makefile configure extconf.rb ).each do |ext|
107
+ extensions << ext if File.exists?(ext)
108
+ end
109
+ end
110
+ extensions = [extensions].flatten.compact
111
+
112
+ # TODO
113
+ if This.dependencies.nil?
114
+ dependencies = []
115
+ else
116
+ case This.dependencies
117
+ when Hash
118
+ dependencies = This.dependencies.values
119
+ when Array
120
+ dependencies = This.dependencies
121
+ end
122
+ end
123
+
124
+ template =
125
+ if test(?e, 'gemspec.erb')
126
+ This.template_for{ IO.read('gemspec.erb') }
127
+ else
128
+ This.template_for {
129
+ <<-__
130
+ ## <%= lib %>.gemspec
131
+ #
132
+
133
+ Gem::Specification::new do |spec|
134
+ spec.name = <%= lib.inspect %>
135
+ spec.version = <%= version.inspect %>
136
+ spec.platform = Gem::Platform::RUBY
137
+ spec.summary = <%= lib.inspect %>
138
+ spec.description = <%= description.inspect %>
139
+
140
+ spec.files =\n<%= files.sort.pretty_inspect %>
141
+ spec.executables = <%= executables.inspect %>
142
+
143
+ spec.require_path = "lib"
144
+
145
+ spec.test_files = <%= test_files.inspect %>
146
+
147
+ <% dependencies.each do |lib_version| %>
148
+ spec.add_dependency(*<%= Array(lib_version).flatten.inspect %>)
149
+ <% end %>
150
+
151
+ spec.extensions.push(*<%= extensions.inspect %>)
152
+
153
+ spec.rubyforge_project = <%= This.rubyforge_project.inspect %>
154
+ spec.author = <%= This.author.inspect %>
155
+ spec.email = <%= This.email.inspect %>
156
+ spec.homepage = <%= This.homepage.inspect %>
157
+ end
158
+ __
159
+ }
160
+ end
161
+
162
+ FileUtils.mkdir_p(This.pkgdir)
163
+ gemspec = "#{ lib }.gemspec"
164
+ open(gemspec, "w"){|fd| fd.puts(template)}
165
+ This.gemspec = gemspec
166
+ end
167
+
168
+ task :gem => [:clean, :gemspec] do
169
+ FileUtils.mkdir_p(This.pkgdir)
170
+ before = Dir['*.gem']
171
+ cmd = "gem build #{ This.gemspec }"
172
+ `#{ cmd }`
173
+ after = Dir['*.gem']
174
+ gem = ((after - before).first || after.first) or abort('no gem!')
175
+ FileUtils.mv(gem, This.pkgdir)
176
+ This.gem = File.join(This.pkgdir, File.basename(gem))
177
+ end
178
+
179
+ task :readme do
180
+ samples = ''
181
+ prompt = '~ > '
182
+ lib = This.lib
183
+ version = This.version
184
+
185
+ Dir['sample*/*'].sort.each do |sample|
186
+ samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
187
+
188
+ cmd = "cat #{ sample }"
189
+ samples << This.util.indent(prompt + cmd, 2) << "\n\n"
190
+ samples << This.util.indent(`#{ cmd }`, 4) << "\n"
191
+
192
+ cmd = "ruby #{ sample }"
193
+ samples << This.util.indent(prompt + cmd, 2) << "\n\n"
194
+
195
+ cmd = "ruby -e'STDOUT.sync=true; exec %(ruby -I ./lib #{ sample })'"
196
+ samples << This.util.indent(`#{ cmd } 2>&1`, 4) << "\n"
197
+ end
198
+
199
+ template =
200
+ if test(?e, 'readme.erb')
201
+ This.template_for{ IO.read('readme.erb') }
202
+ else
203
+ This.template_for {
204
+ <<-__
205
+ NAME
206
+ #{ lib }
207
+
208
+ DESCRIPTION
209
+
210
+ INSTALL
211
+ gem install #{ lib }
212
+
213
+ SAMPLES
214
+ #{ samples }
215
+ __
216
+ }
217
+ end
218
+
219
+ open("README", "w"){|fd| fd.puts template}
220
+ end
221
+
222
+
223
+ task :clean do
224
+ Dir[File.join(This.pkgdir, '**/**')].each{|entry| FileUtils.rm_rf(entry)}
225
+ end
226
+
227
+
228
+ task :release => [:clean, :gemspec, :gem] do
229
+ gems = Dir[File.join(This.pkgdir, '*.gem')].flatten
230
+ raise "which one? : #{ gems.inspect }" if gems.size > 1
231
+ raise "no gems?" if gems.size < 1
232
+
233
+ cmd = "gem push #{ This.gem }"
234
+ puts cmd
235
+ puts
236
+ system(cmd)
237
+ abort("cmd(#{ cmd }) failed with (#{ $?.inspect })") unless $?.exitstatus.zero?
238
+
239
+ #cmd = "rubyforge login && rubyforge add_release #{ This.rubyforge_project } #{ This.lib } #{ This.version } #{ This.gem }"
240
+ #puts cmd
241
+ #puts
242
+ #system(cmd)
243
+ #abort("cmd(#{ cmd }) failed with (#{ $?.inspect })") unless $?.exitstatus.zero?
244
+ end
245
+
246
+
247
+
248
+
249
+
250
+ BEGIN {
251
+ # support for this rakefile
252
+ #
253
+ $VERBOSE = nil
254
+
255
+ require 'erb'
256
+ require 'fileutils'
257
+ require 'rbconfig'
258
+ require 'pp'
259
+
260
+ # cache a bunch of stuff about this rakefile/environment
261
+ #
262
+
263
+ This =
264
+ Class.new(Hash) do
265
+
266
+ def method_missing(method, *args, &block)
267
+ if method.to_s =~ /=/
268
+ key = method.to_s.chomp('=')
269
+ value = block ? block : args.shift
270
+ self[key] = value
271
+ else
272
+ key = method.to_s
273
+ if block
274
+ value = block
275
+ self[key] = value
276
+ else
277
+ value = self[key]
278
+
279
+ if value.respond_to?(:call)
280
+ self[key] = value.call()
281
+ else
282
+ value
283
+ end
284
+ end
285
+ end
286
+ end
287
+
288
+ def inspect
289
+ expand!
290
+ PP.pp(self, '')
291
+ end
292
+
293
+ def expand!
294
+ keys.each do |key|
295
+ value = self[key]
296
+ if value.respond_to?(:call)
297
+ self[key] = value.call()
298
+ end
299
+ end
300
+ end
301
+
302
+ end.new()
303
+
304
+ This.file = File.expand_path(__FILE__)
305
+ This.dir = File.dirname(This.file)
306
+ This.pkgdir = File.join(This.dir, 'pkg')
307
+
308
+ # defaults
309
+ #
310
+ This.lib do
311
+ File.basename(Dir.pwd)
312
+ end
313
+
314
+ def This.setup!
315
+ begin
316
+ require "./lib/#{ This.lib }"
317
+ rescue LoadError
318
+ abort("could not load #{ This.lib }")
319
+ end
320
+ end
321
+
322
+ This.name do
323
+ This.name = This.lib.capitalize
324
+ end
325
+
326
+ This.object do
327
+ begin
328
+ This.object = eval(This.name)
329
+ rescue Object
330
+ abort("could not determine object from #{ This.name }")
331
+ end
332
+ end
333
+
334
+ This.version do
335
+ This.object.send(:version)
336
+ end
337
+
338
+ This.dependencies do
339
+ if This.object.respond_to?(:dependencies)
340
+ This.object.dependencies
341
+ end
342
+ end
343
+
344
+ This.ruby do
345
+ c = Config::CONFIG
346
+ bindir = c["bindir"] || c['BINDIR']
347
+ ruby_install_name = c['ruby_install_name'] || c['RUBY_INSTALL_NAME'] || 'ruby'
348
+ ruby_ext = c['EXEEXT'] || ''
349
+ File.join(bindir, (ruby_install_name + ruby_ext))
350
+ end
351
+
352
+ # some utils
353
+ #
354
+ This.util = Module.new do
355
+ def indent(s, n = 2)
356
+ s = unindent(s)
357
+ ws = ' ' * n
358
+ s.gsub(%r/^/, ws)
359
+ end
360
+
361
+ def unindent(s)
362
+ indent = nil
363
+ s.each_line do |line|
364
+ next if line =~ %r/^\s*$/
365
+ indent = line[%r/^\s*/] and break
366
+ end
367
+ indent ? s.gsub(%r/^#{ indent }/, "") : s
368
+ end
369
+
370
+ extend self
371
+ end
372
+
373
+ # template support
374
+ #
375
+ This.template = Class.new do
376
+ def initialize(&block)
377
+ @block = block
378
+ @template = block.call.to_s
379
+ end
380
+
381
+ def expand(b=nil)
382
+ ERB.new(This.util.unindent(@template)).result((b||@block).binding)
383
+ end
384
+
385
+ alias_method 'to_s', 'expand'
386
+ end
387
+
388
+ def This.template_for(*args, &block)
389
+ This.template.new(*args, &block)
390
+ end
391
+
392
+ # colored console output support
393
+ #
394
+ This.ansi = {
395
+ :clear => "\e[0m",
396
+ :reset => "\e[0m",
397
+ :erase_line => "\e[K",
398
+ :erase_char => "\e[P",
399
+ :bold => "\e[1m",
400
+ :dark => "\e[2m",
401
+ :underline => "\e[4m",
402
+ :underscore => "\e[4m",
403
+ :blink => "\e[5m",
404
+ :reverse => "\e[7m",
405
+ :concealed => "\e[8m",
406
+ :black => "\e[30m",
407
+ :red => "\e[31m",
408
+ :green => "\e[32m",
409
+ :yellow => "\e[33m",
410
+ :blue => "\e[34m",
411
+ :magenta => "\e[35m",
412
+ :cyan => "\e[36m",
413
+ :white => "\e[37m",
414
+ :on_black => "\e[40m",
415
+ :on_red => "\e[41m",
416
+ :on_green => "\e[42m",
417
+ :on_yellow => "\e[43m",
418
+ :on_blue => "\e[44m",
419
+ :on_magenta => "\e[45m",
420
+ :on_cyan => "\e[46m",
421
+ :on_white => "\e[47m"
422
+ }
423
+
424
+ def This.say(something, *args)
425
+ options = args.last.is_a?(Hash) ? args.pop : {}
426
+ options[:color] = args.shift.to_s.to_sym unless args.empty?
427
+ keys = options.keys
428
+ keys.each{|key| options[key.to_s.to_sym] = options.delete(key)}
429
+
430
+ color = options[:color]
431
+ bold = options.has_key?(:bold)
432
+
433
+ parts = [something]
434
+ parts.unshift(This.ansi[color]) if color
435
+ parts.unshift(This.ansi[:bold]) if bold
436
+ parts.push(This.ansi[:clear]) if parts.size > 1
437
+
438
+ method = options[:method] || :puts
439
+
440
+ Kernel.send(method, parts.join)
441
+ end
442
+
443
+ # always run out of the project dir
444
+ #
445
+ Dir.chdir(This.dir)
446
+ }
@@ -0,0 +1,120 @@
1
+ module Errors2Html
2
+ VERSION = '1.0.0'
3
+
4
+ def Errors2Html.version
5
+ Errors2Html::VERSION
6
+ end
7
+
8
+ def Errors2Html.dependencies
9
+ {
10
+ 'map' => [ 'map' , ' >= 6.2.0' ],
11
+ 'rails_view' => [ 'rails_view' , ' >= 1.0.1' ]
12
+ }
13
+ end
14
+
15
+ begin
16
+ require 'rubygems'
17
+ rescue LoadError
18
+ nil
19
+ end
20
+
21
+ Errors2Html.dependencies.each do |lib, dependency|
22
+ gem(*dependency) if defined?(gem)
23
+ require(lib)
24
+ end
25
+
26
+ class << Errors2Html
27
+ attr_accessor :template
28
+ end
29
+
30
+ def Errors2Html.to_html(*args)
31
+ args.flatten!
32
+ args.compact!
33
+
34
+ at_least_one_error = false
35
+
36
+ errors = Map.new
37
+ errors[:global] = []
38
+ errors[:fields] = {}
39
+
40
+ args.each do |e|
41
+ e.each do |key, messages|
42
+ key = key.to_s
43
+
44
+ Array(messages).each do |message|
45
+ at_least_one_error = true
46
+
47
+ list =
48
+ if key =~ /\A(?:[*]|base)\Z/iomx
49
+ errors[:global] ||= []
50
+ else
51
+ errors[:fields][key] ||= []
52
+ end
53
+
54
+ list.push(message.to_s).uniq!
55
+ end
56
+ end
57
+ end
58
+
59
+ return "" unless at_least_one_error
60
+
61
+ locals = {
62
+ :errors => errors,
63
+ :global_errors => errors.global,
64
+ :fields_errors => errors.fields
65
+ }
66
+
67
+ if template
68
+ View.render(:template => template, :locals => locals)
69
+ else
70
+ View.render(:inline => Template, :locals => locals)
71
+ end
72
+ end
73
+
74
+ def to_html
75
+ Errors2Html.to_html(self)
76
+ end
77
+
78
+ def to_s
79
+ to_html
80
+ end
81
+
82
+ Template = <<-erb
83
+ <div class="errors2html errors-summary">
84
+ <h4 class="errors-caption">Sorry, we encountered some errors:</h4>
85
+
86
+ <% unless errors.global.empty? %>
87
+ <ul class="errors-global-list">
88
+ <% errors.global.each do |message| %>
89
+ <li class="errors-message">
90
+ <%= message %>
91
+ </li>
92
+ <% end %>
93
+ </ul>
94
+ <% end %>
95
+
96
+ <% unless errors.fields.empty? %>
97
+ <dl class="errors-fields-list">
98
+ <%
99
+ errors.fields.each do |key, messages|
100
+ title = Array(key).join(" ").titleize
101
+ %>
102
+ <dt class="errors-title">
103
+ <%= title %>
104
+ </dt>
105
+
106
+ <% Array(messages).each do |message| %>
107
+ <dd class="errors-message">
108
+ <%= message %>
109
+ </dd>
110
+ <% end %>
111
+ <% end %>
112
+ </dl>
113
+ <% end %>
114
+ </div>
115
+ erb
116
+ end
117
+
118
+ require 'active_model' unless defined?(ActiveModel)
119
+ ActiveModel::Errors.send(:include, Errors2Html)
120
+
@@ -0,0 +1,39 @@
1
+ ## rails_errors2html.gemspec
2
+ #
3
+
4
+ Gem::Specification::new do |spec|
5
+ spec.name = "rails_errors2html"
6
+ spec.version = "1.0.0"
7
+ spec.platform = Gem::Platform::RUBY
8
+ spec.summary = "rails_errors2html"
9
+ spec.description = "<%= form_for @post do %> <%= @post.errors.to_html %>"
10
+
11
+ spec.files =
12
+ ["README.md",
13
+ "Rakefile",
14
+ "lib",
15
+ "lib/rails_errors2html.rb",
16
+ "rails_errors2html.gemspec",
17
+ "test",
18
+ "test/rails_errors2html_test.rb",
19
+ "test/testing.rb"]
20
+
21
+ spec.executables = []
22
+
23
+ spec.require_path = "lib"
24
+
25
+ spec.test_files = nil
26
+
27
+
28
+ spec.add_dependency(*["map", " >= 6.2.0"])
29
+
30
+ spec.add_dependency(*["rails_view", " >= 1.0.1"])
31
+
32
+
33
+ spec.extensions.push(*[])
34
+
35
+ spec.rubyforge_project = "codeforpeople"
36
+ spec.author = "Ara T. Howard"
37
+ spec.email = "ara.t.howard@gmail.com"
38
+ spec.homepage = "https://github.com/ahoward/rails_errors2html"
39
+ end
@@ -0,0 +1,44 @@
1
+ require_relative '../lib/rails_errors2html.rb'
2
+ require_relative '../test/testing.rb'
3
+
4
+ Testing Errors2Html do
5
+
6
+ testing 'simple rendering' do
7
+ errors = ActiveModel::Errors.new(base = Map.new)
8
+ errors.add :base, 'error on base'
9
+ errors.add :field, 'error on field'
10
+
11
+ expected = <<-__
12
+ <div class="errors2html errors-summary">
13
+ <h4 class="errors-caption">Sorry, we encountered some errors:</h4>
14
+
15
+ <ul class="errors-global-list">
16
+ <li class="errors-message">
17
+ error on base
18
+ </li>
19
+ </ul>
20
+
21
+ <dl class="errors-fields-list">
22
+ <dt class="errors-title">
23
+ Field
24
+ </dt>
25
+
26
+ <dd class="errors-message">
27
+ error on field
28
+ </dd>
29
+ </dl>
30
+ </div>
31
+ __
32
+
33
+ compress = proc do |string|
34
+ end
35
+
36
+ assert{ compress(errors.to_html) == compress(expected) }
37
+ assert{ compress(errors) == compress(expected) }
38
+ end
39
+
40
+ protected
41
+ def compress(*strings)
42
+ strings.flatten.compact.join.gsub(/\s+/, '')
43
+ end
44
+ end
data/test/testing.rb ADDED
@@ -0,0 +1,197 @@
1
+ # -*- encoding : utf-8 -*-
2
+ #
3
+ require 'test/unit'
4
+
5
+ testdir = File.expand_path(File.dirname(__FILE__))
6
+ rootdir = File.dirname(testdir)
7
+ libdir = File.join(rootdir, 'lib')
8
+
9
+ STDOUT.sync = true
10
+
11
+ $:.unshift(testdir) unless $:.include?(testdir)
12
+ $:.unshift(libdir) unless $:.include?(libdir)
13
+ $:.unshift(rootdir) unless $:.include?(rootdir)
14
+
15
+ class Testing
16
+ class Slug < ::String
17
+ def Slug.for(*args)
18
+ string = args.flatten.compact.join('-')
19
+ words = string.to_s.scan(%r/\w+/)
20
+ words.map!{|word| word.gsub %r/[^0-9a-zA-Z_-]/, ''}
21
+ words.delete_if{|word| word.nil? or word.strip.empty?}
22
+ new(words.join('-').downcase)
23
+ end
24
+ end
25
+
26
+ class Context
27
+ attr_accessor :name
28
+
29
+ def initialize(name, *args)
30
+ @name = name
31
+ end
32
+
33
+ def to_s
34
+ Slug.for(name)
35
+ end
36
+ end
37
+ end
38
+
39
+ def Testing(*args, &block)
40
+ Class.new(::Test::Unit::TestCase) do
41
+
42
+ ## class methods
43
+ #
44
+ class << self
45
+ def contexts
46
+ @contexts ||= []
47
+ end
48
+
49
+ def context(*args, &block)
50
+ return contexts.last if(args.empty? and block.nil?)
51
+
52
+ context = Testing::Context.new(*args)
53
+ contexts.push(context)
54
+
55
+ begin
56
+ block.call(context)
57
+ ensure
58
+ contexts.pop
59
+ end
60
+ end
61
+
62
+ def slug_for(*args)
63
+ string = [context, args].flatten.compact.join('-')
64
+ words = string.to_s.scan(%r/\w+/)
65
+ words.map!{|word| word.gsub %r/[^0-9a-zA-Z_-]/, ''}
66
+ words.delete_if{|word| word.nil? or word.strip.empty?}
67
+ words.join('-').downcase.sub(/_$/, '')
68
+ end
69
+
70
+ def name() const_get(:Name) end
71
+
72
+ def testno()
73
+ '%05d' % (@testno ||= 0)
74
+ ensure
75
+ @testno += 1
76
+ end
77
+
78
+ def testing(*args, &block)
79
+ method = ["test", testno, slug_for(*args)].delete_if{|part| part.empty?}.join('_')
80
+ define_method(method, &block)
81
+ end
82
+
83
+ def test(*args, &block)
84
+ testing(*args, &block)
85
+ end
86
+
87
+ def setup(&block)
88
+ define_method(:setup, &block) if block
89
+ end
90
+
91
+ def teardown(&block)
92
+ define_method(:teardown, &block) if block
93
+ end
94
+
95
+ def prepare(&block)
96
+ @prepare ||= []
97
+ @prepare.push(block) if block
98
+ @prepare
99
+ end
100
+
101
+ def cleanup(&block)
102
+ @cleanup ||= []
103
+ @cleanup.push(block) if block
104
+ @cleanup
105
+ end
106
+ end
107
+
108
+ ## configure the subclass!
109
+ #
110
+ const_set(:Testno, '0')
111
+ slug = slug_for(*args).gsub(%r/-/,'_')
112
+ name = ['TESTING', '%03d' % const_get(:Testno), slug].delete_if{|part| part.empty?}.join('_')
113
+ name = name.upcase!
114
+ const_set(:Name, name)
115
+ const_set(:Missing, Object.new.freeze)
116
+
117
+ ## instance methods
118
+ #
119
+ alias_method('__assert__', 'assert')
120
+
121
+ def assert(*args, &block)
122
+ if args.size == 1 and args.first.is_a?(Hash)
123
+ options = args.first
124
+ expected = getopt(:expected, options){ missing }
125
+ actual = getopt(:actual, options){ missing }
126
+ if expected == missing and actual == missing
127
+ actual, expected, *ignored = options.to_a.flatten
128
+ end
129
+ expected = expected.call() if expected.respond_to?(:call)
130
+ actual = actual.call() if actual.respond_to?(:call)
131
+ assert_equal(expected, actual)
132
+ end
133
+
134
+ if block
135
+ label = "assert(#{ args.join(' ') })"
136
+ result = nil
137
+ assert_nothing_raised{ result = block.call }
138
+ __assert__(result, label)
139
+ result
140
+ else
141
+ result = args.shift
142
+ label = "assert(#{ args.join(' ') })"
143
+ __assert__(result, label)
144
+ result
145
+ end
146
+ end
147
+
148
+ def missing
149
+ self.class.const_get(:Missing)
150
+ end
151
+
152
+ def getopt(opt, hash, options = nil, &block)
153
+ [opt.to_s, opt.to_s.to_sym].each do |key|
154
+ return hash[key] if hash.has_key?(key)
155
+ end
156
+ default =
157
+ if block
158
+ block.call
159
+ else
160
+ options.is_a?(Hash) ? options[:default] : nil
161
+ end
162
+ return default
163
+ end
164
+
165
+ def subclass_of exception
166
+ class << exception
167
+ def ==(other) super or self > other end
168
+ end
169
+ exception
170
+ end
171
+
172
+ ##
173
+ #
174
+ module_eval(&block)
175
+
176
+ self.setup()
177
+ self.prepare.each{|b| b.call()}
178
+
179
+ at_exit{
180
+ self.teardown()
181
+ self.cleanup.each{|b| b.call()}
182
+ }
183
+
184
+ self
185
+ end
186
+ end
187
+
188
+
189
+ if $0 == __FILE__
190
+
191
+ Testing 'Testing' do
192
+ testing('foo'){ assert true }
193
+ test{ assert true }
194
+ p instance_methods.grep(/test/)
195
+ end
196
+
197
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails_errors2html
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ara T. Howard
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: map
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 6.2.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 6.2.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: rails_view
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 1.0.1
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 1.0.1
46
+ description: <%= form_for @post do %> <%= @post.errors.to_html %>
47
+ email: ara.t.howard@gmail.com
48
+ executables: []
49
+ extensions: []
50
+ extra_rdoc_files: []
51
+ files:
52
+ - README.md
53
+ - Rakefile
54
+ - lib/rails_errors2html.rb
55
+ - rails_errors2html.gemspec
56
+ - test/rails_errors2html_test.rb
57
+ - test/testing.rb
58
+ homepage: https://github.com/ahoward/rails_errors2html
59
+ licenses: []
60
+ post_install_message:
61
+ rdoc_options: []
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirements: []
77
+ rubyforge_project: codeforpeople
78
+ rubygems_version: 1.8.24
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: rails_errors2html
82
+ test_files: []