From: Robert Jones Date: 2005-07-18T03:30:54+09:00 Subject: Re: Can Rails deal with related attributes in forms? Kirk Haines wrote: > On Saturday 16 July 2005 10:00 am, Robert Jones wrote: > >> Suppose that object A has many of object B, and object B has some >> attribute c, and that my Rails app has models that hold these >> associations. >> >> Can Rails then help me to produce an edit form for object A that includes >> a list of all the related object B's, and allows me to edit each of their >> attribute c's directly (ie not by simply providing a link to a seperate >> edit form for each of the object B's) > > 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' %>


<%= text_field 'house', 'name' %>


<%= text_area 'house', 'description', "rows"=>"5" %>

<% for room in @house.rooms %> <% end %> ------------------------------------------------------------- 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 ? ;) -- Robert Jones