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