hobofields 0.8.5 → 0.8.6
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +17 -2
- data/hobofields.gemspec +34 -134
- data/lib/hobo_fields/email_address.rb +1 -1
- data/lib/hobo_fields/field_spec.rb +14 -1
- data/lib/hobo_fields/migration_generator.rb +23 -21
- data/lib/hobo_fields/model_extensions.rb +3 -4
- data/lib/hobo_fields.rb +11 -5
- data/rails_generators/hobo_migration/hobo_migration_generator.rb +11 -10
- data/test/hobofields.rdoctest +22 -20
- data/test/hobofields_api.rdoctest +134 -113
- data/test/migration_generator.rdoctest +204 -174
- data/test/rich_types.rdoctest +134 -100
- data/test/test_hobofield_model_generator.rb +3 -2
- metadata +3 -3
data/test/rich_types.rdoctest
CHANGED
@@ -2,19 +2,48 @@
|
|
2
2
|
|
3
3
|
This doctest describes the rich types bundles with HoboFields, and the process by which you can create and register your own types.
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
Our test requires rails:
|
6
|
+
{.hidden}
|
7
|
+
|
8
|
+
>> require 'rubygems'
|
9
|
+
>> require 'activesupport'
|
10
|
+
>> require 'activerecord'
|
11
|
+
>> require 'actionpack'
|
12
|
+
>> require 'action_view'
|
13
|
+
>> require 'action_controller'
|
14
|
+
{.hidden}
|
15
|
+
|
16
|
+
ActiveRecord 2.3.2 doesn't work very well without a connection, even
|
17
|
+
though we don't need it for this test:
|
18
|
+
{.hidden}
|
19
|
+
|
20
|
+
>> mysql_database = "hobofields_doctest"
|
21
|
+
>> system "mysqladmin --force drop #{mysql_database} 2> /dev/null"
|
22
|
+
>> system("mysqladmin create #{mysql_database}") or raise "could not create database"
|
23
|
+
>> ActiveRecord::Base.establish_connection(:adapter => "mysql",
|
24
|
+
:database => mysql_database,
|
25
|
+
:host => "localhost")
|
26
|
+
{.hidden}
|
27
|
+
|
28
|
+
Some load path manipulation you shouldn't need:
|
29
|
+
{.hidden}
|
30
|
+
|
31
|
+
>> $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), '../../hobofields/lib')
|
32
|
+
>> $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), '../../hobosupport/lib')
|
33
|
+
{.hidden}
|
34
|
+
|
35
|
+
Finally we can require hobofields:
|
36
|
+
{.hidden}
|
37
|
+
|
38
|
+
>> require 'hobosupport'
|
39
|
+
>> require 'hobofields'
|
11
40
|
|
12
41
|
|
13
42
|
## `to_html` method
|
14
43
|
|
15
44
|
The rich types provide a `to_html` method. If you are using the full Hobo stack you don't need to be aware of this unless you're defining your own rich types -- the `<view>` tag uses `to_html` to render a rich type. If you are not using DRYML and Rapid, you can simply call `to_html` in your views, e.g.
|
16
45
|
|
17
|
-
|
46
|
+
<div class="post-body"><%= @post.body.to_html %></div>
|
18
47
|
|
19
48
|
If you ever decide to change from, say, plain text to markdown formatted, your view won't need to change.
|
20
49
|
|
@@ -24,47 +53,47 @@ Defining a rich type is very simple. We'll show an example here before we go thr
|
|
24
53
|
|
25
54
|
This class defines the methods `to_html` to customize the way the type is rendered, and `validate` to provide a custom validation. It also defined the `COLUMN_TYPE` constant to tell the migration generator what underlying type should represent these values in the database.
|
26
55
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
56
|
+
# Loud text always renderd in caps.
|
57
|
+
# It's rude to shout too much so it's not allowed to be
|
58
|
+
# longer than 100 characters
|
59
|
+
class LoudText < String
|
31
60
|
|
32
61
|
COLUMN_TYPE = :string
|
33
62
|
|
34
|
-
|
63
|
+
HoboFields.register_type(:loud, self)
|
35
64
|
|
36
|
-
|
37
|
-
|
38
|
-
|
65
|
+
def validate
|
66
|
+
"is too long (you shouldn't shout that much)" if length > 100
|
67
|
+
end
|
39
68
|
|
40
|
-
|
41
|
-
|
42
|
-
|
69
|
+
def to_html(xmldoctype = true)
|
70
|
+
upcase
|
71
|
+
end
|
43
72
|
|
44
|
-
|
73
|
+
end
|
45
74
|
|
46
75
|
That's all there is to it. Defining `to_html` and `validate` are optional, defining `COLUMN_TYPE` and calling `HoboFields.register_type` are not.
|
47
76
|
|
48
77
|
|
49
78
|
## Bundled types
|
50
79
|
|
51
|
-
Here we'll give a quick overview of the
|
80
|
+
Here we'll give a quick overview of the bundled types. Remember that along with the specific features the type provides (e.g. validation), the simple fact that the type exists is also useful in the other layers of Hobo. For example `HoboFields::PasswordString` doesn't add any features to `String`, but the fact that a specific type exists for passwords means that the view layer can automatically render an `<input type="password">`.
|
52
81
|
|
53
82
|
|
54
83
|
### `HoboFields::EmailAddress`
|
55
84
|
|
56
85
|
Provides validation of correct email address format.
|
57
86
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
87
|
+
>> good = HoboFields::EmailAddress.new("foo@baa.com")
|
88
|
+
>> bad = HoboFields::EmailAddress.new("foo.baa.com")
|
89
|
+
>> !!good.valid?
|
90
|
+
=> true
|
91
|
+
>> good.validate
|
92
|
+
=> nil
|
93
|
+
>> !!bad.valid?
|
94
|
+
=> false
|
95
|
+
>> bad.validate
|
96
|
+
=> "is not valid"
|
68
97
|
|
69
98
|
### `HoboFields::HtmlString`
|
70
99
|
|
@@ -74,45 +103,46 @@ Provides validation of correct email address format.
|
|
74
103
|
|
75
104
|
`HoboFields::MarkdownString` provides a `to_html` that renders markdown syntax into html. It requires the bluecloth gem.
|
76
105
|
|
77
|
-
|
78
|
-
|
79
|
-
|
106
|
+
>> require 'bluecloth'
|
107
|
+
>> markdown = HoboFields::MarkdownString.new %(
|
108
|
+
This is a heading
|
109
|
+
=================
|
80
110
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
111
|
+
And text can be *emphasised*
|
112
|
+
)
|
113
|
+
>> markdown.to_html
|
114
|
+
>> markdown = HoboFields::MarkdownString.new "# This is a heading\n\nAnd text can be *emphasised*\n"
|
115
|
+
=>""
|
116
|
+
<h1>This is a heading</h1>
|
86
117
|
|
87
|
-
|
88
|
-
|
118
|
+
<p>And text can be <em>emphasised</em></p>
|
119
|
+
>>
|
89
120
|
|
90
121
|
### `HoboFields::TextileString`
|
91
122
|
|
92
123
|
`HoboFields::TextileString` provides a `to_html` that renders markdown syntax into html. It requires the redcloth gem.
|
93
124
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
>>
|
125
|
+
>> require 'redcloth'
|
126
|
+
>> textile = HoboFields::TextileString.new %(
|
127
|
+
Text can be _emphasised_
|
128
|
+
)
|
129
|
+
>> textile.to_html
|
130
|
+
=> "<p>Text can be <em>emphasised</em></p>"
|
131
|
+
>>
|
102
132
|
|
103
133
|
### `HoboFields::Text`
|
104
134
|
|
105
135
|
`HoboFields::Text` provides a `to_html` method with HTML escaping and conversion of newlines to `<br />` tags.
|
106
136
|
|
107
|
-
|
137
|
+
>> text = HoboFields::Text.new %(Tom & Jerry
|
108
138
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
139
|
+
Cat & Mouse)
|
140
|
+
>> text.to_html
|
141
|
+
=>
|
142
|
+
"Tom & Jerry<br />
|
143
|
+
<br />
|
144
|
+
Cat & Mouse"
|
145
|
+
>>
|
116
146
|
|
117
147
|
### `HoboFields::PasswordString`
|
118
148
|
|
@@ -123,78 +153,82 @@ Provides validation of correct email address format.
|
|
123
153
|
|
124
154
|
`HoboFields::EnumString` is not a rich type that you use directly. It's a "type generator", rather like Ruby's `Struct`. It's used for the common situation in database driven apps that you want an enumerated type, but it's not worth going to the extra bother of a separate table enumerating the values. For example you could create a type to represent the status of an article:
|
125
155
|
|
126
|
-
|
127
|
-
|
156
|
+
>> ArticleStatus = HoboFields::EnumString.for(:draft, :approved, :published)
|
157
|
+
=> ArticleStatus
|
128
158
|
|
129
159
|
Note that, like all dynamically created classes in Ruby, the class is anonymous until assigned to a constant:
|
130
160
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
161
|
+
>> klass = HoboFields::EnumString.for(:draft, :approved, :published)
|
162
|
+
=> #<EnumString draft approved published>
|
163
|
+
>> AritcleStatus = klass
|
164
|
+
>> ArticleStatus
|
165
|
+
=> ArticleStatus
|
136
166
|
|
137
167
|
The values in the enum are available as class constants:
|
138
168
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
169
|
+
>> ArticleStatus::DRAFT
|
170
|
+
=> "draft"
|
171
|
+
>> ArticleStatus::DRAFT.class
|
172
|
+
=> ArticleStatus
|
143
173
|
|
144
174
|
There are also instance methods to check for each of the values:
|
145
175
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
176
|
+
>> a = ArticleStatus::APPROVED
|
177
|
+
>> a.is_draft?
|
178
|
+
=> false
|
179
|
+
>> a.is_approved?
|
180
|
+
=> true
|
151
181
|
|
152
182
|
They can be constructed from strings:
|
153
183
|
|
154
|
-
|
155
|
-
|
156
|
-
|
184
|
+
>> a = ArticleStatus.new("approved")
|
185
|
+
>> a.is_approved?
|
186
|
+
=> true
|
157
187
|
|
158
188
|
Equality is string equality, with symbols first converted to strings:
|
159
189
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
190
|
+
>> a == "approved"
|
191
|
+
=> true
|
192
|
+
>> a == :approved
|
193
|
+
=> true
|
164
194
|
|
165
195
|
|
166
196
|
Note that every enum you create is a subclass of HoboFields::EnumString:
|
167
197
|
|
168
|
-
|
169
|
-
|
198
|
+
>> a.is_a?(HoboFields::EnumString)
|
199
|
+
=> true
|
170
200
|
|
171
201
|
|
172
202
|
### Using EnumString in your models
|
173
203
|
|
174
204
|
`HoboFields::EnumString` extends the field declaration DSL with a shorthand for creating enum types:
|
175
205
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
206
|
+
>>
|
207
|
+
class Article < ActiveRecord::Base
|
208
|
+
fields do
|
209
|
+
status enum_string(:draft, :approved, :published)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
>> Article.attr_type :status
|
213
|
+
#<EnumString draft approved published>
|
184
214
|
|
185
215
|
Sometimes it's nice to have a proper type name. Here's one way you might go about it:
|
186
216
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
217
|
+
>>
|
218
|
+
class Article < ActiveRecord::Base
|
219
|
+
Status = HoboFields::EnumString.for(:draft, :approved, :published)
|
220
|
+
fields do
|
221
|
+
status Status
|
222
|
+
end
|
223
|
+
end
|
224
|
+
>> Article.attr_type :status
|
225
|
+
=> Article::Status
|
226
|
+
|
227
|
+
## Cleanup
|
228
|
+
{.hidden}
|
229
|
+
|
230
|
+
>> system "mysqladmin --force drop #{mysql_database} 2> /dev/null"
|
231
|
+
{.hidden}
|
198
232
|
|
199
233
|
|
200
234
|
|
@@ -1,7 +1,8 @@
|
|
1
|
-
require
|
2
|
-
|
1
|
+
require 'rubygems'
|
3
2
|
require 'rails_generator'
|
4
3
|
|
4
|
+
require File.join(File.dirname(__FILE__), "test_generator_helper.rb")
|
5
|
+
|
5
6
|
class TestHobofieldModelGenerator < Test::Unit::TestCase
|
6
7
|
include RubiGen::GeneratorTestHelper
|
7
8
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hobofields
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tom Locke
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2009-05-14 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -20,7 +20,7 @@ dependencies:
|
|
20
20
|
requirements:
|
21
21
|
- - "="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: 0.8.
|
23
|
+
version: 0.8.6
|
24
24
|
version:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rails
|