Kirk said:
This doesn't seem to be a matter of "can" Rails do it. The existing
scaffolding may or may not be able to directly support this, but it should
be darn simple to write something in any decent framework, with any decent
ORM, that can.
I use a component in production that could trivially be extended to do
exactly this, generically.
Kirk Haines
I made it happen, pretty easily, but I still think this ought to be built
into Rails. Can't see why it isn't. Maybe it is and I'm missing
something.
I used an example of houses and rooms. Each house has many rooms, and the
rooms have names. In order to produce a form to edit the houses, which
allows direct editing of the names of the rooms in the house, I did the
following:
sql:
-------------------------------------------------------------
CREATE TABLE `houses` (
`id` mediumint(9) NOT NULL auto_increment,
`name` varchar(30) NOT NULL default '',
`description` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
#
# Dumping data for table `houses`
#
INSERT INTO `houses` VALUES (1, 'Briary Bush', 'Lovely little house near a
babbling river');
INSERT INTO `houses` VALUES (2, 'Fawlty Towers', 'A grotty hell hole');
CREATE TABLE `rooms` (
`id` mediumint(9) NOT NULL auto_increment,
`name` varchar(50) NOT NULL default '',
`house_id` mediumint(9) NOT NULL default '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
#
# Dumping data for table `rooms`
#
INSERT INTO `rooms` VALUES (1, 'First Floor Front Room', 1);
INSERT INTO `rooms` VALUES (2, 'Penthouse', 1);
INSERT INTO `rooms` VALUES (3, 'Room 1', 2);
-------------------------------------------------------------
house.rb:
-------------------------------------------------------------
class House < ActiveRecord::Base
has_many :rooms
# This extends update_attributes to allow for the updating of the
associated records.
# The "rooms" hash is in the form {"id"=>{"column"=>"value",.......},
"id"=>{"column"=>"value",.....},....}
def update_attributes(attributes)
attributes["rooms"].each do |key,value|
@room=Room.find(key)
@room.update_attributes(value)
end
attributes.delete("rooms")
super(attributes)
end
end
-------------------------------------------------------------
room.rb:
-------------------------------------------------------------
class Room < ActiveRecord::Base
belongs_to :house
end
-------------------------------------------------------------
_form.html partial in views/houses :
-----------------------------------------------------------
<%= error_messages_for 'house' %>
<!--[form:house]-->
<p><label for="house_name">Name</label><br/>
<%= text_field 'house', 'name' %></p>
<p><label for="house_description">Description</label><br/>
<%= text_area 'house', 'description', "rows"=>"5" %></p>
<% for room in @house.rooms %>
<label for="room_<%=room.id %>_name">Room <%=h room. id%></label>
<input id="house_rooms_<%=h room. id%>_name" name="house[rooms][<%=h room.
id%>][name]" type="text" value="<%=h room. name%>" />
<% end %>
<!--[eoform:house]-->
-------------------------------------------------------------
I look forward to someone showing me a neater way to do it
The extension of the update_attributes method seems so simple that I can't
believe it would take much work to generalise this and have
update_attributes deal with associated data automatically. Any takers for
this wee Rails development task ?