views:

43

answers:

1
 params[:codes] = "9,10"
    @result = Candidate.find :all,
         :joins =>
           params[:codes].split(',').collect {|c| ["INNER JOIN candidates_codes on candidates_codes.candidate_id = candidates.id, INNER JOIN codes on codes.code_id = candidates_codes.code_id AND codes.value = ?", c]}

Error

Association named 'INNER JOIN candidates_codes on candidates_codes.candidate_id = candidates.id, INNER JOIN codes on codes.code_id = candidates_codes.code_id AND codes.value = ?' was not found; perhaps you misspelled it?

Update

CREATE TABLE `candidates` (
 `id` int(11) NOT NULL auto_increment,
`first_name` varchar(255) collate utf8_unicode_ci default NULL,
`last_name` varchar(255) collate utf8_unicode_ci default NULL,
`mobile_number` varchar(255) collate utf8_unicode_ci default NULL,
`address` text collate utf8_unicode_ci,
`country` varchar(255) collate utf8_unicode_ci default NULL,
`created_at` datetime default NULL,
`updated_at` datetime default NULL,
PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=5 ;

  CREATE TABLE `candidates_codes` (
   `candidate_id` int(11) default NULL,
   `code_id` int(11) default NULL
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE `codes` (
 `id` int(11) NOT NULL auto_increment,
 `section` varchar(255) collate utf8_unicode_ci default NULL,
 `value` varchar(255) collate utf8_unicode_ci default NULL,
 `created_at` datetime default NULL,
 `updated_at` datetime default NULL,
 PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=11 ;

Hi,

I am trying to create a find which can ether be "OR" or "AND"

for example(pseudocode)

array a = (1,2)
array b = (1)

find(1 AND 2) = array a
find(1 OR 2) = array a, array b 

My code currently looks like this -

@result = Code.all :joins => :candidates,
        :conditions => ["codes.id IN (?)", params['searches'][:Company]],
        :select => "candidates.*"

code is a table full of codes that describe a candidate, a habtm relationship exists between code and candidate

The only way of using AND I can see in the guides is between two columns..

Many Thanks

Alex

+1  A: 

Since the association is done with a join table, doing an AND requires an INNER JOIN, once for each term in the AND. What you're trying to do is find a given candidate that has a mapping for all of the codes.

This could get messy, since you not only have to join for each term, but also again to the codes table if you're matching on a field there, such as value.

Assuming the number of terms isn't too high, and you pass in params[:codes] = "1,5,9", and that you're trying to match on codes.value:

Candidate.find :all,
    :joins =>
      params[:codes].split(',').collect {|c| "INNER JOIN candidates_codes#{c} on candidates_codes#{c}.candidate_id = candidates.id INNER JOIN codes#{c} on codes#{c}.id = candidates_codes#{c}.code_id AND codes#{c}.value = c"}

...or something like that. Warning that I haven't tested that code, but give it a whirl if that's what you're looking for.

Note I've removed the substitution from the last rev (where the ? is replaced by a variable) because joins don't support this. You should first sanitize the params (i.e. make sure they are integers, or whatever), or use the protected sanitize_sql method in the model.

fullware
Thanks for your reply! I got a error message with and without the #{c} parts I have put it in my original message with the code.
Alex
Made a slight change to the join, updated above. Did you eliminate the #{c} notation? This will be required in order to multiple AND terms to resolve and be named uniquely.
fullware
Sorry to say that I am still receiving the same error. Do the join statements need to be separated ?
Alex
I made some changes to the code. Note this was intended to get your started, not finish the job for you. In your version above, you have seemed to remove the interpolation [i.e. #{c}] which is required for this to work. Good luck, hope this gets you moving in the right direction.
fullware
That's great! thanks for the help
Alex