You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@buildr.apache.org by Adam George <at...@googlemail.com> on 2013/05/23 15:11:54 UTC

Correct Use of the 'tap' Method

Hi,

I'm relatively new to Buildr/Ruby and whilst I'm getting the hang of most
things there is still one thing that I don't understand.

Consider this:

        # example 1 (seems to do nothing)
        task(:compile) do |task|
                task.sources = [path_to(:source, :main, :catalina)]
                task.with "org.apache.tomcat:tomcat-catalina:jar:7.0.35",
                        "javax.servlet:servlet-api:jar:2.5"
                task.into(_(:target, :classes, :catalina))
        end

... and this:

        # example 2 (works as expected)
        task(:compile).tap do |task|
                task.sources = [path_to(:source, :main, :catalina)]
                task.with "org.apache.tomcat:tomcat-catalina:jar:7.0.35",
                        "javax.servlet:servlet-api:jar:2.5"
                task.into(_(:target, :classes, :catalina))
        end

Both code blocks receive a task argument that identifies itself as
"my_project:compile" when printed to the console, but I can't understand why
the enhancement in example 1 does nothing to the compile task of my_project.  

I'm comfortable with the fact that I need to use .tap, but I don't really
understand why it's necessary. If both functions are given the same argument
at run time, why does only the second example work?  What is happening in
example 1 in this case?

Thanks and regards,

Adam George


Re: Correct Use of the 'tap' Method

Posted by Adam George <at...@googlemail.com>.
Thanks, Alex, that explains things nicely.  Also, no worries Antoine, you
did draw my attention to the double-tap behaviour after all so it was still
a valuable contribution!

Cheers,

Adam





Re: Correct Use of the 'tap' Method

Posted by Antoine Toulme <an...@lunar-ocean.com>.
Sorry, apologies again for posting misleading info.


On Thu, May 23, 2013 at 10:37 AM, Pepijn Van Eeckhoudt <
pepijn@vaneeckhoudt.net> wrote:

> Is tap in buildr different from Kernel#tap? If not then your explanation
> is a bit misleading.
>
> Invoking tap on an object simply yields that object to the block and
> returns that object. I use this now and then to create a new scope which
> avoids cluttering methods with local variables. See
> http://ruby-doc.org/core-2.0/Object.html#method-i-tap for details.
>
> Pepijn
>
> Op 23-mei-2013 om 17:23 heeft Antoine Toulme <an...@lunar-ocean.com>
> het volgende geschreven:
>
> > This is more of a Rake question actually. Rake provides ways for you to
> > define tasks.
> > So when you type task(:compile) do |task| ... you are actually redefining
> > the compile task. That's why it's doing nothing.
> >
> > Rake provides a way to define task dependencies as tasks. Buildr builds
> on
> > this by adding the tap method which lets you add a dependent task
> directly
> > on the compile task. tap inserts the dependency as the first item in the
> > list, so if you tap twice, the second time will execute before the first
> > time.
> >
> > I hope this helps.
> >
> >
> > On Thu, May 23, 2013 at 6:11 AM, Adam George <at...@googlemail.com>
> wrote:
> >
> >> Hi,
> >>
> >> I'm relatively new to Buildr/Ruby and whilst I'm getting the hang of
> most
> >> things there is still one thing that I don't understand.
> >>
> >> Consider this:
> >>
> >>        # example 1 (seems to do nothing)
> >>        task(:compile) do |task|
> >>                task.sources = [path_to(:source, :main, :catalina)]
> >>                task.with "org.apache.tomcat:tomcat-catalina:jar:7.0.35",
> >>                        "javax.servlet:servlet-api:jar:2.5"
> >>                task.into(_(:target, :classes, :catalina))
> >>        end
> >>
> >> ... and this:
> >>
> >>        # example 2 (works as expected)
> >>        task(:compile).tap do |task|
> >>                task.sources = [path_to(:source, :main, :catalina)]
> >>                task.with "org.apache.tomcat:tomcat-catalina:jar:7.0.35",
> >>                        "javax.servlet:servlet-api:jar:2.5"
> >>                task.into(_(:target, :classes, :catalina))
> >>        end
> >>
> >> Both code blocks receive a task argument that identifies itself as
> >> "my_project:compile" when printed to the console, but I can't understand
> >> why
> >> the enhancement in example 1 does nothing to the compile task of
> >> my_project.
> >>
> >> I'm comfortable with the fact that I need to use .tap, but I don't
> really
> >> understand why it's necessary. If both functions are given the same
> >> argument
> >> at run time, why does only the second example work?  What is happening
> in
> >> example 1 in this case?
> >>
> >> Thanks and regards,
> >>
> >> Adam George
> >>
> >>
>

Re: Correct Use of the 'tap' Method

Posted by Pepijn Van Eeckhoudt <pe...@vaneeckhoudt.net>.
Is tap in buildr different from Kernel#tap? If not then your explanation is a bit misleading.

Invoking tap on an object simply yields that object to the block and returns that object. I use this now and then to create a new scope which avoids cluttering methods with local variables. See http://ruby-doc.org/core-2.0/Object.html#method-i-tap for details.

Pepijn

Op 23-mei-2013 om 17:23 heeft Antoine Toulme <an...@lunar-ocean.com> het volgende geschreven:

> This is more of a Rake question actually. Rake provides ways for you to
> define tasks.
> So when you type task(:compile) do |task| ... you are actually redefining
> the compile task. That's why it's doing nothing.
> 
> Rake provides a way to define task dependencies as tasks. Buildr builds on
> this by adding the tap method which lets you add a dependent task directly
> on the compile task. tap inserts the dependency as the first item in the
> list, so if you tap twice, the second time will execute before the first
> time.
> 
> I hope this helps.
> 
> 
> On Thu, May 23, 2013 at 6:11 AM, Adam George <at...@googlemail.com> wrote:
> 
>> Hi,
>> 
>> I'm relatively new to Buildr/Ruby and whilst I'm getting the hang of most
>> things there is still one thing that I don't understand.
>> 
>> Consider this:
>> 
>>        # example 1 (seems to do nothing)
>>        task(:compile) do |task|
>>                task.sources = [path_to(:source, :main, :catalina)]
>>                task.with "org.apache.tomcat:tomcat-catalina:jar:7.0.35",
>>                        "javax.servlet:servlet-api:jar:2.5"
>>                task.into(_(:target, :classes, :catalina))
>>        end
>> 
>> ... and this:
>> 
>>        # example 2 (works as expected)
>>        task(:compile).tap do |task|
>>                task.sources = [path_to(:source, :main, :catalina)]
>>                task.with "org.apache.tomcat:tomcat-catalina:jar:7.0.35",
>>                        "javax.servlet:servlet-api:jar:2.5"
>>                task.into(_(:target, :classes, :catalina))
>>        end
>> 
>> Both code blocks receive a task argument that identifies itself as
>> "my_project:compile" when printed to the console, but I can't understand
>> why
>> the enhancement in example 1 does nothing to the compile task of
>> my_project.
>> 
>> I'm comfortable with the fact that I need to use .tap, but I don't really
>> understand why it's necessary. If both functions are given the same
>> argument
>> at run time, why does only the second example work?  What is happening in
>> example 1 in this case?
>> 
>> Thanks and regards,
>> 
>> Adam George
>> 
>> 

Re: Correct Use of the 'tap' Method

Posted by Alex Boisvert <al...@gmail.com>.
On Thu, May 23, 2013 at 10:05 AM, Adam George <at...@googlemail.com> wrote:

> If "task :foo do ..." enhances the "foo" task successfully, then why does
> "task :compile do ..." seemingly not run in addition to the original
> "compile" task?
>

It's a matter of timing.

When using ".tap" the block executes right away (typically while 'parsing'
the buildfile).

When using  "task ... do" the block will execute if/when the task executes
(and after all previously defined logic on the task) so if you're
configuring the task, it's already too late because the gist of the task
execution has already happened.

alex

PS: Yes, the .tap method is the same behavior as Kernel#tap.

Re: Correct Use of the 'tap' Method

Posted by Adam George <at...@googlemail.com>.
Alex Boisvert <al...@...> writes:

> 
> Actually, the behavior of task ... do is to enhance the task.
> 
> For instance, if you have a Rakefile or Buildfile with,
> 
> task :foo do
>   puts 'foo1'
> end
> 
> task :foo do
>   puts 'foo2'
> end
> 
> and run rake foo, you'd get:
> 
> foo1
> foo2
> 

Thanks, Alex.

This corresponds with my original understanding, which is why I was confused
in the first place.

If "task :foo do ..." enhances the "foo" task successfully, then why does
"task :compile do ..." seemingly not run in addition to the original
"compile" task?

Maybe the problem is to do with my expectations of enhancement.  The
impression I have is that it's basically like overriding a method from a
super class but also calling super.method(args) as part of the overridden
method to extend the functionality rather than redefine it.  Please correct
me if I'm wrong about this.

Thanks again,

Adam



Re: Correct Use of the 'tap' Method

Posted by Antoine Toulme <an...@lunar-ocean.com>.
Apologies. I need a Rake refresher.


On Thu, May 23, 2013 at 9:19 AM, Alex Boisvert <al...@gmail.com>wrote:

> Actually, the behavior of task ... do is to enhance the task.
>
> For instance, if you have a Rakefile or Buildfile with,
>
> task :foo do
>   puts 'foo1'
> end
>
> task :foo do
>   puts 'foo2'
> end
>
> and run rake foo, you'd get:
>
> foo1
> foo2
>
>
>
> On Thu, May 23, 2013 at 9:10 AM, Adam George <at...@googlemail.com>
> wrote:
>
> > Antoine Toulme <an...@...> writes:
> >
> > >
> > > This is more of a Rake question actually. Rake provides ways for you to
> > > define tasks.
> > > So when you type task(:compile) do |task| ... you are actually
> redefining
> > > the compile task. That's why it's doing nothing.
> > >
> > > Rake provides a way to define task dependencies as tasks. Buildr builds
> > on
> > > this by adding the tap method which lets you add a dependent task
> > directly
> > > on the compile task. tap inserts the dependency as the first item in
> the
> > > list, so if you tap twice, the second time will execute before the
> first
> > > time.
> > >
> > > I hope this helps.
> > >
> >
> > Hi Antoine,
> >
> > Thanks, that does make some sense, and it's useful to know about the
> > double-tapping!  However, I am now confused about how the compile task
> > worked at all if I was redefining it.
> >
> > In example 1 (without .tap) the compilation was still working with the
> > default behaviour (compiling from src/main/java).  How is this possible
> if
> > the task has been redefined to be something else by my code?
> >
> > Thanks,
> >
> > Adam
> >
> >
> >
>

Re: Correct Use of the 'tap' Method

Posted by Alex Boisvert <al...@gmail.com>.
Actually, the behavior of task ... do is to enhance the task.

For instance, if you have a Rakefile or Buildfile with,

task :foo do
  puts 'foo1'
end

task :foo do
  puts 'foo2'
end

and run rake foo, you'd get:

foo1
foo2



On Thu, May 23, 2013 at 9:10 AM, Adam George <at...@googlemail.com> wrote:

> Antoine Toulme <an...@...> writes:
>
> >
> > This is more of a Rake question actually. Rake provides ways for you to
> > define tasks.
> > So when you type task(:compile) do |task| ... you are actually redefining
> > the compile task. That's why it's doing nothing.
> >
> > Rake provides a way to define task dependencies as tasks. Buildr builds
> on
> > this by adding the tap method which lets you add a dependent task
> directly
> > on the compile task. tap inserts the dependency as the first item in the
> > list, so if you tap twice, the second time will execute before the first
> > time.
> >
> > I hope this helps.
> >
>
> Hi Antoine,
>
> Thanks, that does make some sense, and it's useful to know about the
> double-tapping!  However, I am now confused about how the compile task
> worked at all if I was redefining it.
>
> In example 1 (without .tap) the compilation was still working with the
> default behaviour (compiling from src/main/java).  How is this possible if
> the task has been redefined to be something else by my code?
>
> Thanks,
>
> Adam
>
>
>

Re: Correct Use of the 'tap' Method

Posted by Adam George <at...@googlemail.com>.
Antoine Toulme <an...@...> writes:

> 
> This is more of a Rake question actually. Rake provides ways for you to
> define tasks.
> So when you type task(:compile) do |task| ... you are actually redefining
> the compile task. That's why it's doing nothing.
> 
> Rake provides a way to define task dependencies as tasks. Buildr builds on
> this by adding the tap method which lets you add a dependent task directly
> on the compile task. tap inserts the dependency as the first item in the
> list, so if you tap twice, the second time will execute before the first
> time.
> 
> I hope this helps.
> 

Hi Antoine,

Thanks, that does make some sense, and it's useful to know about the
double-tapping!  However, I am now confused about how the compile task
worked at all if I was redefining it.

In example 1 (without .tap) the compilation was still working with the
default behaviour (compiling from src/main/java).  How is this possible if
the task has been redefined to be something else by my code?

Thanks,

Adam



Re: Correct Use of the 'tap' Method

Posted by Antoine Toulme <an...@lunar-ocean.com>.
This is more of a Rake question actually. Rake provides ways for you to
define tasks.
So when you type task(:compile) do |task| ... you are actually redefining
the compile task. That's why it's doing nothing.

Rake provides a way to define task dependencies as tasks. Buildr builds on
this by adding the tap method which lets you add a dependent task directly
on the compile task. tap inserts the dependency as the first item in the
list, so if you tap twice, the second time will execute before the first
time.

I hope this helps.


On Thu, May 23, 2013 at 6:11 AM, Adam George <at...@googlemail.com> wrote:

> Hi,
>
> I'm relatively new to Buildr/Ruby and whilst I'm getting the hang of most
> things there is still one thing that I don't understand.
>
> Consider this:
>
>         # example 1 (seems to do nothing)
>         task(:compile) do |task|
>                 task.sources = [path_to(:source, :main, :catalina)]
>                 task.with "org.apache.tomcat:tomcat-catalina:jar:7.0.35",
>                         "javax.servlet:servlet-api:jar:2.5"
>                 task.into(_(:target, :classes, :catalina))
>         end
>
> ... and this:
>
>         # example 2 (works as expected)
>         task(:compile).tap do |task|
>                 task.sources = [path_to(:source, :main, :catalina)]
>                 task.with "org.apache.tomcat:tomcat-catalina:jar:7.0.35",
>                         "javax.servlet:servlet-api:jar:2.5"
>                 task.into(_(:target, :classes, :catalina))
>         end
>
> Both code blocks receive a task argument that identifies itself as
> "my_project:compile" when printed to the console, but I can't understand
> why
> the enhancement in example 1 does nothing to the compile task of
> my_project.
>
> I'm comfortable with the fact that I need to use .tap, but I don't really
> understand why it's necessary. If both functions are given the same
> argument
> at run time, why does only the second example work?  What is happening in
> example 1 in this case?
>
> Thanks and regards,
>
> Adam George
>
>