On 9/20/07, Sharon Rosner <ciconia / gmail.com> wrote:
> Hi gang
>
> I've stumbled upon a weird phenomenon when trying nested Dataset#query
> methods with Sequel:
>
>   ds = DB[:items].query do
>     select :x, :y
>     where :x => DB[:stuff].query do
>       select :a
>       where :b => DB[:misc].query do
>         select :c
>         where :d => true
>       end
>     end
>   end
>
>   #=> /usr/local/lib/ruby/gems/1.8/gems/sequel-0.2.0.2/lib/sequel/../
> sequel/dataset/convenience.rb:217:in `instance_eval': block not
> supplied (ArgumentError)
>
> If I enclose the nested procs in parens everything works fine:
>
>   ds = DB[:items].query do
>     select :x, :y
>     where :x => (DB[:stuff].query do
>       select :a
>       where :b => (DB[:misc].query do
>         select :c
>         where :d => true
>       end)
>     end)
>   end
>
> It also works if I use the curly brackets notation:
>
>   ds = DB[:items].query {
>     select :x, :y
>     where :x => DB[:stuff].query {
>       select :a
>       where :b => DB[:misc].query {
>         select :c
>         where :d => true
>       }
>     }
>   }
>
> Is the error above the intended behavior? If it is, can someone
> explain what's going on?

It's a matter of the operator precedence of do and {}.

Braces bind more strongly than do  (In general in Ruby symbols bind
tighter than keywords)

irb(main):001:0> def m1(arg)
irb(main):002:1>   puts "m1 got block" if block_given?
irb(main):003:1> end
=> nil
irb(main):004:0> def m2
irb(main):005:1>   puts "m2 got block" if block_given?
irb(main):006:1> end
=> nil
irb(main):007:0> m1 m2 {}
m2 got block
=> nil
irb(main):008:0> m1 m2 do;end
m1 got block
=> nil

So in the expression

   where :x => DB[:stuff].query do;end

The block is being given to the where method instead of the query method.

-- 
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/