Please explain find_with_ferret, retrieve_records, :include and :conditions

Hello, I’m using find_with_ferret to search multiple models and it
works great. The trouble is I need to filter the results
using :include and :conditions.

I get two errors depending on the syntax I use in the search. Reading
the source, I see the retrieve_records method seems to filter
the :include and :conditions so that they only apply to the relevant
model when searching multiple models. This is exactly what I want, but
I can’t seem to get it to work.

My question: is my syntax wrong? Or have I misread how retrieve_record
works? If so, How would I apply conditions to a subset of models being
searched in a multi model search?

First Try. This syntax with using a hash to contain the include

params works with regular active_record calls.
@results = Inventory.find_with_ferret( @query,
{ :multi => [ Artist], :page => params[ :page ],
:per_page
=> 10 },
{ :include => {:media_files => {}}, :conditions =>
[ “media_files.file and inventories.status = ‘donated’” ] } )

Resulting Error

undefined method `to_sym’ for [:media_files, {}]:Array

Second try. I put the :include params in [] array brackets to see if

that would help the to_sym error. That fixes the to_sym error. But now
the association isn’t getting found?
@results = Inventory.find_with_ferret( @query,
{ :multi =>
[ Artist], :page => params[ :page ], :per_page => 10 },
{ :include =>
[:media_files => {}], :conditions => [ “media_files.file and
inventories.status = ‘donated’” ] } )

Resulting Error

Association named ‘media_files’ was not found; perhaps you misspelled
it?

Thanks in advance.

J-C

Hi,

first of all, the include options should be a simple Array of Symbols,
or, if you only want to include one relationship, a single Symbol,
like

:include => [ :media_files ]
or
:include => :media_files

And yes, aaf will filter these includes for each model.

Second, aaf unfortunately does not support specifying conditions on a
per model basis yet, so the sql resulting from your conditions argument
has to be valid for fetching records from each of the models you query -
in short, only use attributes present in all of the models.

Afair there’s already a trac ticket regarding the implementation of
per-model conditions for multi search, but I didn’t find the time to
implement this yet. I’ll try to have a look into this over the weekend.

Cheers,
Jens

On Thu, Dec 13, 2007 at 03:28:09PM -0500, Jean-Charles Carelli wrote:

My question: is my syntax wrong? Or have I misread how retrieve_record
‘donated’" ] } )
@results = Inventory.find_with_ferret( @query,

Thanks in advance.

J-C


Ferret-talk mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/ferret-talk


Jens Krämer
http://www.jkraemer.net/ - Blog
http://www.omdb.org/ - The new free film database

Jens Krämer wrote:

Afair there’s already a trac ticket regarding the implementation of
per-model conditions for multi search, but I didn’t find the time to
implement this yet. I’ll try to have a look into this over the weekend.

Hey Jens, did you actually manage to get to this over the weekend? I was
looking over the code in your RDOC for AAF, and I saw the following in
class_methods.rb, line 377:

    # check for per-model conditions and take these if provided
    if conditions = find_options[:conditions]
      key = model.underscore.to_sym
      conditions = conditions[key] if Hash === conditions
    end

And then I noticed my copy of the code (from stable release) didn’t have
those lines. So I update to the bleeding edge of trunk, and it sure
looks like per-model conditions are in place and working (at least with
my set of models they appear to be working).

So, are per-model conditions working as you would expect them to be
working? Or am I completely out to lunch and imagining things?

  • Sheldon M.

Hi!

Yeah, I experimented with this and it should work as intended. However
I’m not sure I like it the way it is now - imho it would be cleaner to
have not only conditions on a per model basis, but other AR options like
include or group_by, too.

That’s why I didn’t announce this feature yet, I just wanted to think
about it a bit more :wink:

One way to specify these per-model options might with in the :multi
option:

find_with_ferret query, :multi => {
:model_a => { :conditions => [‘a=?’, a_Value ]
},
:model_b => { :include => :some_relationship }
}

What do you think?

Cheers,
Jens

On Tue, Dec 18, 2007 at 07:35:25AM +0100, Sheldon M. wrote:

    # check for per-model conditions and take these if provided

So, are per-model conditions working as you would expect them to be
working? Or am I completely out to lunch and imagining things?


Ferret-talk mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/ferret-talk

Jens Krämer
webit! Gesellschaft für neue Medien mbH
Schnorrstraße 76 | 01069 Dresden
Telefon +49 351 46766-0 | Telefax +49 351 46766-66
[email protected] | www.webit.de

Amtsgericht Dresden | HRB 15422
GF Sven Haubold

I thought that the current implementation looked like a quick-fix! That
said, it solved an immediate problem, so I’ll continue to use it until
what you proposed below comes along.

I like what I see below. My question would be, if I had three models,
ModelA, ModelB, and ModelC and all three had conditions and includes,
how would the statement look? Would it be:

ModelA.find_with_ferret(query, {
:page => 1, :per_page => 5,
:multi => {
:ModelB => { :conditions => [‘b=?’, b_Value ], :include =>
:some_B_relationship] },
:ModelC => { :conditions => [‘c=?’, c_Value ], :include =>
:some_C_relationship] },
}
},
{ :conditions => [‘a=?’, a_Value ], :include => :some_A_relationship]
} )

or would it be:

ModelA.find_with_ferret(query, {
:page => 1, :per_page => 5,
:multi => {
:ModelA => { :conditions => [‘a=?’, a_Value ], :include =>
:some_A_relationship] },
:ModelB => { :conditions => [‘b=?’, b_Value ], :include =>
:some_B_relationship] },
:ModelC => { :conditions => [‘c=?’, c_Value ], :include =>
:some_C_relationship] }
}
} )

In the first example, the conditions for ModelA are left hanging in the
find_options argument, as they would be with a single model search. The
second example is much cleaner, and is (I think) what happens internally
with the method call add_self_to_model_list_if_necessary(). The problem
with the second example, is that the syntax between a single model
search and multi-model search would be different.

Looking over the AAF code, perhaps it doesn’t really matter. People
could use whatever syntax they’re comfortable with.

The last question to ponder would be, what if I didn’t have any
conditions or includes? Would it be

ModelA.find_with_ferret(query, {
:page => 1, :per_page => 5,
:multi => {
:ModelB => { },
:ModelC => { }
}
} )

I don’t think I helped any, did I? What I can say, is I like bringing
the conditions into the :multi, rather than having to specify the :multi
as an array and then the conditions as a hash, but I can see the
inconsistencies it brings to the table.

Cheers,

  • Sheldon M.

Jens K. wrote:

find_with_ferret query, :multi => {
:model_a => { :conditions => [‘a=?’, a_Value ]
},
:model_b => { :include => :some_relationship }
}

What do you think?