# Rake rules question

**URL:** <https://www.ruby-forum.com/t/rake-rules-question/55108>\
**Category:** Ruby\
**Created:** [March 17, 2006, 12:45am UTC](https://www.ruby-forum.com/t/rake-rules-question/55108 "2006-03-17T00:45:47Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![itsme213](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/258eb7/32.png) [@itsme213](https://www.ruby-forum.com/u/itsme213)\
**Post date:** [March 17, 2006, 12:45am UTC](https://www.ruby-forum.com/t/rake-rules-question/55108/1 "2006-03-17T00:45:47Z")

</div>

I am using RMagick to do multi-stage processing of some images.

Can I have two different rules to process .PNG files in two different  
directories?

rule stage\_0/_.png =\> source/_.png do |t|  
make\_0 t.source, t.name  
end

rule stage\_1/_.png =\> stage\_0/_.png do |t|  
make\_1 t.source, t.name  
end

I can’t seem to get this to work, and don’t know if it is supposed to.

Thanks.

---

<div class="post-metadata">

**Author:** ![itsme213](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/258eb7/32.png) [@itsme213](https://www.ruby-forum.com/u/itsme213)\
**Post date:** [March 17, 2006, 4:20am UTC](https://www.ruby-forum.com/t/rake-rules-question/55108/2 "2006-03-17T04:20:07Z")

</div>

Jim W. wrote:  
[… Rakefile example elided …]

There are some extra lines of dashes in that Rakefile example. I swear  
they weren’t there when I pressed send. Oh well, hopefully that will  
get you started.

–  
– Jim W.

---

<div class="post-metadata">

**Author:** ![itsme213](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/258eb7/32.png) [@itsme213](https://www.ruby-forum.com/u/itsme213)\
**Post date:** [March 17, 2006, 4:17am UTC](https://www.ruby-forum.com/t/rake-rules-question/55108/3 "2006-03-17T04:17:54Z")

</div>

itsme213 wrote:

> I am using RMagick to do multi-stage processing of some images.
> 
> Can I have two different rules to process .PNG files in two different  
> directories?
> 
> rule stage\_0/_.png =\> source/_.png do |t|  
> make\_0 t.source, t.name  
> end
> 
> rule stage\_1/_.png =\> stage\_0/_.png do |t|  
> make\_1 t.source, t.name  
> end
> 
> I can’t seem to get this to work, and don’t know if it is supposed to.

It will work. The attached Rakefile will demonstrate the principle.  
Basically, if you want your rules to trigger on something other than  
simple file extenstions, you need to write them in this format:

rule(REGEX =\> LAMBDA\_TRANSFORMER) do  
ACTIONS  
end

The REGEX should match the thing your are trying to build. The  
LAMBDA\_TRANSFORMER is just a lambda expression with a single input that  
transforms the name of the target (i.e. whatever was matched by the  
REGEX) into the target of the task (i.e. the thing the rule is to  
produce).

For example, your regex might be %r{stage1/.\*.png$} to match a file  
that should be in stage 1. Your lambda could be

lambda { |fn| fn.sub(/^stage1/, ‘source’) }

Make appropriate changes for the stage1 to stage2 work.

If you find rules confusing, an alternative is dynamically generate the  
tasks in a list. For example:

```
SRC_FILES = FileList['source/*.png']

SRC_FILES.each do |fn|
  stage1 = fn.sub(/^source/, 'stage1')
  stage2 = fn.sub(/^source/, 'stage2')
  task stage1 => stage2 do
    do_stage_one_transform(fn, stage1)
  end
  task stage2 => stage1 do
    do_stage_two_transform(stage2, stage1)
  end
end

```

In many ways this is easier than rules and just as flexible.

Anyways, here is the example Rakefile using rules:

* * *

#!/usr/bin/env ruby

require ‘rake/clean’

CLOBBER.include ‘stage1’, ‘stage2’

task :default =\> %w(stage1 stage2 stage2/a.png)

## directory ‘stage1’ directory ‘stage2’

rule(%r{^stage1/.\*.png$} =\> lambda { |fn| fn.sub(/^stage1/, ‘source’)  
}) do |t|  
File.open(t.source) do |ins|  
File.open(t.name, “w”) do |outs|  
outs.write ins.read  
outs.puts “Added to stage one”  
end  
end  
end

## rule(%r{^stage2/.\*.png$} =\> lambda { |fn| fn.sub(/^stage2/, ‘stage1’) }) do |t| File.open(t.source) do |ins| File.open(t.name, “w”) do |outs| outs.write ins.read outs.puts “Added to stage two” end end end

# Other tasks --------------------------------------------------------

task :init =\> :clobber do  
File.open(“source/a.png”, “w”) do |outs|  
outs.puts “A PNG FILE”  
end  
end

## task :see do puts “-- Contents of source/a.png -------------------------------” puts File.read(“source/a.png”) puts “-- Contents of stage2/a.png -------------------------------” puts File.read(“stage1/a.png”) puts “-- Contents of stage2/a.png -------------------------------” puts File.read(“stage2/a.png”) end

–  
– Jim W.

---

<div class="post-metadata">

**Author:** ![itsme213](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/258eb7/32.png) [@itsme213](https://www.ruby-forum.com/u/itsme213)\
**Post date:** [March 17, 2006, 7:06pm UTC](https://www.ruby-forum.com/t/rake-rules-question/55108/4 "2006-03-17T19:06:25Z")

</div>

Thanks, Jim!

“Jim W.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote

> Basically, if you want your rules to trigger on something other than  
> simple file extenstions, you need to write them in this format:
> 
> rule(REGEX =\> LAMBDA\_TRANSFORMER) do  
> ACTIONS  
> end

Lovely. I will try this out.
