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: GitHub - activerecord-hackery/meta_where at 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: GitHub - activerecord-hackery/meta_where at 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: