release more Arel power?

Hello,

I just learned that Arel support more powerful queries than in rails, e.g.

users = Arel::Table.new(‘users’)
users.where( (users[:id].eq(1)).or(users[:id].eq(2)) )

In rails it will be

User.where( (User.arel_table[:id].eq(1)).or(User.arel_table[:id].eq(2))) )

Which is too complex. DAE think it’s a good to have a convinient way to express above query in rails? maybe like this:

User.where(:id.eq(1).or.(:id.eq(2)))
or
User.where(:id => 1).or.where(:id => 2)
?

Or such a way already exists? If no, why not?

Regards
Jan

Check out the meta_where gem: https://github.com/ernie/meta_where

That’s awesome, thanks :slight_smile:

Now I just wonder why it’s not in rails by default?

I’ve been discussed the possibility of exposing ARel power with the core team too, and found out that they thing ARel API is not mature enough to be exposed. Maybe we should wait :slight_smile:

In another hand, they don’t like the extending hash for this apparent reason so I’m pretty sure you won’t see it in the future release unless you can convince them that it’s more elegant. Using that metawhere gem is you way to go :slight_smile:

Prem

I'll third the recommendation for MetaWhere, though I may be biased. :slight_smile:

I assume that when you mentioned extending Hash, you meant extending
Symbol. I know a number of rubyists are vehemently opposed to such
extensions, though I've never really been sure of why. I can assume
that it's because extending symbol in this way treats it as something
of an extra global namespace and that strictly from an OO purity
perspective, hanging factory methods off of symbol is considered
unsavory. That, or it has something to do with symbols not being
garbage collected and such methods encouraging/necessitating extra use
of symbols -- irrelevant in this context since hash keys are already
symbols in most cases.

Anyway, I'd contend that that from a practical perspective, "freedom
patching" in this manner makes a lot of sense. Granted, the argument
will be easier once we have module refinement, but in the meantime,
is it really that likely that your app is going to have a better use
for something like Symbol#matches than to get an ARel Matches node?

In any case, it's been working out alright for the DataMapper guys for
a while now, and I've not heard any reports of anarchy, cats sleeping
with dogs, etc...

Yes, I meant to say symbol :slight_smile:

Hi Ernie, although I like this approach or extending symbols for easying the queries, I don't think this would be great to be included inside any framework. This could be enabled in a per-basis application but if it happen that you depend on another library that also needs symbols to be extended in a conflicting way, this would lead to problems. Until Ruby provides us some way of limitating the use of some modules per context, I think that extending symbols that way is not the way to go with current Ruby specification since it can lead to incompatibilities among libraries relying on some symbol operators/methods that could be defined in different ways.

What I'm saying is that I would be happy using your meta_where gem on my applications, while I would not be comfortable with it being included in ActiveRecord.

Best regards and thank you for your gem!

Rodrigo.

is it really that likely that your app is going to have a better use
for something like Symbol#matches than to get an ARel Matches node?

Case-in-point: the mongoid gem defines Symbol#matches. Libraries that do this have a myopic view of the world.

Chris

Wouldn't it be possible to implement the sexy api with blocks ?

var = 12

# meta_where
User.where(:id.gt > var)

# another implementation
User.condition { id.gt > var }

Evaluate the the block in different scope in which title method would
be definied to return some object responding to :gt, :lt and other
nice methods...

If that's possible, maybe that's our goal ?

Robert Pankowecki

DataMapper has moved away from core patching (as we too think it’s a bad idea). The symbol extensions that monkey patch core are opt-in now for legacy support, and i (amongst others) think it should go away all together. DataMapper’s extended key support can also be had through string based keys like “property.matcher” => “value”.

Cheers,

-Ted

I actually fiddled around with this in my current work on a rewrite of MetaWhere. The problem is that once you start looking to handle nested associations and the like, things start looking pretty ridiculously verbose. Couldn't come up with a DSL I liked.

Maybe. I see libraries doing this as not much different than ActiveSupport extending Object. So long as you're able to opt in or out (in MetaWhere, this is by choosing to use the gem -- in AR, it would be a configuration option) then there's no harm done. There are certainly plenty of use cases for mixing and matching ORMs for different backend data stores, but I would say that the person setting out to do so has some pretty compelling reasons for doing so, understands their libraries, and is more than capable of dealing with any potential conflicts such as this.

Some defensive coding by library authors (falling back to a pseudo-namespaced method in the event the other method is already taken, for instance) makes sure the functionality is exposed even in the event of a method name conflict.

This debate becomes largely a non-issue when we get module refinements, but in the meantime I can't help but feel an arbitrary stance against such things is throwing the baby out with the bath water.

(off topic: this discussion is good to see, as I will be taking it into account on the metawhere rewrite)

Personally, I really dislike the noise of the string-based solution. I'll be taking another look at a block-based alternative.

I'm really glad we all work with a language that gives us so much flexibility, though!

Sequel does this and it seems to work out.

Jack

(off topic: this discussion is good to see, as I will be taking it into account on the metawhere rewrite)

So, since this thread and another are currently ongoing relating to complex queries and the handling of ARel predicates, I thought I’d make a quick announcement that the MetaWhere rewrite-in-progress for Rails 3.1 is up on GitHub and actively being worked on: https://github.com/ernie/meta_where/tree/rewrite

Specifically as a result of this thread, I’ve made core extensions opt-in, and am adding block syntax for those Relation methods where it makes sense. Hopefully this will alleviate some of the Symbol extension gripes that came up here. For example:

SQL Functions:

Person.select{max(id).as(max_id)}

=> SELECT max(“people”.“id”) AS ‘max_id’ FROM “people”

ANDs and association mapping:

Person.joins(:comments).

where{name >> ‘bob’ & {comments => body >> ‘First post!’}}

=> SELECT “people”.* FROM “people”

INNER JOIN “comments” ON “comments”.“person_id” = “people”.“id”

WHERE ((“people”.“name” = ‘bob’ AND “comments”.“body” = ‘First post!’))

The same query with an OR:

Person.joins(:comments).

where{name >> ‘bob’ | {comments => body >> ‘First post!’}}

=> SELECT “people”.* FROM “people”

INNER JOIN “comments” ON “comments”.“person_id” = “people”.“id”

WHERE ((“people”.“name” = ‘bob’ OR “comments”.“body” = ‘First post!’))

Could also be written as:

Person.joins(:comments).

where{name.eq(‘bob’) | {comments => body.eq(‘First post!’)}}

You get the idea. I’m still tweaking the operators, not so sure about >> for eq.

Anyway, this is the last MetaWhere-related post I’ll make – I just thought it might give a plugin option to those people who are looking for a way to get at the ARel goodness in AR and don’t want to wait on something in core.

-Ernie

(off topic: this discussion is good to see, as I will be taking it into
account on the metawhere rewrite)

So, since this thread and another are currently ongoing relating to complex
queries and the handling of ARel predicates, I thought I'd make a quick
announcement that the MetaWhere rewrite-in-progress for Rails 3.1 is up on
GitHub and actively being worked on:
https://github.com/ernie/meta_where/tree/rewrite
Specifically as a result of this thread, I've made core extensions opt-in,
and am adding block syntax for those Relation methods where it makes sense.
Hopefully this will alleviate some of the Symbol extension gripes that came
up here. For example:

SQL Functions:
Person.select{max(id).as(max_id)}
=> SELECT max("people"."id") AS 'max_id' FROM "people"

ANDs and association mapping:
Person.joins(:comments).
where{name >> 'bob' & {comments => body >> 'First post!'}}
=> SELECT "people".* FROM "people"
INNER JOIN "comments" ON "comments"."person_id" = "people"."id"
WHERE (("people"."name" = 'bob' AND "comments"."body" = 'First post!'))
The same query with an OR:
Person.joins(:comments).
where{name >> 'bob' | {comments => body >> 'First post!'}}
=> SELECT "people".* FROM "people"
INNER JOIN "comments" ON "comments"."person_id" = "people"."id"
WHERE (("people"."name" = 'bob' OR "comments"."body" = 'First post!'))

Could also be written as:
Person.joins(:comments).
where{name.eq('bob') | {comments => body.eq('First post!')}}
You get the idea. I'm still tweaking the operators, not so sure about >> for
eq.

The >> definitely weirds me out.

I haven't looked at the source, but why aren't you overriding ==? (a
link to rtfm is fine, I'm just lazy :))

Honestly, I don't know. I thought about it, but something about overriding == even in this block context seemed weird. I'll give it a try and see if it adversely affects anything but my specs. :slight_smile: