I have a model that allows subclasses to dynamically define fields. The following code is a short test case that illustrates the problem I''m having: class Product < ActiveRecord::Base acts_as_ferret :fields => [:name] serialize :data def self.data_properties (*properties) properties.each do |property| define_method(property) {self.get_property(property)} define_method((property.to_s + ''='').to_sym) \ {|value| self.set_property(property, value)} end end def get_property (property) self[:data][property] if self[:data] end def set_property (property, value) self[:data] = Hash.new unless self[:data] self[:data][property] = value end end Here''s the migration for said model: class CreateProducts < ActiveRecord::Migration def self.up create_table :products do |t| t.column :name, :string t.column :type, :string t.column :data, :string end end def self.down drop_table :products end end An example of a couple subclasses are: class Book < Product acts_as_ferret :fields => [:name, :author, :pages] data_properties :author, :pages end and: class Music < Product acts_as_ferret :fields => [:name, :artist, :label] data_properties :artist, :label end Creating a couple of records works fine:>> (Book.new(:name => ''Moby Dick'', :author => ''Herman Melville'', :pages => 704)).save=> true>> (Music.new(:name => ''Abbey Road'', :artist => ''The Beatles'', :label => ''Apple'')).save=> true But things start to get strange when I search for content:>> Book.find_by_contents(''*'')=> #<FerretMixin::Acts::ARFerret::SearchResults:0xb7433ef8 @total_hits=2, @results=[]>>> Music.find_by_contents(''*'')=> #<FerretMixin::Acts::ARFerret::SearchResults:0xb7431360 @total_hits=2, @results=[#<Music:0xb7431608 @attributes={"name"=>"Abbey Road", "type"=>"Music", "id"=>"2", "data"=>"--- \n:artist: The Beatles\n:label: Apple\n"}>]> I can provide debug output for the above commands if you''d like. My ultimate goal here is to be able to find Products by fields only defined for Products (i.e. name) as well as to be able to find subclasses of Products by their respective fields (i.e. find Music by artist). Any help, insight, or even telling me that I''m smoking crack would be greatly appreciated. Regards, Evan -- Posted via http://www.ruby-forum.com/.
On Wed, Oct 11, 2006 at 01:11:32AM +0200, Evan wrote:> I have a model that allows subclasses to dynamically define fields. > > The following code is a short test case that illustrates the problem I''m > having: > > class Product < ActiveRecord::Base > acts_as_ferret :fields => [:name]Don''t call acts_as_ferret in your base class, instead add the :name field to the acts_as_ferret calls in Music and Book. That should fix your problems. acts_as_ferret isn''t supposed to be called twice in a model (which is the case if you call it in your superclass, and in classes inheriting from that). cheers, Jens -- webit! Gesellschaft f?r neue Medien mbH www.webit.de Dipl.-Wirtschaftsingenieur Jens Kr?mer kraemer at webit.de Schnorrstra?e 76 Tel +49 351 46766 0 D-01069 Dresden Fax +49 351 46766 66
Jens Kraemer wrote:> On Wed, Oct 11, 2006 at 01:11:32AM +0200, Evan wrote: > Don''t call acts_as_ferret in your base class, instead add the :name > field to the acts_as_ferret calls in Music and Book. That should fix > your problems.I assume that I will be unable to call Product.find_by_contents in this case. So, in order to do search of all products I would have to do a multi-index search? -- Posted via http://www.ruby-forum.com/.
On Mon, Oct 16, 2006 at 05:41:23PM +0200, Evan wrote:> Jens Kraemer wrote: > > On Wed, Oct 11, 2006 at 01:11:32AM +0200, Evan wrote: > > Don''t call acts_as_ferret in your base class, instead add the :name > > field to the acts_as_ferret calls in Music and Book. That should fix > > your problems. > > I assume that I will be unable to call Product.find_by_contents in this > case. So, in order to do search of all products I would have to do a > multi-index search?right. You could also do it the other way around: just call acts_as_ferret in your Product class, and override to_doc in your child classes to add your dynamic properties to the ferret document. Don''t forget to use :store_classname => true when you call acts_as_ferret. If you want to declare special Ferret options on a per field level, you''d have to declare them in the acts_as_ferret call in class Product for all kinds of products. That''s not really nice but should work. Jens -- webit! Gesellschaft f?r neue Medien mbH www.webit.de Dipl.-Wirtschaftsingenieur Jens Kr?mer kraemer at webit.de Schnorrstra?e 76 Tel +49 351 46766 0 D-01069 Dresden Fax +49 351 46766 66