Hi all, I'm having some trouble with a has_many association on a table using the single table inheritance model that I'm hoping someone can help me with. The schema for the table is: CREATE TABLE `comments` ( `id` int(11) NOT NULL auto_increment, `user_id` int(11) default NULL, `type` varchar(20) NOT NULL default '', `type_id` int(11) NOT NULL default '0', `name` varchar(255) default NULL, `comment` text NOT NULL, `created_at` datetime default NULL, `updated_at` datetime default NULL, PRIMARY KEY (`id`), KEY `FK_users_comments` (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; ALTER TABLE `comments` ADD FOREIGN KEY (`user_id`) REFERENCES `users` (`id`); on top of which, I've got two tables: events and activities, both of which can have comments. Here are the model associations for Events, Activities and Comments: class Activity < ActiveRecord::Base belongs_to :user has_many :comments, :conditions => "type = 'Activity'", :foreign_key => "type_id" acts_as_taggable :join_class_name => "TagActivity" class Event < ActiveRecord::Base include EventMatching belongs_to :activity_type has_and_belongs_to_many :users has_many :comments, :conditions => "type = 'Event'", :foreign_key => "type_id" class Comment < ActiveRecord::Base belongs_to :user belongs_to :activity, :conditions => "type = 'Activity'", :foreign_key => "type_id" belongs_to :event, :conditions => "type = 'Event'", :foreign_key => "type_id" The strange behaviour is this: for activities, everything works perfectly. I can do: render(:partial => "shared/comment", :collection => @activity.comments) And it works like a charm. When I do the same for events: render(:partial => "shared/comment", :collection => @event.comments) I get an error: undefined method `user' for #<Event:0x382e3a8>. This error is on the first line that accesses comment.user in the partial. Here is the SQL I'm seeing in the development.log for fetching comments for Activities and Events: SELECT * FROM comments WHERE (comments.type_id = 59 AND (type = 'Activity')) SELECT * FROM comments WHERE (comments.type_id = 8 AND (type = 'Event')) Both queries return the correct rows when executed directly against the DB (MySQL 5 btw). The really odd thing though, is if I comment out the belongs_to :user from the Activity model, then Activity starts throwing the same error as Event. Somehow it looks like the association from Comment to User is relying upon the parent object also having an association to user (even though Event does have a h_a_b_t_m :users, it's still breaking), and even though the Comment is relying on the parent's relationship, it's still pulling in the proper user for each individual comment. This has had me stumped for the better part of the day, so hopefully someone might have some insight. If there's any relevant info or code I've left out let me know and I'll be glad to share it. Thanks in advance, Joshua
on 2006-03-19 13:17
on 2006-03-19 13:17
That's not quite how STI is supposed to be used. What you should do is something like: class Comment < ActiveRecord::Base end class EventComment < Comment end class ActivityComment < Comment end class Event < ActiveRecord::Base has_many :comments, :class_name => 'EventComment' end class Activity < ActiveRecord::Base has_many :comments, :class_name => 'ActivityComment' end Throw an event_comment_id and activity_comment_id on the comments table, and remove type_id. Haven't tried it but it should do what you're after. The user error you are getting is because there is no 'user' association on Event. You have used a belongs_to on Activity, and has_and_belongs_to_many on Event. You need to access Event.users instead. -Jonathan.