demeler 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/CHANGELOG.md +11 -1
- data/README.md +262 -67
- data/lib/demeler.rb +33 -22
- data/lib/demeler/version.rb +1 -1
- data/notes +33 -3
- data/spec/demeler.rb +14 -3
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0c386f96ecc1bd387757913d8c06df79c31a705
|
4
|
+
data.tar.gz: bed41140c85456d8d829e8b9919bbc70b9a7d838
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a75c02f4294c9da6b8fe6159c274c05a793c2ce2a31c90815f677723082b12d1117c0366543cc0fb08878442510d1d348af1520d3a344ec8aed1b53941109aa
|
7
|
+
data.tar.gz: c6eff11ee04f5a3b2f95f5938b5ed3f3ade2de6b158141bb3ce79f7683b2b38a738888fb7264f92ebdee7d0ac01713ac08f88645b81dddcddc7970cb696e23ed
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,2 +1,12 @@
|
|
1
|
+
# 1.0.1
|
2
|
+
* Changed the `clear` method to return self so that clear can be chained.
|
3
|
+
* Corrected some of the comments above individual methods.
|
4
|
+
* Made some corrections and additions to the README.
|
5
|
+
* Made `write_html` a private method because it's only used by `to_html`.
|
6
|
+
* Added an argument to `build` and `initialize` to allow a session variable to be passed through.
|
7
|
+
* Corrected a problem with the `select` control in that the attributes were not being applied.
|
8
|
+
* Added a variable to `build` and `initialize` to be able to pass through a user argument. I called it `session` because that's what it would commonly be used for, but you could pass anything and access it in your Demeler code. For example, if you needed session _and_ some other variables, you would just pass them all in a Hash, including session.
|
9
|
+
|
10
|
+
|
1
11
|
# 1.0.0
|
2
|
-
* Initial version.
|
12
|
+
* Initial version.
|
data/README.md
CHANGED
@@ -1,9 +1,16 @@
|
|
1
1
|
# Demeler Gem
|
2
2
|
|
3
|
-
|
3
|
+
**Copyright (c) 2017 Michael J Welch, Ph.D. <mjwelchphd@gmail.com>**
|
4
|
+
|
5
|
+
_NOTE: I appologize that the documentation isn't better than it is, but I'm running way behind in my work trying to make this into a gem in order to preserve and share it._
|
6
|
+
|
4
7
|
All files in this distribution are subject to the terms of the MIT license.
|
5
8
|
|
6
|
-
This gem builds HTML code on-the-fly. The advantages are:
|
9
|
+
This gem builds HTML code on-the-fly. The advantages are:
|
10
|
+
|
11
|
+
1. HTML code is properly formed with respect to tags and nesting;
|
12
|
+
2. the code is dynamic, i.e., values from an object containing data (if used) are automatically extracted and inserted into the resultant HTML code; and
|
13
|
+
3. if there are errors, the error message is generated also.
|
7
14
|
|
8
15
|
The French word démêler means "to unravel," and that's sort of what this gem does. Démêler is pronounced "day-meh-lay." It unravels your inputs to form HTML code. The diacritical marks are not used in the name for compatibility.
|
9
16
|
|
@@ -12,8 +19,8 @@ This class doesn't depend on any particular framework, but I use it with Ruby Se
|
|
12
19
|
|
13
20
|
## The Demeler gem generates HTML from three inputs:
|
14
21
|
* A Ruby source file you write;
|
15
|
-
* A Hash-based object you provide, like Sequel::Model objects
|
16
|
-
* An errors list inside the Hash-based object
|
22
|
+
* A Hash-based object you provide, like Sequel::Model objects; and
|
23
|
+
* An errors list inside the Hash-based object.
|
17
24
|
|
18
25
|
Let's start with the most basic form, a simple example. Run `irb` and enter this:
|
19
26
|
|
@@ -187,7 +194,7 @@ Any attribute can be added in this way.
|
|
187
194
|
|
188
195
|
## Embedding text between tags on one line
|
189
196
|
|
190
|
-
Normally, anything in brackets {} is embedded like this
|
197
|
+
Normally, anything in brackets {} is embedded like this; `p{"Some text."}` yields:
|
191
198
|
|
192
199
|
```html
|
193
200
|
<!-- begin generated output -->
|
@@ -197,7 +204,7 @@ Normally, anything in brackets {} is embedded like this: `p{"Some text."}` yield
|
|
197
204
|
<!-- end generated output -->
|
198
205
|
```
|
199
206
|
|
200
|
-
You can make it come out on one line by using the
|
207
|
+
You can make it come out on one line by using the `:text` attribute; `p :text=>"Some text."` yields:
|
201
208
|
|
202
209
|
```html
|
203
210
|
<!-- begin generated output -->
|
@@ -205,7 +212,7 @@ You can make it come out on one line by using the :text attribute: `p :text=>"So
|
|
205
212
|
<!-- end generated output -->
|
206
213
|
```
|
207
214
|
|
208
|
-
In most cases, this can be achieved just by eliminating the {}
|
215
|
+
In most cases, this can be achieved just by eliminating the {}; `p "Some text." yields:
|
209
216
|
|
210
217
|
```html
|
211
218
|
<!-- begin generated output -->
|
@@ -215,101 +222,289 @@ In most cases, this can be achieved just by eliminating the {}: `p "Some text."
|
|
215
222
|
|
216
223
|
This is because the solo string is converted to a :text argument automatically.
|
217
224
|
|
225
|
+
## How to create an input control
|
218
226
|
|
219
|
-
|
227
|
+
A standard input control is just a tag and options. Take the `text` control, for example.
|
220
228
|
|
221
|
-
|
229
|
+
`text :username, :size=>30, :value=>"joe.e.razsolli"` => `<input name="username" size="30" value="joe.e.razsolli" type="text" />`
|
222
230
|
|
223
|
-
|
231
|
+
The button, color, date, datetime_local, email, hidden, image, month, number, password, range, reset, search, submit, tel, text, time, url, and week tags all work the that way.
|
224
232
|
|
225
|
-
|
233
|
+
The textarea control, on the other hand, puts it's value between the tags, so it uses a :text attribute instead of a :value attribute.
|
226
234
|
|
227
|
-
|
235
|
+
`textarea :username, :size=>30, :text="joe.e.razsolli` => `<textarea name="username" size="30">joe.e.razsolli</textarea>`
|
228
236
|
|
229
|
-
|
237
|
+
The textarea tag can take its text from a block, also.
|
230
238
|
|
231
|
-
|
239
|
+
`textarea(:username, :size=>30) { "joe.e.razsolli" }` => `<textarea name="username" size="30">joe.e.razsolli</textarea>`
|
232
240
|
|
233
|
-
|
234
|
-
puts (Demeler.build(nil, true) do
|
235
|
-
div :class=>"div-class" do
|
236
|
-
"..."
|
237
|
-
end
|
238
|
-
end)
|
241
|
+
Notice for the block form, you have to enclose the parameters to the textarea call in parenthesis.
|
239
242
|
|
240
|
-
|
241
|
-
<div class="div-class">
|
242
|
-
...
|
243
|
-
</div>
|
244
|
-
<!-- end generated output -->
|
245
|
-
```
|
246
|
-
#### tag
|
243
|
+
## How to Create a Checkbox, Radio, or Select Control
|
247
244
|
|
248
|
-
|
245
|
+
For a checkbox, radio, or select control, use the formats below.
|
249
246
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
247
|
+
`checkbox(:vehicle, opts, :volvo=>"Volvo", :saab=>"Saab", :mercedes=>"Mercedes", :audi=>"Audi")` =>
|
248
|
+
```html
|
249
|
+
<input name="vehicle[1]" type="checkbox" value="volvo">Volvo</input>
|
250
|
+
<input name="vehicle[2]" type="checkbox" value="saab">Saab</input>
|
251
|
+
<input name="vehicle[3]" type="checkbox" value="mercedes">Mercedes</input>
|
252
|
+
<input name="vehicle[4]" type="checkbox" value="audi">Audi</input>
|
253
|
+
```
|
254
254
|
|
255
|
-
|
256
|
-
|
257
|
-
|
255
|
+
`radio(:vehicle, opts, :volvo=>"Volvo", :saab=>"Saab", :mercedes=>"Mercedes", :audi=>"Audi")` =>
|
256
|
+
```html
|
257
|
+
<input name="vehicle" type="radio" value="volvo">Volvo</input>
|
258
|
+
<input name="vehicle" type="radio" value="saab">Saab</input>
|
259
|
+
<input name="vehicle" type="radio" value="mercedes">Mercedes</input>
|
260
|
+
<input name="vehicle" type="radio" value="audi">Audi</input>
|
258
261
|
```
|
259
262
|
|
260
|
-
|
263
|
+
`select(:vehicle, opts, :volvo=>"Volvo", :saab=>"Saab", :mercedes=>"Mercedes", :audi=>"Audi")` =>
|
264
|
+
```html
|
265
|
+
<select name="vehicle">
|
266
|
+
<option value="volvo">Volvo</option>
|
267
|
+
<option value="saab">Saab</option>
|
268
|
+
<option value="mercedes">Mercedes</option>
|
269
|
+
<option value="audi">Audi</option>
|
270
|
+
</select>
|
271
|
+
```
|
261
272
|
|
262
|
-
|
273
|
+
Opts represents a Hash with tag attributes.
|
263
274
|
|
264
|
-
```ruby
|
265
|
-
puts (Demeler.build(nil, true) do
|
266
|
-
p "This is a paragraph."
|
267
|
-
end)
|
268
275
|
|
269
|
-
<!-- begin generated output -->
|
270
|
-
<p>This is a paragraph.</p>
|
271
|
-
<!-- end generated output -->
|
272
|
-
```
|
273
276
|
|
274
|
-
|
277
|
+
## Reference Guide
|
278
|
+
|
279
|
+
### def self.build(obj=nil, gen_html=false, session={}, &block)
|
280
|
+
|
281
|
+
This is the main Demeler call used to build your HTML. This call uses your code in the block, so it makes no sense to call `build` without a block.
|
282
|
+
|
283
|
+
Name | Type | Value
|
284
|
+
---- | ---- | -----
|
285
|
+
obj | Hash+ | An object to use to get values and error messages.
|
286
|
+
gen_html | Boolean | Create formatted HTML (true), or compact HTML (false: default).
|
287
|
+
session | Hash | A variable meant to pass a session in a web server, but you can use it for passing any other value as well. _This value is for the caller's use and is not used by Demeler._
|
288
|
+
block | Proc | The block with your code.
|
289
|
+
|
290
|
+
### def initialize(obj=nil, session={}, &block)
|
291
|
+
|
292
|
+
Initialize sets up the initial conditions in Demeler, and is called by `new`.
|
293
|
+
|
294
|
+
Name | Type | Value
|
295
|
+
---- | ---- | -----
|
296
|
+
obj | Hash+ | An object to use to get values and error messages.
|
297
|
+
session | Hash | A variable meant to pass a session in a web server, but you can use it for passing any other value as well. _This value is for the caller's use and is not used by Demeler._
|
298
|
+
block | Proc | The block with your code.
|
299
|
+
|
300
|
+
### def clear
|
301
|
+
|
302
|
+
Clear resets the output variables in order to reuse Demeler without having to reinstantiate it.
|
303
|
+
|
304
|
+
### method_missing(meth, *args, &block)
|
305
|
+
|
306
|
+
This is a Ruby method which catches method calls that have no real method. For example, when you code a `body` tag, there is no method in Demeler to handle that, so it is caught be `missing_method`. Missing_method passes the call along to `tag_generator` to be coded.
|
307
|
+
|
308
|
+
Name | Type | Value
|
309
|
+
---- | ---- | -----
|
310
|
+
meth | Symbol | The name of the missing method being caught.
|
311
|
+
*args | Array | An array of arguments from the call that was intercepted. Tag_generator will try to make sense of them.
|
312
|
+
block | Proc | The block with your code.
|
313
|
+
|
314
|
+
### def p(*args, &block)
|
315
|
+
|
316
|
+
The `p` method is a workaround to make 'p' tags work in `build`.
|
317
|
+
|
318
|
+
Name | Type | Value
|
319
|
+
---- | ---- | -----
|
320
|
+
*args | Array | An array of arguments from the call that was intercepted. Tag_generator will try to make sense of them.
|
321
|
+
block | Proc | The block with your code.
|
322
|
+
|
323
|
+
### def alink(text, args={})
|
324
|
+
|
325
|
+
The `alink` method is a shortcut to build an `a` tag. You could also write a `a` tag like so:
|
275
326
|
|
276
327
|
```ruby
|
277
|
-
|
278
|
-
|
279
|
-
end
|
328
|
+
Demeler.build do
|
329
|
+
a(:href=>"/") { "Home" }
|
330
|
+
end
|
331
|
+
```
|
280
332
|
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
333
|
+
but the alink method is a shortcut. Code it like this:
|
334
|
+
|
335
|
+
```ruby
|
336
|
+
Demeler.build do
|
337
|
+
alink("Home", :href=>"/")
|
338
|
+
end
|
285
339
|
```
|
286
340
|
|
287
|
-
|
341
|
+
Yes, I know. Six of one, half-dozen of another. It had a legacy beginning, and I kept it in here.
|
288
342
|
|
289
|
-
|
343
|
+
Name | Type | Value
|
344
|
+
---- | ---- | -----
|
345
|
+
text | String | The text to be inserted into the tag.
|
346
|
+
*args | Hash | An hash of attributes which must include the :href attribute.
|
290
347
|
|
291
|
-
|
348
|
+
### def checkbox(name, opts, values)
|
292
349
|
|
293
|
-
|
350
|
+
This is a shortcut to build `checkbox` tags. A properly formed check box is created for each value in the `values` list. If the form object has one or more values set, those boxes will be checked.
|
294
351
|
|
352
|
+
Each check box name will begin with `name` and have a number added, beginning with 1.
|
295
353
|
|
296
|
-
|
354
|
+
Name | Type | Value
|
355
|
+
---- | ---- | -----
|
356
|
+
name | Symbol | The name of the control. It will be prepended with a number.
|
357
|
+
opts | Hash | The attributes and options for the control.
|
358
|
+
values | Hash | The names and values of the check boxes.
|
297
359
|
|
298
|
-
|
360
|
+
The data value in the form object may be a String, Array or Hash. If this is a string, the values are comma separated. If this is an array, the elements are the values. If this is a hash, the values (right hand side of each pair) are the values.
|
299
361
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
text :username
|
304
|
-
end)
|
362
|
+
### radio(name, opts, values)
|
363
|
+
|
364
|
+
This is a shortcut to build radio buttons. All the radio buttons in a set are named the same, and only vary in value. Unlike the checkbox control, the radio control only has one value at a time. The opts are applied to each radio button.
|
305
365
|
|
366
|
+
Name | Type | Value
|
367
|
+
---- | ---- | -----
|
368
|
+
name | Symbol | The name of the control.
|
369
|
+
opts | Hash | The attributes and options for the control.
|
370
|
+
values | Hash | The names and values of the radio boxes.
|
371
|
+
|
372
|
+
The data value in the form object may be a String, Array or Hash. If this is a string, the values are comma separated. If this is an array, the elements are the values. If this is a hash, the values (right hand side of each pair) are the values.
|
373
|
+
|
374
|
+
### def select(name, opts, values)
|
375
|
+
|
376
|
+
The select control is unique in that it has `select` tags surrounding a list of `option` tags. Based on the attributes (opts), you can create a pure dropdown list, or a scrolling list. See https://www.w3schools.com for more info on HTML.
|
377
|
+
|
378
|
+
Name | Type | Value
|
379
|
+
---- | ---- | -----
|
380
|
+
name | Symbol | The name of the control.
|
381
|
+
opts | Hash | The attributes and options for the control.
|
382
|
+
values | Hash | The names and values of the radio boxes.
|
383
|
+
|
384
|
+
The data value in the form object may be a String, Array or Hash. If this is a string, the values are comma separated. If this is an array, the elements are the values. If this is a hash, the values (right hand side of each pair) are the values.
|
385
|
+
|
386
|
+
### def submit(text, opts={})
|
387
|
+
|
388
|
+
The submit shortcut creates a `input` control of type 'submit'.
|
389
|
+
|
390
|
+
Name | Type | Value
|
391
|
+
---- | ---- | -----
|
392
|
+
text | String | The text displayed on the face of the button.
|
393
|
+
opts | Hash | The attributes and options for the control.
|
394
|
+
|
395
|
+
### def tag_generator(meth, args=[], &block)
|
396
|
+
|
397
|
+
You don't normally call `tag_generator` (although you can if you wish to). Tag_generator has many forms which are documented one by one below.
|
398
|
+
|
399
|
+
### def tag_generator(meth, opts, &block)
|
400
|
+
|
401
|
+
This form is used for most simple input controls.
|
402
|
+
|
403
|
+
Name | Type | Value
|
404
|
+
---- | ---- | -----
|
405
|
+
meth | Symbol | The method, i.e., the tag name: :p, :br, :input, etc.
|
406
|
+
opts | Hash | The attributes, i.e., :class="user-class", etc.
|
407
|
+
block | Proc | The block
|
408
|
+
|
409
|
+
### def tag_generator(meth, &block)
|
410
|
+
|
411
|
+
This form is used for most simple controls which have no options specified.
|
412
|
+
|
413
|
+
Name | Type | Value
|
414
|
+
---- | ---- | -----
|
415
|
+
meth | Symbol | The method, i.e., the tag name: :p, :br, :input, etc.
|
416
|
+
block | Proc | The block
|
417
|
+
|
418
|
+
### def tag_generator(meth, [text], &block)
|
419
|
+
|
420
|
+
This form is used for controls which consist of text between opening and closing tags.
|
421
|
+
|
422
|
+
Name | Type | Value
|
423
|
+
---- | ---- | -----
|
424
|
+
meth | Symbol | The method, i.e., the tag name: :p, :br, :input, etc.
|
425
|
+
text | String | The string becomes the :text=>string attribute.
|
426
|
+
block | Proc | The block
|
427
|
+
|
428
|
+
### def tag_generator(meth, [name], &block)
|
429
|
+
|
430
|
+
This form is used for simple input controls which have only a name, i.e., `text(:username)`. You would use a control like this with a form object probably.
|
431
|
+
|
432
|
+
Name | Type | Value
|
433
|
+
---- | ---- | -----
|
434
|
+
meth | Symbol | The method, i.e., the tag name: :p, :br, :input, etc.
|
435
|
+
name | Symbol | The name of the control.
|
436
|
+
block | Proc | The block
|
437
|
+
|
438
|
+
### def tag_generator(meth, [opts], &block)
|
439
|
+
|
440
|
+
This form is used for simple input controls which have only a name, i.e., `text(:username)`. You would use a control like this with a form object probably. This option is equivalent to the first option which is the same except the opts are not in an array.
|
441
|
+
|
442
|
+
Name | Type | Value
|
443
|
+
---- | ---- | -----
|
444
|
+
meth | Symbol | The method, i.e., the tag name: :p, :br, :input, etc.
|
445
|
+
opts | Hash | The attributes, i.e., :class="user-class", etc.
|
446
|
+
block | Proc | The block
|
447
|
+
|
448
|
+
### def tag_generator(meth, [name, opts], &block)
|
449
|
+
|
450
|
+
This form is the same as the preceeding one, except the name is specified seperately for convenience.
|
451
|
+
|
452
|
+
Name | Type | Value
|
453
|
+
---- | ---- | -----
|
454
|
+
meth | Symbol | The method, i.e., the tag name: :p, :br, :input, etc.
|
455
|
+
name | Symbol | The name of the control.
|
456
|
+
opts | Hash | The attributes, i.e., :class="user-class", etc.
|
457
|
+
block | Proc | The block
|
458
|
+
|
459
|
+
### def tag_generator(meth, [name, text], &block)
|
460
|
+
|
461
|
+
This form is the same as the preceeding one, except the text is placed between opening and closing tages, but if the meth is 'label', a `for="text"` attribute is created; otherwise, a `name="text"`. (This is the call that implements `label` tags, obviously.)
|
462
|
+
|
463
|
+
Name | Type | Value
|
464
|
+
---- | ---- | -----
|
465
|
+
meth | Symbol | The method, i.e., the tag name: :p, :br, :input, etc.
|
466
|
+
name | Symbol | The name of the control.
|
467
|
+
text | String | The string becomes the :text=>string attribute.
|
468
|
+
block | Proc | The block
|
469
|
+
|
470
|
+
## How the form object is harvested
|
471
|
+
|
472
|
+
For Demeler to pick up data from the form object and automatically set `value` attributes, you need to have the following conditions:
|
473
|
+
|
474
|
+
* There must be a `name` attribute;
|
475
|
+
* There must be a form object given in the `build` or `new` method;
|
476
|
+
* The form object must contain the named key in the object's hash; and
|
477
|
+
* The retrieved data must not be `nil` and, if the retrieved data is a String, it must not be `empty`.
|
478
|
+
|
479
|
+
The data will create a:
|
480
|
+
|
481
|
+
* (for `textarea`) :text attribute; or
|
482
|
+
* (for all others) :value attribute.
|
483
|
+
|
484
|
+
## Outputting the HTML
|
485
|
+
|
486
|
+
There are two ways to output the HTML: formatted and compressed.
|
487
|
+
|
488
|
+
Formatted code is human readable, like this:
|
489
|
+
|
490
|
+
```html
|
306
491
|
<!-- begin generated output -->
|
307
|
-
<
|
308
|
-
<
|
492
|
+
<select name="vehicle" class="x">
|
493
|
+
<option value="volvo">Volvo</option>
|
494
|
+
<option value="saab">Saab</option>
|
495
|
+
<option value="mercedes">Mercedes</option>
|
496
|
+
<option value="audi">Audi</option>
|
497
|
+
</select>
|
309
498
|
<!-- end generated output -->
|
310
499
|
```
|
311
500
|
|
312
|
-
|
501
|
+
whereas compressed code looks like this:
|
502
|
+
|
503
|
+
```html
|
504
|
+
<select name=\"vehicle\" class=\"x\"><option value=\"volvo\">Volvo</option><option value=\"saab\">Saab</option><option value=\"mercedes\">Mercedes</option><option value=\"audi\">Audi</option></select>
|
505
|
+
```
|
506
|
+
|
507
|
+
Compressed HTML is faster to generate, and is recommended for production.
|
313
508
|
|
314
509
|
## A Bigger Example of a Demeler Script
|
315
510
|
|
data/lib/demeler.rb
CHANGED
@@ -21,7 +21,7 @@
|
|
21
21
|
# Ruby Sequel.
|
22
22
|
|
23
23
|
class Demeler
|
24
|
-
attr_reader :out, :obj
|
24
|
+
attr_reader :out, :obj, :session
|
25
25
|
|
26
26
|
# These calls are effectively generated in the same way as 'text' input
|
27
27
|
# tags. Method_missing just does a substitution to implement them.
|
@@ -33,10 +33,13 @@ class Demeler
|
|
33
33
|
# The default way to start building your markup.
|
34
34
|
# Takes a block and returns the markup.
|
35
35
|
#
|
36
|
+
# @param [object] obj a Sequel::Model object, or Hash object with an added 'errors' field.
|
37
|
+
# @param [boolean] gen_html A flag to control final output: true=>formatted, false=>compressed.
|
38
|
+
# @param [Hash] session The session variable from the caller, although it can be anything because Demeler doesn't use it.
|
36
39
|
# @param [Proc] block
|
37
40
|
#
|
38
|
-
def self.build(obj=nil, gen_html=false, &block)
|
39
|
-
demeler = self.new(obj, &block)
|
41
|
+
def self.build(obj=nil, gen_html=false, session={}, &block)
|
42
|
+
demeler = self.new(obj, session, &block)
|
40
43
|
if gen_html then demeler.to_html else demeler.to_s end
|
41
44
|
end
|
42
45
|
|
@@ -48,6 +51,8 @@ class Demeler
|
|
48
51
|
# A note of warning: you'll get extra spaces in textareas if you use .to_html.
|
49
52
|
#
|
50
53
|
# @param [object] obj--a Sequel::Model object, or Hash object with an added 'errors' field.
|
54
|
+
# @param [Hash] session The session variable from the caller, although it can be anything because Demeler doesn't use it.
|
55
|
+
# @param [Proc] block
|
51
56
|
#
|
52
57
|
# To use this without Sequel, you can use an object like this:
|
53
58
|
# class Obj<Hash
|
@@ -57,9 +62,10 @@ class Demeler
|
|
57
62
|
# end
|
58
63
|
# end
|
59
64
|
#
|
60
|
-
def initialize(obj=nil, &block)
|
65
|
+
def initialize(obj=nil, session={}, &block)
|
61
66
|
raise ArgumentError.new("The object passed to Demeler must have an errors field containing a Hash") if obj && !defined?(obj.errors)
|
62
67
|
@obj = obj
|
68
|
+
@session = session
|
63
69
|
clear
|
64
70
|
instance_eval(&block) if block_given?
|
65
71
|
end
|
@@ -71,6 +77,7 @@ class Demeler
|
|
71
77
|
@level = 0
|
72
78
|
@out = []
|
73
79
|
@labels = []
|
80
|
+
self
|
74
81
|
end
|
75
82
|
|
76
83
|
##
|
@@ -103,13 +110,14 @@ class Demeler
|
|
103
110
|
end
|
104
111
|
|
105
112
|
##
|
106
|
-
# The #alink method simplyfies the generation of <a>...</a> tags
|
113
|
+
# The #alink method simplyfies the generation of <a>...</a> tags.
|
107
114
|
#
|
115
|
+
# @param [String] The link line to be displayed
|
108
116
|
# @param [Array] args Extra arguments that should be processed before
|
109
117
|
# creating the 'a' tag.
|
110
118
|
# @param [Proc] block
|
111
119
|
#
|
112
|
-
def alink(text, args={})
|
120
|
+
def alink(text, args={})Hash
|
113
121
|
raise ArgumentError.new("In Demeler#alink, expected String for argument 1, text") if !text.kind_of?(String)
|
114
122
|
raise ArgumentError.new("In Demeler#alink, expected Hash for argument 2, opts") if !args.kind_of?(Hash)
|
115
123
|
raise ArgumentError.new("In Demeler#alink, expected an href option in opts") if !args[:href]
|
@@ -162,10 +170,12 @@ class Demeler
|
|
162
170
|
##
|
163
171
|
# The radio shortcut
|
164
172
|
#
|
165
|
-
# @param [
|
173
|
+
# @param [Symbol] name Base Name of the control (numbers 1..n will be added)
|
174
|
+
# @param [Hash] opts Attributes for the control
|
175
|
+
# @param [Hash] value=>nomenclature pairs
|
166
176
|
#
|
167
177
|
# @example
|
168
|
-
# g.radio(:
|
178
|
+
# g.radio(:vehicle, {}, :volvo=>"Volvo", :saab=>"Saab", :mercedes=>"Mercedes", :audi=>"Audi")
|
169
179
|
#
|
170
180
|
# @note: first argument is the :name; without the name, the radio control won't work
|
171
181
|
#
|
@@ -190,7 +200,7 @@ class Demeler
|
|
190
200
|
#
|
191
201
|
# @param [Symbol] name The name of the SELECT statement
|
192
202
|
# @param [Hash] opts Options for the SELECT statement
|
193
|
-
# @param [Hash]
|
203
|
+
# @param [Hash] values A list of :name=>value pairs the control will have
|
194
204
|
#
|
195
205
|
# @example
|
196
206
|
# g.select(:vehicle, {}, :volvo=>"Volvo", :saab=>"Saab", :mercedes=>"Mercedes", :audi=>"Audi")
|
@@ -198,14 +208,13 @@ class Demeler
|
|
198
208
|
# @note: first argument is the :name=>"vehicle"
|
199
209
|
# @note: the second argument is a Hash or nil
|
200
210
|
#
|
201
|
-
def select(name,
|
211
|
+
def select(name, args, values)
|
202
212
|
raise ArgumentError.new("In Demeler#select, expected Symbol for argument 1, name") if !name.kind_of?(Symbol)
|
203
|
-
raise ArgumentError.new("In Demeler#select, expected Hash for argument 2,
|
213
|
+
raise ArgumentError.new("In Demeler#select, expected Hash for argument 2, args") if !args.kind_of?(Hash)
|
204
214
|
raise ArgumentError.new("In Demeler#select, expected Hash for argument 3, values") if !values.kind_of?(Hash)
|
205
|
-
opts = {:name=>name}
|
206
|
-
opts.merge!(opts)
|
215
|
+
opts = {:name=>name}.merge(args)
|
207
216
|
data = if @obj then @obj[name] else nil end
|
208
|
-
tag_generator(:select,
|
217
|
+
tag_generator(:select, opts) do
|
209
218
|
values.each do |value,nomenclature|
|
210
219
|
sets = {:value=>value}
|
211
220
|
sets[:selected] = 'true' if data==value.to_s
|
@@ -357,14 +366,6 @@ class Demeler
|
|
357
366
|
@out.join
|
358
367
|
end
|
359
368
|
|
360
|
-
##
|
361
|
-
# This method is part of #to_html below.
|
362
|
-
#
|
363
|
-
def write_html(indent,part)
|
364
|
-
# "<!-- #{indent} --> #{' '*(if indent<0 then 0 else indent end)}#{part}\n"
|
365
|
-
"#{' '*(if indent<0 then 0 else indent end)}#{part}\n"
|
366
|
-
end
|
367
|
-
|
368
369
|
##
|
369
370
|
# Method for converting the results of Demeler to a
|
370
371
|
# human readable string. This isn't recommended for
|
@@ -398,4 +399,14 @@ class Demeler
|
|
398
399
|
return html
|
399
400
|
end # to_html
|
400
401
|
|
402
|
+
private
|
403
|
+
|
404
|
+
##
|
405
|
+
# This method is part of #to_html.
|
406
|
+
#
|
407
|
+
def write_html(indent,part)
|
408
|
+
# "<!-- #{indent} --> #{' '*(if indent<0 then 0 else indent end)}#{part}\n"
|
409
|
+
"#{' '*(if indent<0 then 0 else indent end)}#{part}\n"
|
410
|
+
end
|
411
|
+
|
401
412
|
end
|
data/lib/demeler/version.rb
CHANGED
data/notes
CHANGED
@@ -1,13 +1,43 @@
|
|
1
1
|
cd ~/demeler-gem
|
2
|
-
gem build demeler.gemspec
|
3
2
|
|
4
|
-
|
3
|
+
#----------------------------------------
|
5
4
|
|
5
|
+
# To build the gem and install locally
|
6
|
+
gem build demeler.gemspec
|
7
|
+
sudo gem uninstall demeler
|
6
8
|
sudo gem install demeler
|
7
9
|
|
8
10
|
#----------------------------------------
|
9
11
|
|
10
12
|
To run tests (with 'bacon' installed):
|
11
|
-
|
12
13
|
bacon -Ilib spec/demeler.rb
|
13
14
|
|
15
|
+
#----------------------------------------
|
16
|
+
|
17
|
+
# To set globals in Git
|
18
|
+
git config --global user.name "Michael J. Welch, Ph.D."
|
19
|
+
git config --global user.email mjwelchphd@gmail.com
|
20
|
+
git config --global core.editor xed
|
21
|
+
git config --list
|
22
|
+
|
23
|
+
#----------------------------------------
|
24
|
+
|
25
|
+
# To push up to GitHub
|
26
|
+
git remote add origin https://github.com/mjwelchphd/demeler.git
|
27
|
+
git push -u origin master
|
28
|
+
|
29
|
+
#----------------------------------------
|
30
|
+
|
31
|
+
# To upload the gem to rubygems.org
|
32
|
+
gem push demeler-1.0.1.gem
|
33
|
+
|
34
|
+
#----------------------------------------
|
35
|
+
|
36
|
+
# To run 'irb' for testing
|
37
|
+
cd ~/demeler-gem
|
38
|
+
irb -Ilib
|
39
|
+
|
40
|
+
require_relative 'lib/demeler'
|
41
|
+
load './lib/demeler.rb'
|
42
|
+
|
43
|
+
|
data/spec/demeler.rb
CHANGED
@@ -57,8 +57,8 @@ describe "Simple Demeler with no Object" do
|
|
57
57
|
|
58
58
|
it "should be a plain select control" do
|
59
59
|
@d.clear
|
60
|
-
@d.select(:vehicle, {}, :volvo=>"Volvo", :saab=>"Saab", :mercedes=>"Mercedes", :audi=>"Audi")
|
61
|
-
@d.to_s.should.equal "<select name=\"vehicle\"><option value=\"volvo\">Volvo</option><option value=\"saab\">Saab</option><option value=\"mercedes\">Mercedes</option><option value=\"audi\">Audi</option></select>"
|
60
|
+
@d.select(:vehicle, {:class=>"select-class"}, :volvo=>"Volvo", :saab=>"Saab", :mercedes=>"Mercedes", :audi=>"Audi")
|
61
|
+
@d.to_s.should.equal "<select name=\"vehicle\" class=\"select-class\"><option value=\"volvo\">Volvo</option><option value=\"saab\">Saab</option><option value=\"mercedes\">Mercedes</option><option value=\"audi\">Audi</option></select>"
|
62
62
|
end
|
63
63
|
|
64
64
|
it "should be a plain submit control" do
|
@@ -74,7 +74,19 @@ describe "Simple Demeler with no Object" do
|
|
74
74
|
@d.text(:username)
|
75
75
|
@d.to_s.should.equal "<input type=\"submit\" value=\"Go!\" /><label for=\"username\">Enter Username</label><input name=\"username\" type=\"text\" id=\"username\" />"
|
76
76
|
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "Simple Demeler with Session" do
|
80
|
+
session = {:id=>1}
|
81
|
+
before do
|
82
|
+
@d = Demeler.new(nil, session)
|
83
|
+
end
|
77
84
|
|
85
|
+
it "should pass through the session variable" do
|
86
|
+
@d.clear
|
87
|
+
@d.out << session.inspect
|
88
|
+
@d.to_s.should.equal "{:id=>1}"
|
89
|
+
end
|
78
90
|
end
|
79
91
|
|
80
92
|
describe "Complex Demeler with Object" do
|
@@ -332,5 +344,4 @@ describe "Complex Demeler with Object" do
|
|
332
344
|
@d.tag_generator(:input, {:name=>:err, :value=>"bobama", :type=>:text})
|
333
345
|
@d.to_html.should.equal "<!-- begin generated output -->\n<input name=\"err\" value=\"bobama\" type=\"text\" /><warn> <-- Username already used.</warn>\n<!-- end generated output -->\n"
|
334
346
|
end
|
335
|
-
|
336
347
|
end
|