nitro 0.7.0 → 0.8.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.
Files changed (102) hide show
  1. data/AUTHORS +14 -4
  2. data/ChangeLog +192 -1
  3. data/README +50 -6
  4. data/RELEASES +60 -0
  5. data/Rakefile +1 -1
  6. data/bin/cluster.rb +2 -2
  7. data/bin/new_form.rb +1 -1
  8. data/examples/blog/config.rb +5 -4
  9. data/examples/blog/lib/blog.rb +56 -36
  10. data/examples/blog/root/comments.xhtml +5 -2
  11. data/examples/blog/root/entry_form.xhtml +7 -2
  12. data/examples/blog/root/login.xhtml +1 -1
  13. data/examples/blog/root/style.xsl +7 -0
  14. data/examples/og/mock_example.rb +6 -9
  15. data/examples/og/mysql_to_psql.rb +100 -0
  16. data/examples/og/run.rb +8 -17
  17. data/lib/glue.rb +7 -8
  18. data/lib/glue/array.rb +1 -1
  19. data/lib/glue/attribute.rb +86 -0
  20. data/lib/glue/cache.rb +1 -1
  21. data/lib/glue/hash.rb +1 -1
  22. data/lib/glue/inflector.rb +1 -1
  23. data/lib/glue/logger.rb +118 -18
  24. data/lib/glue/mixins.rb +1 -1
  25. data/lib/glue/number.rb +1 -1
  26. data/lib/glue/pool.rb +1 -1
  27. data/lib/glue/property.rb +48 -31
  28. data/lib/glue/string.rb +1 -1
  29. data/lib/glue/time.rb +2 -2
  30. data/lib/glue/validation.rb +400 -0
  31. data/lib/nitro/application.rb +6 -6
  32. data/lib/nitro/builders/form.rb +5 -5
  33. data/lib/nitro/builders/rss.rb +1 -1
  34. data/lib/nitro/builders/xhtml.rb +119 -0
  35. data/lib/nitro/builders/xml.rb +111 -0
  36. data/lib/nitro/config.rb +6 -6
  37. data/lib/nitro/events.rb +1 -1
  38. data/lib/nitro/html.rb +1 -1
  39. data/lib/nitro/markup.rb +15 -20
  40. data/lib/nitro/scaffold.rb +2 -2
  41. data/lib/nitro/server/appserver.rb +3 -3
  42. data/lib/nitro/server/cluster.rb +2 -2
  43. data/lib/nitro/server/dispatcher.rb +2 -2
  44. data/lib/nitro/server/filters/autologin.rb +1 -1
  45. data/lib/nitro/server/fragment.rb +2 -2
  46. data/lib/nitro/server/handlers.rb +2 -2
  47. data/lib/nitro/server/render.rb +17 -15
  48. data/lib/nitro/server/request.rb +6 -6
  49. data/lib/nitro/server/script.rb +2 -2
  50. data/lib/nitro/server/server.rb +2 -2
  51. data/lib/nitro/server/session.rb +6 -6
  52. data/lib/nitro/server/shaders.rb +2 -2
  53. data/lib/nitro/server/webrick.rb +1 -1
  54. data/lib/nitro/sitemap.rb +2 -2
  55. data/lib/nitro/uri.rb +1 -1
  56. data/lib/nitro/version.rb +7 -5
  57. data/lib/og.rb +95 -129
  58. data/lib/og/backend.rb +47 -46
  59. data/lib/og/backends/mysql.rb +64 -63
  60. data/lib/og/backends/psql.rb +73 -72
  61. data/lib/og/connection.rb +7 -8
  62. data/lib/og/enchant.rb +80 -0
  63. data/lib/og/meta.rb +21 -21
  64. data/lib/og/mock.rb +31 -88
  65. data/lib/og/version.rb +6 -5
  66. data/lib/parts/README +9 -0
  67. data/lib/parts/content.rb +23 -9
  68. data/test/glue/tc_attribute.rb +22 -0
  69. data/test/glue/tc_cache.rb +4 -6
  70. data/test/glue/tc_hash.rb +2 -2
  71. data/test/glue/tc_logger.rb +36 -0
  72. data/test/glue/tc_numbers.rb +2 -2
  73. data/test/glue/tc_property_mixins.rb +35 -4
  74. data/test/glue/tc_strings.rb +32 -32
  75. data/test/glue/tc_validation.rb +186 -0
  76. data/test/nitro/builders/tc_xhtml.rb +38 -0
  77. data/test/nitro/builders/tc_xml.rb +47 -0
  78. data/test/nitro/server/tc_request.rb +2 -2
  79. data/test/nitro/server/tc_session.rb +1 -1
  80. data/test/nitro/tc_sitemap.rb +1 -1
  81. data/test/nitro/ui/tc_pager.rb +1 -10
  82. data/test/tc_og.rb +3 -3
  83. data/vendor/blankslate.rb +53 -0
  84. data/vendor/extensions/_base.rb +153 -0
  85. data/vendor/extensions/_template.rb +36 -0
  86. data/vendor/extensions/all.rb +21 -0
  87. data/vendor/extensions/array.rb +68 -0
  88. data/vendor/extensions/binding.rb +224 -0
  89. data/vendor/extensions/class.rb +50 -0
  90. data/vendor/extensions/continuation.rb +71 -0
  91. data/vendor/extensions/enumerable.rb +250 -0
  92. data/vendor/extensions/hash.rb +23 -0
  93. data/vendor/extensions/io.rb +58 -0
  94. data/vendor/extensions/kernel.rb +42 -0
  95. data/vendor/extensions/module.rb +114 -0
  96. data/vendor/extensions/numeric.rb +230 -0
  97. data/vendor/extensions/object.rb +164 -0
  98. data/vendor/extensions/ostruct.rb +41 -0
  99. data/vendor/extensions/string.rb +316 -0
  100. data/vendor/extensions/symbol.rb +28 -0
  101. metadata +35 -13
  102. data/lib/glue/property.rb.old +0 -307
@@ -0,0 +1,9 @@
1
+ = Parts
2
+
3
+ Parts are 'modules of functionality'. This is a higher level concept.
4
+ Examples of parts could be a Forum, a Content/User management system,
5
+ etc.
6
+
7
+ Nitro is a low level framework and does not include functionality parts
8
+ in the standard distribution. Libraries of modules will be available from
9
+ Navel and other vendors.
@@ -1,10 +1,8 @@
1
- # = Content
2
- #
3
- # Content Management Foundation
1
+ # = Content
4
2
  #
5
- # code:
6
- # * George Moschovitis <gm@navel.gr>
3
+ # Content management foundation.
7
4
  #
5
+ # George Moschovitis <gm@navel.gr>
8
6
  # (c) 2004 Navel, all rights reserved.
9
7
  # $Id$
10
8
 
@@ -23,15 +21,31 @@ module BaseContent
23
21
  prop_accessor :body, String, :markup => true, :ui => :textarea
24
22
  end
25
23
 
24
+ # = CreateTime mixin.
25
+ #
26
+ module CreateTime
27
+ prop_accessor :create_time, Time
28
+ prop_accessor :update_time, Time
29
+
30
+ def og_pre_insert(conn)
31
+ @create_time = @update_time = Time.now
32
+ end
33
+
34
+ def og_pre_update(conn)
35
+ @update_time = Time.now
36
+ end
37
+ end
38
+
26
39
  # = Content
27
40
  #
28
41
  # The foundamental Content Unit.
29
- #
30
42
  #--
31
43
  # THINK: rename this to Entity?
32
44
  #++
45
+
33
46
  module Content
34
47
  include N::BaseContent
48
+ prop_accessor :name, String
35
49
  prop_accessor :ctime, Time
36
50
  prop_accessor :mtime, Time
37
51
 
@@ -41,7 +55,7 @@ module Content
41
55
  end
42
56
 
43
57
  # = Category
44
- #
58
+
45
59
  class Category
46
60
  include N::BaseContent
47
61
  end
@@ -49,7 +63,7 @@ end
49
63
  # = ACL
50
64
  #
51
65
  # Unix style permissions.
52
- #
66
+
53
67
  module ACL
54
68
  # bits:
55
69
  # 0, 1, 2: owner read, write, execute
@@ -58,4 +72,4 @@ module ACL
58
72
  prop_accessor :permissions
59
73
  end
60
74
 
61
- end # module
75
+ end
@@ -0,0 +1,22 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
2
+
3
+ require 'test/unit'
4
+ require 'glue/attribute'
5
+
6
+ class TC_Attribute < Test::Unit::TestCase # :nodoc: all
7
+
8
+ class Dummy
9
+ cattr_accessor :value, 'Default'
10
+ cattr_reader :reader, 3
11
+ end
12
+
13
+ def test_attr
14
+ assert_equal 'Default', Dummy.value
15
+ assert_nothing_raised { Dummy.value = 2 }
16
+ assert_equal 2, Dummy.value
17
+
18
+ assert_equal 3, Dummy.reader
19
+ assert_raise(NoMethodError) { Dummy.reader = 19 }
20
+ end
21
+
22
+ end
@@ -1,17 +1,15 @@
1
- # :nodoc: all
2
-
3
1
  require "test/unit"
4
2
  require "glue/cache"
5
3
 
6
- class TC_N_Utils_Cache < Test::Unit::TestCase
4
+ class TC_Glue_Cache < Test::Unit::TestCase
7
5
  # :nodoc: all
8
6
 
9
7
  class Dummy
10
- include G::LRUCache::Item
8
+ include N::LRUCache::Item
11
9
  end
12
10
 
13
11
  def setup
14
- @cache = G::LRUCache.new(maxitems = 3)
12
+ @cache = N::LRUCache.new(maxitems = 3)
15
13
  end
16
14
 
17
15
  def teardown
@@ -44,4 +42,4 @@ class TC_N_Utils_Cache < Test::Unit::TestCase
44
42
  assert_equal(d4, @cache.first)
45
43
  end
46
44
 
47
- end
45
+ end
@@ -7,7 +7,7 @@ class TC_N2_Utils_Cache < Test::Unit::TestCase
7
7
  # :nodoc: all
8
8
 
9
9
  def setup
10
- @safe_cache = G::SafeHash.new(Hash.new)
10
+ @safe_cache = N::SafeHash.new(Hash.new)
11
11
  end
12
12
 
13
13
  def teardown
@@ -35,4 +35,4 @@ class TC_N2_Utils_Cache < Test::Unit::TestCase
35
35
  assert_equal(3, @safe_cache.values.size)
36
36
  end
37
37
 
38
- end
38
+ end
@@ -0,0 +1,36 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
2
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'vendor')
3
+
4
+ require 'stringio'
5
+
6
+ require 'test/unit'
7
+ require 'glue/logger'
8
+
9
+ class TC_Logger < Test::Unit::TestCase # :nodoc: all
10
+
11
+ def setup
12
+ @io = StringIO.new('')
13
+ Logger.set(Logger.new(@io))
14
+ end
15
+
16
+ def test_logger
17
+ Logger.info 'hello'
18
+ assert_equal(" INFO: hello\n", @io.string)
19
+
20
+ # bug: Binding.of_caller thinks Logger is the caller.
21
+ a = 14
22
+ b = 13
23
+ Logger.trace 'a * b'
24
+ assert_equal(" INFO: hello\nDEBUG: a * b = 182\n", @io.string)
25
+
26
+ @io.string = ''
27
+ Logger.debug 'hello'
28
+ assert_equal("DEBUG: hello\n", @io.string)
29
+
30
+ # test logging level.
31
+ Logger.get.level = Logger::INFO
32
+ Logger.debug 'world'
33
+ assert_equal("DEBUG: hello\n", @io.string)
34
+ end
35
+
36
+ end
@@ -13,8 +13,8 @@ class TC_N_NumberUtils < Test::Unit::TestCase
13
13
  end
14
14
 
15
15
  def test_ceil_multiple
16
- assert_equal(20, G::NumberUtils.ceil_multiple(15, 10))
17
- assert_equal(10, G::NumberUtils.ceil_multiple(1, 10))
16
+ assert_equal(20, N::NumberUtils.ceil_multiple(15, 10))
17
+ assert_equal(10, N::NumberUtils.ceil_multiple(1, 10))
18
18
  end
19
19
 
20
20
  end
@@ -1,11 +1,11 @@
1
1
  #! /usr/bin/env ruby
2
2
  # vim:sw=2:ai
3
3
 
4
- # code:
5
- # * Thomas Quas <tquas@yahoo.com>
6
- # * George Moschovitis <gm@navel.gr>
7
- #
4
+ #--
5
+ # Thomas Quas <tquas@yahoo.com>
6
+ # George Moschovitis <gm@navel.gr>
8
7
  # $Id$
8
+ #++
9
9
 
10
10
  $LOAD_PATH.unshift 'lib'
11
11
 
@@ -14,9 +14,16 @@ require 'glue/property'
14
14
 
15
15
  module Mixin
16
16
  prop_accessor :date
17
+ meta :dummy, [123]
17
18
  end
18
19
 
19
20
  class MixedOnly
21
+ include Mixin
22
+ __meta[:dummy] << 5
23
+ __meta[:dummy] << 3
24
+ end
25
+
26
+ class MixedOnly2
20
27
  include Mixin
21
28
  end
22
29
 
@@ -33,6 +40,18 @@ end
33
40
  class Empty
34
41
  end
35
42
 
43
+ class Base
44
+ prop_accessor :date
45
+ meta :dummy, [123]
46
+ end
47
+
48
+ class Child1 < Base
49
+ __meta[:dummy].first << 5
50
+ __meta[:dummy].first << 3
51
+ end
52
+
53
+ class Child2 < Base
54
+ end
36
55
 
37
56
  # Tests auto management.
38
57
  class TC_MixinsTest < ::Test::Unit::TestCase
@@ -59,4 +78,16 @@ class TC_MixinsTest < ::Test::Unit::TestCase
59
78
  assert( obj.respond_to?( :date ) )
60
79
  assert( obj.respond_to?( :dummy ) )
61
80
  end
81
+
82
+ def test_crosspolination
83
+ assert_equal 3, MixedOnly.__meta[:dummy].size
84
+ assert_equal 1, MixedOnly2.__meta[:dummy].size
85
+ assert_equal 1, Mixin.__meta[:dummy].size
86
+ =begin
87
+ gmosx: THINK!
88
+ assert_equal 3, Child1.__meta[:dummy].first.size
89
+ assert_equal 1, Child2.__meta[:dummy].first.size
90
+ assert_equal 1, Base.__meta[:dummy].first.size
91
+ =end
92
+ end
62
93
  end
@@ -11,20 +11,20 @@ class TC_StringUtilsUtils < Test::Unit::TestCase
11
11
  end
12
12
 
13
13
  def test_valid?
14
- assert_equal(true, G::StringUtils.valid?("test"))
15
- assert_equal(false, G::StringUtils.valid?(""))
16
- assert_equal(false, G::StringUtils.valid?(nil))
14
+ assert_equal(true, N::StringUtils.valid?("test"))
15
+ assert_equal(false, N::StringUtils.valid?(""))
16
+ assert_equal(false, N::StringUtils.valid?(nil))
17
17
  end
18
18
 
19
19
  def test_head
20
- assert_equal(nil, G::StringUtils.head(nil))
21
- assert_equal("this...", G::StringUtils.head(@s, 3))
22
- assert_equal("this+++", G::StringUtils.head(@s, 3, false, "+++"))
23
- assert_equal("thi...", G::StringUtils.head(@s, 3, true))
24
- assert_equal("this is...", G::StringUtils.head(@s, 8))
25
- assert_equal(nil, G::StringUtils.head(@s, 0))
26
- assert_equal(nil, G::StringUtils.head(@s, 0, true))
27
- assert_equal("this is...", G::StringUtils.head(@s, 8, true))
20
+ assert_equal(nil, N::StringUtils.head(nil))
21
+ assert_equal("this...", N::StringUtils.head(@s, 3))
22
+ assert_equal("this+++", N::StringUtils.head(@s, 3, false, "+++"))
23
+ assert_equal("thi...", N::StringUtils.head(@s, 3, true))
24
+ assert_equal("this is...", N::StringUtils.head(@s, 8))
25
+ assert_equal(nil, N::StringUtils.head(@s, 0))
26
+ assert_equal(nil, N::StringUtils.head(@s, 0, true))
27
+ assert_equal("this is...", N::StringUtils.head(@s, 8, true))
28
28
  end
29
29
 
30
30
  def test_rewrite
@@ -34,65 +34,65 @@ class TC_StringUtilsUtils < Test::Unit::TestCase
34
34
  [/^games/, "../../games"],
35
35
  [/^tmp/, "/n/theseas/var/tmp"],
36
36
  ]
37
- string = G::StringUtils.rewrite("games/arkanoid.html", rules)
37
+ string = N::StringUtils.rewrite("games/arkanoid.html", rules)
38
38
  assert_equal("../../games/arkanoid.html", string)
39
- string = G::StringUtils.rewrite("tmp/garbage.html", rules)
39
+ string = N::StringUtils.rewrite("tmp/garbage.html", rules)
40
40
  assert_equal("/n/theseas/var/tmp/garbage.html", string)
41
- string = G::StringUtils.rewrite("root/index.html", rules)
41
+ string = N::StringUtils.rewrite("root/index.html", rules)
42
42
  assert_equal("root/index.html", string)
43
- assert_equal(nil, G::StringUtils.rewrite(nil, rules))
44
- assert_equal("", G::StringUtils.rewrite("", rules))
43
+ assert_equal(nil, N::StringUtils.rewrite(nil, rules))
44
+ assert_equal("", N::StringUtils.rewrite("", rules))
45
45
 
46
46
  assert_raises(ArgumentError) {
47
- assert_equal("koko", G::StringUtils.rewrite("koko", nil))
47
+ assert_equal("koko", N::StringUtils.rewrite("koko", nil))
48
48
  }
49
49
 
50
50
  # bug: should keep order
51
- s = G::StringUtils.rewrite("/$/koko.html", rules)
51
+ s = N::StringUtils.rewrite("/$/koko.html", rules)
52
52
  assert_equal("../n1/koko.html", s)
53
53
  end
54
54
 
55
55
  def test_wrap
56
56
  s = "1234567890abcdefghijklmnopqrstu"
57
57
  r = "1234 5678 90ab cdef ghij klmn opqr stu"
58
- assert_equal(r, G::StringUtils::wrap(s, 4, " "))
58
+ assert_equal(r, N::StringUtils::wrap(s, 4, " "))
59
59
 
60
60
  s = "111111111111111111111111111111111111111111111111"
61
61
  r = "1111111111 1111111111 1111111111 1111111111 11111111"
62
- assert_equal(r, G::StringUtils::wrap(s, 10, " "))
62
+ assert_equal(r, N::StringUtils::wrap(s, 10, " "))
63
63
 
64
64
  s = "jackdaws love my big sphinx of quartz"
65
65
  r = "jackdaws love my big sphinx of quartz"
66
- assert_equal(r, G::StringUtils::wrap(s, 10, " "))
66
+ assert_equal(r, N::StringUtils::wrap(s, 10, " "))
67
67
 
68
68
  s = "jackdaws love my big sphinx of quartz"
69
69
  r = "jack daws love my big sphi nx of quar tz"
70
- assert_equal(r, G::StringUtils::wrap(s, 4, " "))
70
+ assert_equal(r, N::StringUtils::wrap(s, 4, " "))
71
71
 
72
72
  s = "jack.daws love my big sphinx of quartz"
73
73
  r = "jack .daw s love my big sphi nx of quar tz"
74
- assert_equal(r, G::StringUtils::wrap(s, 4, " "))
74
+ assert_equal(r, N::StringUtils::wrap(s, 4, " "))
75
75
 
76
- assert_equal("", G::StringUtils::wrap("", 4, " "))
77
- assert_equal(nil, G::StringUtils::wrap(nil, 4, " "))
76
+ assert_equal("", N::StringUtils::wrap("", 4, " "))
77
+ assert_equal(nil, N::StringUtils::wrap(nil, 4, " "))
78
78
  end
79
79
 
80
80
  def test_rationalize_filename
81
- filename = G::StringUtils.rationalize_filename("hello my friend!.gif")
81
+ filename = N::StringUtils.rationalize_filename("hello my friend!.gif")
82
82
  assert_equal("hello-my-friend.gif", filename)
83
- filename = G::StringUtils.rationalize_filename("���� ����.gif")
83
+ filename = N::StringUtils.rationalize_filename("���� ����.gif")
84
84
  assert_equal("pame-pali.gif", filename)
85
- filename = G::StringUtils.rationalize_filename("�� ���.gif")
85
+ filename = N::StringUtils.rationalize_filename("�� ���.gif")
86
86
  assert_equal("ti-les.gif", filename)
87
87
 
88
88
  # bug:
89
- filename = G::StringUtils.rationalize_filename("image-(10).gif")
89
+ filename = N::StringUtils.rationalize_filename("image-(10).gif")
90
90
  assert_equal("image-10.gif", filename)
91
91
  end
92
92
 
93
93
  def test_random_string
94
- s1 = G::StringUtils.random()
95
- s2 = G::StringUtils.random()
94
+ s1 = N::StringUtils.random()
95
+ s2 = N::StringUtils.random()
96
96
  assert_not_equal(s1, s2)
97
97
  assert(s1.size == s2.size)
98
98
  end
@@ -100,4 +100,4 @@ class TC_StringUtilsUtils < Test::Unit::TestCase
100
100
  def teardown
101
101
  @s = nil
102
102
  end
103
- end
103
+ end
@@ -0,0 +1,186 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
2
+
3
+ require 'test/unit'
4
+
5
+ require 'glue'
6
+ require 'glue/validation'
7
+
8
+ class TC_Validation < Test::Unit::TestCase # :nodoc: all
9
+
10
+ # Override the default error message
11
+ N::Validation::Errors.invalid_format = 'INVALID'
12
+
13
+ module Mixin
14
+ prop_accessor :value, String
15
+ validate_format :value, :format => /123/, :msg => 'mixin error'
16
+ end
17
+
18
+ class User
19
+ include Mixin
20
+
21
+ prop_accessor :name, String
22
+ validate_format :name, :format => /Leo/, :msg => 'per class override'
23
+ end
24
+
25
+ class Article
26
+ prop_accessor :name, String
27
+ validate_format :name, :format => /news/
28
+ end
29
+
30
+ class Dummy1
31
+ prop_accessor :test, Fixnum
32
+ prop_accessor :str, String
33
+ validate_value :test, :str
34
+ end
35
+
36
+ class Dummy2
37
+ prop_accessor :password, String
38
+ validate_confirmation :password
39
+ end
40
+
41
+ class Dummy3
42
+ prop_accessor :vmin, String
43
+ validate_length :vmin, :min => 2
44
+
45
+ prop_accessor :vmax, String
46
+ validate_length :vmax, :max => 3, :msg => 'LOOONG'
47
+
48
+ prop_accessor :vran, String
49
+ validate_length :vran, :range => 2..4, :msg_long => 'argh'
50
+
51
+ prop_accessor :vlen, String
52
+ validate_length :vlen, :length => 3, :msg => 'argh'
53
+ end
54
+
55
+ class Dummy4
56
+ prop_accessor :sex, String
57
+ validate_inclusion :sex, :in => %w{ Male Female }, :msg => 'huh?'
58
+
59
+ prop_accessor :age, Fixnum
60
+ validate_inclusion :age, :in => 5..99
61
+ end
62
+
63
+ # bug
64
+
65
+ class NoProp
66
+ include Mixin
67
+ validate_length :value, :min => 3
68
+ end
69
+
70
+ def test_validate_value
71
+ d = Dummy1.new
72
+
73
+ assert !d.valid?
74
+ assert_equal 2, d.errors.count
75
+ d.test = 1
76
+ assert !d.valid?
77
+ assert_equal 1, d.errors.count
78
+ d.str = 'yeah'
79
+ assert d.valid?
80
+ end
81
+
82
+ def test_validate_confirmation
83
+ d = Dummy2.new
84
+
85
+ assert_respond_to d, :password_confirmation
86
+
87
+ d.password = 'hello'
88
+ assert !d.valid?
89
+ d.password_confirmation = 'hel'
90
+ assert !d.valid?
91
+ d.password_confirmation = 'hello'
92
+ assert d.valid?
93
+ end
94
+
95
+ def test_validate_format
96
+ u = User.new
97
+
98
+ u.value = '1234'
99
+
100
+ u.name = 'George'
101
+ assert !u.valid?
102
+
103
+ assert_equal 'per class override', u.errors[:name].first
104
+
105
+ u.name = 'Leonard'
106
+ assert u.valid?
107
+
108
+ a = Article.new
109
+
110
+ a.name = 'In the news'
111
+ assert a.valid?
112
+
113
+ a.name = 'Sports'
114
+ assert !a.valid?
115
+
116
+ assert_equal 1, a.errors.count
117
+ assert_equal 1, a.errors.on(:name).size
118
+ assert_kind_of Array, a.errors[:name]
119
+
120
+ assert_equal 'INVALID', a.errors[:name].first
121
+
122
+ # test mixin
123
+
124
+ u.value = '543'
125
+ assert !u.valid?
126
+ end
127
+
128
+ def test_validate_length
129
+ d = Dummy3.new
130
+
131
+ d.vmin = 'q'
132
+ d.vmax = '2'
133
+ d.vlen = '123'
134
+ d.vran = '123'
135
+
136
+ assert !d.valid?
137
+ assert_equal 'Too short, must be more than 2 characters long', d.errors.on(:vmin).first
138
+ d.vmin = 'longer'
139
+ assert d.valid?
140
+
141
+ d.vmax = 'loooooooooooong'
142
+ assert !d.valid?
143
+ assert_equal 'LOOONG', d.errors.on(:vmax).first
144
+
145
+ d.vmax = nil
146
+ assert !d.valid?
147
+ assert_equal 'No value provided', d.errors.on(:vmax).first
148
+
149
+ d.vlen = '12'
150
+ assert !d.valid?
151
+ assert_equal 'argh', d.errors.on(:vlen).first
152
+
153
+ d.vlen = '1234565'
154
+ assert !d.valid?
155
+
156
+ d.vran = '1'
157
+ assert !d.valid?
158
+ assert_equal 'Too short, must be more than 2 characters long', d.errors.on(:vran).first
159
+
160
+ d.vran = '11111111'
161
+ assert !d.valid?
162
+ assert_equal 'argh', d.errors.on(:vran).first
163
+ end
164
+
165
+ def test_validate_inclusion
166
+ d = Dummy4.new
167
+
168
+ d.sex = 'Alien'
169
+ d.age = 1
170
+
171
+ assert !d.valid?
172
+ assert_equal 2, d.errors.count
173
+
174
+ d.sex = 'Male'
175
+ assert !d.valid?
176
+ assert_equal 1, d.errors.count
177
+
178
+ d.age = 110
179
+ assert !d.valid?
180
+ assert_equal 1, d.errors.count
181
+
182
+ d.age = 90
183
+ assert d.valid?
184
+ end
185
+
186
+ end