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

102 views
Skip to first unread message

Josh

unread,
Dec 28, 2014, 8:16:40 PM12/28/14
to rubyonra...@googlegroups.com

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!

Frederick Cheung

unread,
Dec 29, 2014, 4:30:48 AM12/29/14
to rubyonra...@googlegroups.com


On Monday, December 29, 2014 1:16:40 AM UTC, Josh wrote:

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

Jason Fleetwood-Boldt

unread,
Dec 29, 2014, 8:23:52 AM12/29/14
to rubyonra...@googlegroups.com

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 received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-ta...@googlegroups.com.
To post to this group, send email to rubyonra...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/bbc2f6bd-8713-472d-b184-e737a83d0929%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

----

Jason Fleetwood-Boldt

All material © Jason Fleetwood-Boldt 2014. Public conversations may be turned into blog posts (original poster information will be made anonymous). Email ja...@datatravels.com with questions/concerns about this.

Jason Fleetwood-Boldt

unread,
Dec 29, 2014, 1:16:51 PM12/29/14
to rubyonra...@googlegroups.com

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


Order.try{|query| 
if x==1
  query
else
  query.unscope(:where)
 






--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-ta...@googlegroups.com.
To post to this group, send email to rubyonra...@googlegroups.com.

Josh

unread,
Dec 29, 2014, 4:04:30 PM12/29/14
to rubyonra...@googlegroups.com

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.

Reply all
Reply to author
Forward
0 new messages