Add a visitor to enable checking if a relation #would_include? an object... #210

Closed
wants to merge 1 commit into
from

3 participants

@shoe

....

This provides a mechanism to check, without actually executing a
query, whether a given object matches the conditions represented by
the WHERE clause of a relation.

This is useful in several cases.

Example 1: When you can avoid re-executing a query by knowing whether
or not a record you just inserted would be returned if the query were
to be re-executed. (e.g. Cache invalidation)

Example 2: When you are storing or manipulating conditions as
first-class entities, as done by https://github.com/ernie/ransack and
want know which of many queries would return a given object, without
executing each query.

Example 3: When you're already representing a complex condition as an
arel relation, and want to avoid duplication of code that would
re-implement the same condition in ruby as a predicate instance
method. e.g. ActiveRecord example:

scope :active, -> { where(state: 'active')}

def active?
  state == 'active'
end

You would now be able to write: User.active.would_include?(user)

@shoe shoe Add a visitor to enable checking if a relation #would_include? an obj…
…ect.

This provides a mechanism to check, without actually executing a
query, whether a given object matches the conditions represented by
the WHERE clause of a relation.

This is useful in several cases.

Example 1: When you can avoid re-executing a query by knowing whether
or not a record you just inserted would be returned if the query were
to be re-executed.  (e.g. Cache invalidation)

Example 2: When you are storing or manipulating conditions as
first-class entities, as done by https://github.com/ernie/ransack and
want know which of many queries would return a given object, without
executing each query.

Example 3: When you're already representing a complex condition as an
arel relation, and want to avoid duplication of code that would
re-implement the same condition in ruby as a predicate instance
method.  e.g. ActiveRecord example:

    scope :active, -> { where(state: 'active')}

    def active?
      state == 'active'
    end

You would now be able to write: User.active.would_include?(user)
f18b374
@ernie

Thought I should probably post our discussion via e-mail here, so @tenderlove is in the loop as well.


On Wed, Oct 9, 2013 at 11:03 AM, Ernie Miller ernie@erniemiller.org wrote:

Hey Chris,

I'll take a look. At first glance, I'm not entirely sure it makes sense for inclusion in Arel as we've moved away from the general relational algebra stuff and toward building SQL as the only goal of the project. Also, I'm not sure it's enough to simply check the where clause. There's the having clause to consider, and joins, where the join condition might potentially limit the result set... A lot of complexity here. :(

-Ernie


On Oct 9, 2013, at 2:06 PM, Chris Shoemaker chris@mojotech.com wrote:

Hi Ernie,

Thanks for taking a look. You're right that the having, joins, limit, offset could affect whether the record would be returned, so I explicitly warn about all those being unsupported and raise an error.

In the three use-cases we've encountered here, those nodes aren't needed, but I could imagine a condition on a inner-joined table might be something somebody would want to support.

For the original use-case that prompted this - ransack - I think it handles the all the "stock" query conditions except for conditions on associations, right?


It should, yeah. I think my big concern is that if we introduce something like this, the floodgates open to a whole lot of people asking for enhancements to it. It's the proverbial foot in the door, so to speak.

@sheerun

I don't think it should be implemented at Arel level. This can be some kind of middleware that mimics RMDB and caches rows in memory but almost certainly Arel is not about answering queries, but creating them. There can be many cases we could skip db lookup and implementing all of them in Arel is not a solution, it introduces much complexity. This should be a separate gem or extension to Arel.

@ernie

Yeah, I think that's where we're landing, here. Sorry! :(

@ernie ernie closed this Oct 25, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment