views:

260

answers:

5

I have a Reservation model that I'm searching for with three fields. The container_id must always be self.id but as confirmed and auto_confirmed only one needs to be true. I have the following but it doesn't perform what I need:

Reservation.find(:all, 
:conditions => ['container_id = ? AND confirmed = ? OR auto_confirm = ?', 
self.id, true, true,])

How should I change this?

+1  A: 

I'm not sure I'm getting your problem, but from what I understand this would work:

Reservation.find(:all, 
:conditions => ['container_id = ? AND (confirmed = ? OR auto_confirm = ?)', 
self.id, true, true,])
marcgg
this will not work when both are true.
Salil
so how to get it to work when both are true?
Sam
It works for me when both are true.
Sam
You ask "only one needs to be true" logically it means row with both are true should not get in resultset.And for this look my answer below.
Salil
@sam If both are true then it will work as well. Then it depends on the logic you want
marcgg
I agree with @salil as per the Question he is right.
Aditya
Only one must be true means that only one can be true and should not work if both are true
Sam
Only one needs to be true - on my derailed train of thought - means that both can be true but only one needs to be true
Sam
+2  A: 

As per your question confirmed and auto_confirmed only one needs to be true. So use following

Reservation.find(:all, 
                 :conditions => ['container_id = :container AND 
                  ( (confirmed = :flag and auto_confirm != :flag) ||
                    (confirmed != :flag and auto_confirm = :flag))', 
                    {:container=> self.id, :flag=>true}]
               )
Salil
+1 for Answer as per the question.
Aditya
Thanks for your answer but it didn't finish the job as simple as the one I checked - and of course this is contingent on how I worded the question. But plus one for your answer thanks!
Sam
A: 

I think something like this:

Reservation.find(:all, 
:conditions => ['container_id = ? AND ((confirmed != true AND auto_confirm = true) OR (confirmed = true AND auto_confirm != true))', 
self.id])
dombesz
this will not work with confirmed = false AND auto_confirm = null just for example though.
Salil
the default values for confirmed and auto_confirm are :false
Sam
changed to work as you like
dombesz
A: 

I'm not sure if this is database agnostic, but you could try

Reservation.find(:all, 
:conditions => ['container_id = ? AND confirmed = ? **XOR** auto_confirm = ?', 
self.id, true, true,])
Tadas Tamosauskas
A: 

What you are saying is not true - a query like

  SELECT * FROM foos WHERE content_id = 345 AND (confirm = 1 OR auto_confirm = 1)

will select the rows where both "confirm" columns are set to 1 (and ActiveRecord creates tinyint columns for booleans and checks against 1 and 0).

If you mean "find all rows matching on the content_id and having EITHER confirmed OR auto_confirmed true but NOT both" then you come down to a query like this

 SELECT * FROM foos WHERE content_id = 345 AND ((confirmed = 1 AND auto_confirm = 0) OR (confirmed = 0 AND auto_confirm = 1))

which you reword in AR terms like this

  Reservation.find(:all, 
    :conditions => [
      'container_id = ? AND ((confirmed = 1 AND auto_confirm != 1) OR (confirmed = 0 AND auto_confirm != 1))', 
      self]
  )

However, judging from the names your fields have you are actually implementing a state machine with separate columns which will bring you pain, so I'd investigate something that would give you progressions of states instead of checking for separate on and off bits.

Julik
over my head but its simple enough for right now.
Sam