Sorry for the double post, but I came up with arel:

    
people.project(:id).join(services).on(services[:person_id].eq(people[:id])).where(services[:type].eq(1)).intersect(
      
people.project(:id).join(services).on(services[:person_id].eq(people[:id])).where(services[:type].eq(2)))

calling to_sql on that yields the following:

( SELECT id 
  FROM `people` INNER JOIN `services` ON `services`.`person_id` = 
`people`.`id` 
  WHERE `services`.`type` = 1
  INTERSECT 
  SELECT id 
  FROM `people` INNER JOIN `services` ON `services`.`person_id` = 
`people`.`id` 
  WHERE `services`.`type` = 2 )

that won't work on mysql. Maybe it's an arel bug, I don't know. Anyway, I 
think active record should implement & and | methods.

PS: I used a one-to-many relationship when writing arel code, only for 
simplicity sake (it saves me a lot of typing).

On Friday, August 10, 2012 12:42:23 AM UTC-3, Rafael Almeida wrote:
>
> I studied Squeel a bit, the best I could do was this:
>
>     Person.joins{services}.where{
>       id.in(Person.joins{services}.where{services.type == 1}.select{id})
>       & id.in(Person.joins{services}.where{services.type == 
> 2}.select{id})}
>
> which is both unefficient and very ugly.
>
> I think it would be much better if & was implemented in Relation class. It 
> seems like & used to be an alias to merge and that was dropped. That's nice 
> because & and merge are indeed different. But why not properly implement & 
> using DBMS's INTERSECTION (or doing some workaround such as 
> http://www.bitbybit.dk/carsten/blog/?p=71 on those dbms that don't 
> support INTERSECTION)?
>
> If we had such implementation, then what I want would be as simple (and 
> pretty) as:
>
>     Person.joins(:services).where('services.type' => 1) 
> & Person.joins(:services).where('services.type' => 2)
>
> that works today, but as I said, it returns an Array and not a Relation.
>
> I'm not good with arel yet (I haven't found much documentation on the 
> topic yet). So I'm not sure if it can be done with it. I recall that, while 
> I was playing with it a while back, I was able to do make it generate the 
> query with INTERSECT, but it didn't work with mysql. So maybe there's still 
> work to do in arel's side.
>
> On Wednesday, August 8, 2012 2:27:14 PM UTC-3, Pedro Nascimento wrote:
>>
>> Take a look at ARel and Squeel gem. Squeel gem supports something like 
>> this already.
>>
>> On Wed, Aug 8, 2012 at 12:05 PM, Rafael Almeida <[email protected]>wrote:
>>
>>> Hello.
>>>
>>> Let's say I have the following schema
>>>
>>>     People <---> people_services <---> services
>>>
>>> That is, people has a many-to-many relationship with services. Say I 
>>> want to find all people who has services of types 1 and 2. How can we do it 
>>> on activerecord today?
>>>
>>> My best solution so far is this
>>>
>>>     people_query = Person.joins(:services)
>>>     people = []
>>>     [1,2].each do |t|
>>>         people << people_query.where(:type => 1)
>>>     end
>>>     people = people.reduce(:&)
>>>
>>> That's not so good because by doing reduce(:&) you're exiting 
>>> activerecord domain. So you wouldn't be able to do something like 
>>> people.reduce(:&).limit(10). Also, that way I'm loading a lot more data 
>>> than I actually need in my application memory. So, certainly not optimal 
>>> solution.
>>>
>>> It's possible to make such query in SQL alone, if the dbms supports 
>>> INTERSECTION then doing it is straightforward. If it doesn't, it's still 
>>> possible using joins on subqueries.
>>>
>>> I think activerecord ought support such query and I'm willing to take my 
>>> time and write the code for it. However, I'd like someone to help me out 
>>> with it a bit. I don't understand rails or activerecord code base so well. 
>>> Anyway, it would be best if I did a gem that introduces that feature into 
>>> activerecord. Can anyone tell me what should I look up? A high level 
>>> description of what I must do would be great. Something like "You'll need 
>>> to create a gem, monkey patch this activerecord class, probably use this 
>>> and this function to help you writing your SQL" would be nice.
>>>
>>> Cheers
>>>
>>> -- 
>>> You received this message because you are subscribed to the Google 
>>> Groups "Ruby on Rails: Core" group.
>>> To view this discussion on the web visit 
>>> https://groups.google.com/d/msg/rubyonrails-core/-/jz3f6lJrXEkJ.
>>> To post to this group, send email to [email protected].
>>> To unsubscribe from this group, send email to 
>>> [email protected].
>>> For more options, visit this group at 
>>> http://groups.google.com/group/rubyonrails-core?hl=en.
>>>
>>
>>

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Core" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/rubyonrails-core/-/9t0fM-NiDdEJ.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-core?hl=en.

Reply via email to