I''ve got a model, "category" and another model "subcategory." Each subcategory belongs_to a category, and a category has_many subcategories. What I need to do is set it up so that I can search Category and Subcategory with one .find call. So: Category.find(:all, <etc) will find categories and subcategories. Now, I believe this can be done by making Subcategory a subclass of Category. Am I right? Unfortunately, there''s almost nothing in AWD about subclasses and has_many relationships, so I''m lost. I tried to just change Subcategory to extend Category in the model, but that led to errors (no such field: "categories.category_id"). What else do I need to change to allow Subcategory to extend Category and also belong_to a category? Thanks, Adam -- Posted via http://www.ruby-forum.com/.
Adam, I would probably do this with a single table that references itself, rather than have a new model Subcategory extend from Category. Basically you just need a categories table that contains a parent_id column referring to another row in that same table. There is a brief discussion of this at: http://wiki.rubyonrails.com/rails/pages/HowToCreateASelfReferentialHasManyRelationship It is also discussed in AWD ( ~ page 255 ) when they go over "Acts As Tree". Hope that helps, Jeff On 4/15/06, Adam Bloom <admanb@gmail.com> wrote:> I''ve got a model, "category" and another model "subcategory." Each > subcategory belongs_to a category, and a category has_many > subcategories. > > What I need to do is set it up so that I can search Category and > Subcategory with one .find call. So: > > Category.find(:all, <etc) > > will find categories and subcategories. > > Now, I believe this can be done by making Subcategory a subclass of > Category. Am I right? Unfortunately, there''s almost nothing in AWD about > subclasses and has_many relationships, so I''m lost. I tried to just > change Subcategory to extend Category in the model, but that led to > errors (no such field: "categories.category_id"). What else do I need to > change to allow Subcategory to extend Category and also belong_to a > category? > > Thanks, > > Adam > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
On Sat, Apr 15, 2006 at 10:07:10PM +0200, Adam Bloom wrote:> I''ve got a model, "category" and another model "subcategory." Each > subcategory belongs_to a category, and a category has_many > subcategories. > > What I need to do is set it up so that I can search Category and > Subcategory with one .find call. So: > > Category.find(:all, <etc) > > will find categories and subcategories. > > Now, I believe this can be done by making Subcategory a subclass of > Category. Am I right?Possibly-sorta, if when you say "subclass" you mean to use single-table inheritance. In that instance, yes, you can search Categories and also get matching subcategories, because STI is wonderfully intelligent about that sort of thing, like so: CREATE TABLE categories ( id INTEGER PRIMARY KEY, type VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, category_id INTEGER ); class Category << ActiveRecord::Base has_many :subcategories end class SubCategory << Category belongs_to :category end (All that off the top of my head, so it might not be strictly correct) Then, when you do a Category.find(), the SQL that will be generated will include "WHERE type=''Category'' OR type=''SubCategory''", while SubCategory.find() will only have "WHERE type=''SubCategory''". Speaking structurally, though, I''m not sure that STI really describes what you''re looking for. I''d consider putting together my own Category.find() type method that also ran the find on the subcategories itself, or else using something like acts_as_tree to do the whole thing (although I don''t know if acts_as_tree has the searching capabilities you want -- I''ve never used it myself). - Matt
Thanks guys! -Adam -- Posted via http://www.ruby-forum.com/.
Adam > What I need to do is set it up so that I can search Category and > Subcategory with one .find call. So: > Category.find(:all, <etc) > will find categories and subcategories. You could aggregate 2 searches in 1 call : (untested:) def find_deep (*args) result = Category.find(args) result << Subcategory.find(args) result.flatten end Alain
Hmmm. I have a different but related question. Is there such a thing as an "includes" condition for .find? i.e. if I''m searching for listings (which habtm categories) that are in a certain category with id = category_id I could do: Listing.find(:all, :conditions => [ "categories INCLUDE ?", category_id ] and, as an extension, is there any way to find a listing that is in a category with category_id = one of [ id1, id2, id3 ]. That way I could do something like: Listing.find(:all, :conditions => ["name = ?, or <is in a category which is in category_ids>, or <is in a subcategory which is in subcategory_ids>", "%#{params[:search_string]}%", <category_ids>, <subcategory_ids>] and find every listing with one search. It seems like it''d be something I could do with a pure-Ruby .find, but I''m not sure how hard that would be to integrate. -Adam -- Posted via http://www.ruby-forum.com/.
Formatting on that last pseudo-code chunk got really messed up. Listing.find(:all, :conditions => ["name = ?, or <is in a category which is in category_ids>, or <is in a subcategory which is in subcategory_ids>", "%#{params[:search_string]}%", <category_ids>, <subcategory_ids>] -- Posted via http://www.ruby-forum.com/.
Adam > Formatting on that last pseudo-code chunk got really messed up. > Listing.find(:all, :conditions => ["name = ?, > or <is in a subcategory which is in subcategory_ids>", > "%#{params[:search_string]}%", <category_ids>, <subcategory_ids>] When in doubt, just do it... with the console: ./script/console >> Foo.find_by_sql(''select * from foes where id in (1,2,3,4,5)'') (On Windows, you launch the console with ruby script\console ) Alain