how to remove (and resuse) all existing constraints from ActiveRecord::Relation

I’d like to remove all existing constraints from an ActiveRecord::Relation and leave the rest in-tact.

I am not looking for #unscoped since I would like to keep any joins/order clauses around.

Additionally, I would like to re-use the constraints that were removed in another query, so the ability to call #to_sql on them would be a very nice bonus.

This is the best I’ve been able to hack together:

Order.where(id: 1).where(id: 2).arel.constraints[0].to_sql

=> “orders.id = 1 AND orders.id = 2”

…but that just seems wrong. As far as I can tell #constraints always has one item in it, but I don’t know that will always be true.

Thanks!

I’d like to remove all existing constraints from an ActiveRecord::Relation and leave the rest in-tact.

I am not looking for #unscoped since I would like to keep any joins/order clauses around.

Additionally, I would like to re-use the constraints that were removed in another query, so the ability to call #to_sql on them would be a very nice bonus.

Sounds like you are looking for

some_scope.unscope(:where)

Fred

You can use a .try{ |query| … } block inside the Arel chain.

I think to achieve what you want you would do something like

Order.where(id: 1).try{|query| if continue_with_query; query; else; Order; end}

Notice that inside the try block I’m passing back either the query (with Arel constraints) or a new Order class object (which will “reset” all the constraints because it’ll be a new object)

I actually think a better design would be to adopt this try-block method for all your constraints, and then add them optionally depending on your if statement. then you don’t have to do any “resetting” at all because each individual step will either return the original query or will return the query with more scope restrictions on it.

-Jason

You can do that inside a .try{} block too, same idea:

Order.try{|query|

if x==1

  query

else

  query.unscope(:where)

}

Sounds like you are looking for

some_scope.unscope(:where)

This doesn’t appear to return the existing constraints for me to re-use them.