New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feedback] Implement Relation#or #18706

Closed
wants to merge 4 commits into
base: master
from

Conversation

Projects
None yet
5 participants
@sgrif
Member

sgrif commented Jan 27, 2015

This is an idea for another implementation of Relation#or, in order to
address some of the API concerns for the previous APIs. In order to make
it clear what is being changed on the relation, the result is explictly
passed to either where or having. This also removes the need to
check for "structural compatibility", since you've told us what you're
looking to use from either one. If you give two relations that don't
make sense together, it's no different than passing column names to
where that don't make sense, and will result in an
ActiveRecord::StatementInvalid.

Additionally, any arguments which would be valid to where or having
are valid arguments to or, as well, to allow for a slightly lighter
weight alternative.

Examples:

def self.for_homepage
  where(active.or(pinned))
end

def self.for_homepage
  where(active.or(pinned: true))
end

/cc @matthewd

[Feedback] Implement Relation#or
This is an idea for another implementation of `Relation#or`, in order to
address some of the API concerns for the previous APIs. In order to make
it clear what is being changed on the relation, the result is explictly
passed to either `where` or `having`. This also removes the need to
check for "structural compatibility", since you've told us what you're
looking to use from either one. If you give two relations that don't
make sense together, it's no different than passing column names to
`where` that don't make sense, and will result in an
`ActiveRecord::StatementInvalid`.

Additionally, any arguments which would be valid to `where` or `having`
are valid arguments to `or`, as well, to allow for a slightly lighter
weight alternative.
@egilburg

This comment has been minimized.

Contributor

egilburg commented Jan 28, 2015

If active is itself a where statement, would your example be equilvalent to this?:

scope :for_homepage, ->{ active.or(pinned: true) }

And can this be generalized to any where chain?:

scope :for_homepage, ->{ where(pinned: true).or(active: true) }
@sgrif

This comment has been minimized.

Member

sgrif commented Jan 28, 2015

Both of your examples assume that or can only apply to where, but it could also apply to having. There were also concerns that having Relation#or be meaningful on its own read more like it was constructing a union query, than modifying the predicates. We also become ambiguous about what is getting merged from the other relation. By returning an object that must be passed to where or having, we clear up all of those ambiguities.

@senny senny added the activerecord label Jan 28, 2015

@senny senny added this to the 5.0.0 milestone Jan 28, 2015

@senny

This comment has been minimized.

Member

senny commented Jan 28, 2015

For reference, these are alternative PR's with different API's:

  • #16052 Post.where('id = 1').or(Post.where('id = 2'))
  • #9052 Post.where("id = 1").or.where("id = 2")
@jiripospisil

This comment has been minimized.

Contributor

jiripospisil commented Jan 28, 2015

There's also #10891 (extracted as activerecord_any_of).

User.where.any_of(name: 'Doe', active: true)
# => SELECT * FROM users WHERE name = 'Doe' OR active = '1'
@sgrif

This comment has been minimized.

Member

sgrif commented Jan 28, 2015

Closing in favor of #16052

@sgrif sgrif closed this Jan 28, 2015

@bf4 bf4 referenced this pull request Sep 22, 2015

Open

Add 'things I link to' #7

@rafaelfranca rafaelfranca modified the milestones: 5.0.0 [temp], 5.0.0 Dec 30, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment