From: Dave Howell Date: 2010-10-17T10:17:07+09:00 Subject: Re: ODBC app in Ruby - I don't believe it. 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 => "Huffy Angelaton" >> puts blog.author => "Huffy Angelaton" >> puts Form.new(:action=>"/savepost"){ blog.author } => "
" I found *nothing* that even remotely approached that. So I wrote my own. 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. 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. >> b = Batch['3705bf0e-4264-6654-ff6c-00065b3f562c'] =>#"1:1.7", :notes=>nil, :active=>true, :herbpercent=>#, :pressed=>nil, :batchcode=>"06082030.1", :herbweight=>3741, :lot_id=>"e62b56d2-a741-xxxx-xxxx-xxxxxxxxxxxx", :initvol=>6360, :created=>Fri Aug 04 00:00:00 -0700 2006, :finalvol=>8812, :extract_id=>"f2580cc8-2354-xxxx-xxxx-xxxxxxxxxxxx", :batch_id=>"3451a2a6-5fc1-xxxx-xxxx-xxxxxxxxxxxx", :id=>1534, :decocted=>false, :cultivation_id=>"3705ff6c-2355-xxxx-xxxx-xxxxxxxxxxxx"}> However, a batch also contains multiple non-active ingredients, called components. >> b.components => [ ##, :batch_id=>"3705ff6c-5fc1-xxxx-xxxx-xxxxxxxxxxxx", :componentcategory_id=>"4ace3c04-2357-xxxx-xxxx-xxxxxxxxxxxx"}>, ##, :batch_id=>"3705ff6c-5fc1-xxxx-xxxx-xxxxxxxxxxxx", :componentcategory_id=>"4ace3f92-2357-xxxx-xxxx-xxxxxxxxxxxx"}>, ##, :batch_id=>"3705ff6c-5fc1-xxxx-xxxx-xxxxxxxxxxxx", :componentcategory_id=>"4ace430c-xxxx-xxxx-xxxx-xxxxxxxxxxxx"}>] And each component, in turn, is linked to a category: >> b.components[0].componentcategory => #"Glycerine", :sequence=>3, :componentcategory_id=>"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. 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 . 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. >> b.components[0].componentcategory => #"Glycerine", :sequence=>3, :componentcategory_id=>"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