4 ms·
This has been long awaited: Post.where('id = 1').or(Post.where('id = 2'))
by jesalg 10y ago
This has been long awaited:
Post.where('id = 1').or(Post.where('id = 2'))
- ch4s3 10y agoSeriously, .or() always felt like a glaring omission.
- gleenn 10y agoIt's not an omission per se, it's actually a challenging thing to implement. I'm sure they'd have done it sooner if it wasn't so hard to get right. Think of how the precedence rules would work: especially since the queries are composable, tacking on another .or() can do funny things semantically.
- ch4s3 10y agoI think I chose my words poorly. I'm sure it was a huge undertaking, but the lack .or() is very noticeable in AR if you're coming from other ORMs or straight SQL.
- pmontra 10y agoI wrote it in SQL when I needed it, after all I knew SQL before AR came around. An OR is very rare and probably that's why it landed only in version 5. Another implementation is Post.where(id: [1, 2]) which is SELECT * FROM posts WHERE id IN (1, 2). I guess a db would compile it into exactly the same code (dbs use different terms but that's what it is) but the performances could be different inside AR/Arel.
- chippy 10y agoPost.find([1,2]) Works in Rails 4
- dogweather 10y agoI'm pretty sure that DHH strongly opposed .or(), but I'm not sure why. I'd really like to know if this is true, and if so, what the reasoning was.
- cortesoft 10y agoI like the sequel gem's syntax even better: Post.where(:id => 1).or(:id => 2)
- stouset 10y agoSequel's syntax is strictly less powerful, since Rails' accepts any scope instead of just a hash of conditions. Post.where(id: 1).or Post.joins(:author).where(author: { name: 'John' })
- cyberferret 10y agoCorrect me if I am wrong, but can't the Sequel ORM accomplish this as well? Post.join(:author).where(:author__name => "John") (the above is purely from memory and may have syntax errors). In any case, it lets you drop into raw SQL as a last resort.
- cortesoft 10y agoYes, you are correct.
- jeremyevans 10y agoThat doesn't appear to work: Post.where(id: 1).or Post.joins(:author).where(author: { name: 'John' }) ArgumentError: Relation passed to #or must be structurally compatible. Incompatible values: [:joins, :references] It appears that only the filter clauses are allowed to be different (similar errors if :select, :order, :group, :limit are different), in which case it's no more powerful than Sequel, just more of a pain to use. You can easily implement ActiveRecord's behavior in Sequel if you want to combine filter clauses for arbitrary datasets: ds = Post.where(id: 2) Post.where(id: 1).or(ds.opts[:where]) It's also interesting what happens if you mix where and having clauses (I'm not saying it doesn't make sense, but it may bite someone): Post.where(id: 1).or(Post.having(id: 2)).to_sql # SELECT "posts".* FROM "posts"
- rabidferret 10y agoI talk about this at length in one of my recent talks but the short version is we wanted to optimize for reuse via named scopes
- bphogan 10y agoYea. I wanted this since Rails 3.
- loramel 10y agoCan not agreed more.