D
Dave Howell
The other paradigm that I've tripped over is that I want my models to =
know how to present themselves. Tango did this to a limited extent, and =
I really liked it. I was expecting a beautiful world of =
self-constructing data when I started working with Rails. Something like =
this:
blog.author
}
=3D> "<form action=3D\"/savepost"><input type=3D'text' length=3D'50' =
value=3D'Huffy Angelaton' name=3D'blog.author'></form>"
I found *nothing* that even remotely approached that. So I wrote my own.=20=
There was a pretty long discussion on the Ramaze list about this, =
because I'm well aware that this is a big-time violation of the =
Model-View-Controller idea. Unfortunately, MVC just can't handle this =
without a huge amount of extra lumps of code. Well, it can handle the =
*previous* example. But it really can't handle the following one. Or (to =
inject at least a smidge of humility), I was quite unable to find a way =
to do it.=20
This is a slightly modified example from my working code. A "Batch" is a =
particular batch of manufactured product, specifically an herbal =
medicine. I've obfuscated the UUIDs.=20
:herbpercent=3D>#<BigDecimal:101f28328,'0.0',4(12)>, ressed=3D>nil, =
:batchcode=3D>"06082030.1", :herbweight=3D>3741, =
:lot_id=3D>"e62b56d2-a741-xxxx-xxxx-xxxxxxxxxxxx", :initvol=3D>6360, =
:created=3D>Fri Aug 04 00:00:00 -0700 2006, :finalvol=3D>8812, =
:extract_id=3D>"f2580cc8-2354-xxxx-xxxx-xxxxxxxxxxxx", =
:batch_id=3D>"3451a2a6-5fc1-xxxx-xxxx-xxxxxxxxxxxx", :id=3D>1534, =
:decocted=3D>false, =
:cultivation_id=3D>"3705ff6c-2355-xxxx-xxxx-xxxxxxxxxxxx"}>
However, a batch also contains multiple non-active ingredients, called =
components.
=3D> [
#<Component =
@values=3D{ercentage=3D>#<BigDecimal:101f220b8,'0.1E2',4(8)>,=20
:batch_id=3D>"3705ff6c-5fc1-xxxx-xxxx-xxxxxxxxxxxx",=20
=
:componentcategory_id=3D>"4ace3c04-2357-xxxx-xxxx-xxxxxxxxxxxx"}>,=20
#<Component =
@values=3D{ercentage=3D>#<BigDecimal:101f21a50,'0.5E2',4(8)>,=20
:batch_id=3D>"3705ff6c-5fc1-xxxx-xxxx-xxxxxxxxxxxx",=20
=
:componentcategory_id=3D>"4ace3f92-2357-xxxx-xxxx-xxxxxxxxxxxx"}>,=20
#<Component =
@values=3D{ercentage=3D>#<BigDecimal:101f21410,'0.4E2',4(8)>,=20
:batch_id=3D>"3705ff6c-5fc1-xxxx-xxxx-xxxxxxxxxxxx",=20
=
:componentcategory_id=3D>"4ace430c-xxxx-xxxx-xxxx-xxxxxxxxxxxx"}>]
And each component, in turn, is linked to a category:
:componentcategory_id=3D>"4ace3c04-2357-xxxx-xxxx-xxxxxxxxxxxx"}>
If I want to create a form for a user to edit the batch data, what I put =
in my code is this:
e.editform.to_form
and what I get is this:
A batch has more than one component, and each component can be a =
particular substance. In order to present that HTML code, my batch =
object had to know to take its own fields, like "batchcode" and turn =
them in to text input fields. The size of the field is based on how much =
space is reserved in the database itself for that data. Each Component =
of a Batch has to do the same thing. "Percentage" is a text input field =
long enough for the custom data type (a numeric(5,2) that only accepts =
numbers in the range 0.00 to 100.00). But since there are multiple =
components, and HTML forms don't have support for nesting, each form =
field has to get a unique name so that when the data comes back, it's =
possible to figure out which percentage belongs to which component.=20
Finally, each component is linked to a 'Componentcategory." In =
order to allow the user to select a different category, the form has to =
know what EVERY row in the table is, in order to create the list of =
<options>.=20
This last bit is really critical. If you just ask the object itself, it =
cannot tell you what you need to know to create the form.=20
:sequence=3D>3, =
:componentcategory_id=3D>"4ace3c04-2357-xxxx-xxxx-xxxxxxxxxxxx"}>
To find out what other categories this component *could* be, you have to =
back up from this component category to the class, then query for all =
members of the class, then use that information to construct one form =
field, using the identity of the current active *instance* of the class =
to figure out which <option> is marked as "selected".=20
I tried to get to this point with templating, but pretty soon my =
templates were hardly more than <body><@htmlfromcontroller></body>, so =
what's the point?=20
I must admit, I'm still not too sure what paradigm IS behind the current =
flock of templating tools, except that it isn't like this, and doing it =
this way is totally rocking, so I have no incentive to change.=20
know how to present themselves. Tango did this to a limited extent, and =
I really liked it. I was expecting a beautiful world of =
self-constructing data when I started working with Rails. Something like =
this:
blog.author
}
=3D> "<form action=3D\"/savepost"><input type=3D'text' length=3D'50' =
value=3D'Huffy Angelaton' name=3D'blog.author'></form>"
I found *nothing* that even remotely approached that. So I wrote my own.=20=
There was a pretty long discussion on the Ramaze list about this, =
because I'm well aware that this is a big-time violation of the =
Model-View-Controller idea. Unfortunately, MVC just can't handle this =
without a huge amount of extra lumps of code. Well, it can handle the =
*previous* example. But it really can't handle the following one. Or (to =
inject at least a smidge of humility), I was quite unable to find a way =
to do it.=20
This is a slightly modified example from my working code. A "Batch" is a =
particular batch of manufactured product, specifically an herbal =
medicine. I've obfuscated the UUIDs.=20
=3D>#<Batch @values=3D{:wv=3D>"1:1.7", :notes=3D>nil, :active=3D>true, =b =3D Batch['3705bf0e-4264-6654-ff6c-00065b3f562c']
:herbpercent=3D>#<BigDecimal:101f28328,'0.0',4(12)>, ressed=3D>nil, =
:batchcode=3D>"06082030.1", :herbweight=3D>3741, =
:lot_id=3D>"e62b56d2-a741-xxxx-xxxx-xxxxxxxxxxxx", :initvol=3D>6360, =
:created=3D>Fri Aug 04 00:00:00 -0700 2006, :finalvol=3D>8812, =
:extract_id=3D>"f2580cc8-2354-xxxx-xxxx-xxxxxxxxxxxx", =
:batch_id=3D>"3451a2a6-5fc1-xxxx-xxxx-xxxxxxxxxxxx", :id=3D>1534, =
:decocted=3D>false, =
:cultivation_id=3D>"3705ff6c-2355-xxxx-xxxx-xxxxxxxxxxxx"}>
However, a batch also contains multiple non-active ingredients, called =
components.
=3D> [
#<Component =
@values=3D{ercentage=3D>#<BigDecimal:101f220b8,'0.1E2',4(8)>,=20
:batch_id=3D>"3705ff6c-5fc1-xxxx-xxxx-xxxxxxxxxxxx",=20
=
:componentcategory_id=3D>"4ace3c04-2357-xxxx-xxxx-xxxxxxxxxxxx"}>,=20
#<Component =
@values=3D{ercentage=3D>#<BigDecimal:101f21a50,'0.5E2',4(8)>,=20
:batch_id=3D>"3705ff6c-5fc1-xxxx-xxxx-xxxxxxxxxxxx",=20
=
:componentcategory_id=3D>"4ace3f92-2357-xxxx-xxxx-xxxxxxxxxxxx"}>,=20
#<Component =
@values=3D{ercentage=3D>#<BigDecimal:101f21410,'0.4E2',4(8)>,=20
:batch_id=3D>"3705ff6c-5fc1-xxxx-xxxx-xxxxxxxxxxxx",=20
=
:componentcategory_id=3D>"4ace430c-xxxx-xxxx-xxxx-xxxxxxxxxxxx"}>]
And each component, in turn, is linked to a category:
=3D> #<Componentcategory @values=3D{:name=3D>"Glycerine", :sequence=3D>3, =b.components[0].componentcategory
:componentcategory_id=3D>"4ace3c04-2357-xxxx-xxxx-xxxxxxxxxxxx"}>
If I want to create a form for a user to edit the batch data, what I put =
in my code is this:
e.editform.to_form
and what I get is this:
value=3D'3705ff6c-xxxx-xxxx-xxxx-xxxxxxxxxxxx' type=3D'hidden'/><input name=3D'batch_id' =
<select name=3D'cultivation_id' id=3D'Cultivation'>
<option =
value=3D'3451a2a6-xxxx-xxxx-xxxx-xxxxxxxxxxxx'>Organically =value=3D'345183ca-xxxx-xxxx-xxxx-xxxxxxxxxxxx'>Other said:<option selected=3D'true' =
Grown said:<option =
value=3D'3451a68e-xxxx-xxxx-xxxx-xxxxxxxxxxxx'>Wildcrafted said:<option =
value=3D'3451a9b8-xxxx-xxxx-xxxx-xxxxxxxxxxxx'> said:<option =
value=3D'3451b08e-xxxx-xxxx-xxxx-xxxxxxxxxxxx'>Grown Without =value=3D'3451acd8-xxxx-xxxx-xxxx-xxxxxxxxxxxx'>Cultivated said:<option =
Chemicals said:<option =
value=3D'77cc2f7a-xxxx-xxxx-xxxx-xxxxxxxxxxxx'>Forest Grown said:<option =
value=3D'3705ff6c-xxxx-xxxx-xxxx-xxxxxxxxxxxx' type=3D'hidden'/>value=3D'c7406e90-xxxx-xxxx-xxxx-xxxxxxxxxxxx'>Wild Simulated said:</select>
<input name=3D'Component:8313022463:batch_id' =
value=3D'4ace3c04-xxxx-xxxx-xxxx-xxxxxxxxxxxx' type=3D'hidden'/><input name=3D'Component:8313022463:componentcategory_id' =
<select name=3D'Component:8313022463:componentcategory_id' = id=3D'Componentcategory'>
<option =
value=3D'4acb07a0-xxxx-xxxx-xxxx-xxxxxxxxxxxx'>Olive Oil said:<option =
value=3D'4ace354c-xxxx-xxxx-xxxx-xxxxxxxxxxxx'>Other said:<option selected=3D'true' =
value=3D'4ace3c04-xxxx-xxxx-xxxx-xxxxxxxxxxxx'>Glycerine said:<option =
value=3D'4ace3f92-xxxx-xxxx-xxxx-xxxxxxxxxxxx'>Ethanol said:<option =
value=3D'3705ff6c-xxxx-xxxx-xxxx-xxxxxxxxxxxx' type=3D'hidden'/>value=3D'4ace430c-xxxx-xxxx-xxxx-xxxxxxxxxxxx'>Water said:<input name=3D'Component:8313022463ercentage' size=3D'6' = value=3D'10' type=3D'text'/>
<input name=3D'Component:-7531801290:batch_id' =
value=3D'4ace3f92-xxxx-xxxx-xxxx-xxxxxxxxxxxx' type=3D'hidden'/><input name=3D'Component:-7531801290:componentcategory_id' =
<select name=3D'Component:-7531801290:componentcategory_id' = id=3D'Componentcategory'>
<option =
value=3D'4acb07a0-xxxx-xxxx-xxxx-xxxxxxxxxxxx'>Olive Oil said:<option =
value=3D'4ace354c-xxxx-xxxx-xxxx-xxxxxxxxxxxx'>Other said:<option =
value=3D'4ace3c04-xxxx-xxxx-xxxx-xxxxxxxxxxxx'>Glycerine said:<option selected=3D'true' =
value=3D'4ace3f92-xxxx-xxxx-xxxx-xxxxxxxxxxxx'>Ethanol said:<option =
value=3D'3705ff6c-xxxx-xxxx-xxxx-xxxxxxxxxxxx' type=3D'hidden'/>value=3D'4ace430c-xxxx-xxxx-xxxx-xxxxxxxxxxxx'>Water said:<input name=3D'Component:-7531801290ercentage' size=3D'6' = value=3D'50' type=3D'text'/>
<input name=3D'Component:-6831266729:batch_id' =
value=3D'4ace430c-xxxx-xxxx-xxxx-xxxxxxxxxxxx' type=3D'hidden'/><input name=3D'Component:-6831266729:componentcategory_id' =
<select name=3D'Component:-6831266729:componentcategory_id' = id=3D'Componentcategory'>
<option =
value=3D'4acb07a0-xxxx-xxxx-xxxx-xxxxxxxxxxxx'>Olive Oil said:<option =
value=3D'4ace354c-xxxx-xxxx-xxxx-xxxxxxxxxxxx'>Other said:<option =
value=3D'4ace3c04-xxxx-xxxx-xxxx-xxxxxxxxxxxx'>Glycerine said:<option =
value=3D'4ace3f92-xxxx-xxxx-xxxx-xxxxxxxxxxxx'>Ethanol said:<option selected=3D'true' =
value=3D'4ace430c-xxxx-xxxx-xxxx-xxxxxxxxxxxx'>Water said:<input name=3D'Component:-6831266729ercentage' size=3D'6' = value=3D'40' type=3D'text'/>
<input name=3D'created' size=3D'12' value=3D'2006 Aug 04' = type=3D'text'/>
<input name=3D'wv' size=3D'40' value=3D'1:1.7' type=3D'text'/>
<input name=3D'herbpercent' size=3D'6' value=3D'0' type=3D'text'/>=
<input name=3D'batchcode' size=3D'40' value=3D'55436476' = type=3D'text'/>
<input name=3D'herbweight' size=3D'7' value=3D'3741' = type=3D'text'/>
<input name=3D'initvol' size=3D'7' value=3D'6360' type=3D'text'/>
<input name=3D'finalvol' size=3D'7' value=3D'8812' type=3D'text'/>=
<input name=3D'decocted' type=3D'checkbox'/><textarea =
name=3D'notes' rows=3D'8' cols=3D'80'> said:<input checked=3D'' name=3D'active' type=3D'checkbox'/>
<input name=3D'pressed' size=3D'12' value=3D'' type=3D'text'/>"
A batch has more than one component, and each component can be a =
particular substance. In order to present that HTML code, my batch =
object had to know to take its own fields, like "batchcode" and turn =
them in to text input fields. The size of the field is based on how much =
space is reserved in the database itself for that data. Each Component =
of a Batch has to do the same thing. "Percentage" is a text input field =
long enough for the custom data type (a numeric(5,2) that only accepts =
numbers in the range 0.00 to 100.00). But since there are multiple =
components, and HTML forms don't have support for nesting, each form =
field has to get a unique name so that when the data comes back, it's =
possible to figure out which percentage belongs to which component.=20
Finally, each component is linked to a 'Componentcategory." In =
order to allow the user to select a different category, the form has to =
know what EVERY row in the table is, in order to create the list of =
<options>.=20
This last bit is really critical. If you just ask the object itself, it =
cannot tell you what you need to know to create the form.=20
=3D> #<Componentcategory @values=3D{:name=3D>"Glycerine", =b.components[0].componentcategory
:sequence=3D>3, =
:componentcategory_id=3D>"4ace3c04-2357-xxxx-xxxx-xxxxxxxxxxxx"}>
To find out what other categories this component *could* be, you have to =
back up from this component category to the class, then query for all =
members of the class, then use that information to construct one form =
field, using the identity of the current active *instance* of the class =
to figure out which <option> is marked as "selected".=20
I tried to get to this point with templating, but pretty soon my =
templates were hardly more than <body><@htmlfromcontroller></body>, so =
what's the point?=20
I must admit, I'm still not too sure what paradigm IS behind the current =
flock of templating tools, except that it isn't like this, and doing it =
this way is totally rocking, so I have no incentive to change.=20