Include Require.JS (r.js build) into the Middleman build - ruby

I work with Middleman to develop, test and build my HAML & SASS Projects.
Now I also like to work with require.js. Is there any way i could integrate the R.js build into the Middleman build?
Did you make any experience with it? How do you handle require.js in middleman?

As far as just "running r.js" is concerned, it's pretty straightforward:
Save r.js into the project's root.
Define a custom extension (config.rb) which executes r.js after the build:
module RequireJS
class << self
def registered(app)
app.after_build do |builder|
exec('node r.js -o build/javascripts/app.build.js');
end
end
alias :included :registered
end
end
::Middleman::Extensions.register(:requirejs, RequireJS)
Activate custom extension (config.rb):
configure :build do
…
activate :requirejs
end

r.js can be used with node via the command line, just like middleman. I don't know how exactly you use middleman, but incorporating another command in your workflow shouldn't be a problem. You can find instructions on how to use r.js from the command line here.

Related

Can a Ruby test get the location of the folder where Rake executed it from?

Can a Ruby test get the location of the folder where Rake executed it from? I want to run Test::Unit unit tests using Rake but my defined "test suites" in Rake need to be able to find locations of libraries relative to the root of my project.
With Maven, I can set a system property like so :
<properties>
<main.basedir>${project.basedir}</main.basedir>
</properties>
And then Java can reference it like so:
String baseDir = System.getProperty("main.basedir");
Can Ruby do something similar? If so, how? Do I need to use a Rake namespace-require + include ? Not brewing my own framework: just trying to do the most basic test setup. I do have some lib files I created that my tests want to use.
This doesn't work because it hard codes the base dir into the class file:
base_dir = File.expand_path(File.join(File.dirname(__FILE__), ".."))
You can probably do this by injecting it in a test helper and getting the base location relative to the location of the file the test helper is is, but I would like to ask you what are you actually trying to achive?
normally the tests have access to the lib path and you should be able to just require what you want to use in the tests directly. are you using something like rspec or test::unit? are you brewing your own test framework?
so overall the answer is yes you can do it, but you should not have to do it. can show you how once you clarify what test framework you're using.
Edit
For test unit, this describes almost what you want to do:
https://github.com/test-unit/test-unit/blob/master/doc/text/how-to.md
The run_test.rb helper is placed in test. You see how the base dir is built by using the path of file (as mentioned above) and how the lib dir is placed on the load path.

what is the right way to use CLEAN rake task?

This is what I'm trying to do in my Rakefile:
require 'rake/clean'
CLEAN = ['coverage']
This is what I see in the log:
$ rake
/code/foo/Rakefile:29: warning: already initialized constant CLEAN
/Users/foo/.rvm/gems/ruby-2.1.3/gems/rake-10.3.2/lib/rake/clean.rb:61: warning: previous definition of CLEAN was here
I don't like these warnings.. What is the right way?
CLEAN is a FileList that is used by the predefined clean task. To add your own files to be cleaned, add them to this list. You can use the include method:
require 'rake/clean'
CLEAN.include 'coverage'
Now running rake clean will remove your files, as well as the predefined set of temporary files if any have bean created.
'rake/clean' already defines the constant CLEAN like so: CLEAN = ::Rake::FileList["**/*~", "**/*.bak", "**/core"]. Constants aren't meant to be overridden (although ruby will let you). If you want to specify the files to be cleaned, you should create your own rake task similar the existing one.
The existing task runs:
Rake::Cleaner.cleanup_files(CLEAN)
So you could run:
Rake::Cleaner.cleanup_files(['coverage'])
to clean up your coverage files.

How do I Declare a Rake::PackageTask with Prerequisites?

In Rake, I can use the following syntax to declare that task charlie requires tasks alpha and bravo to have been completed first.
task :charlie => [:alpha, :bravo]
This seems to work fine if charlie is a typical Rake task or a file task but I cannot figure out how to do this for a Rake::PackageTask. Here are the relevant parts of the rakefile so far:
require 'rake/packagetask'
file :package_jar => [:compile] do
puts("Packaging library.jar...")
# code omitted for brevity, but this bit works fine
end
Rake::PackageTask.new("library", "1.0") do |pt|
puts("Packaging library distribution artefact...")
pt.need_tar = true
pt.package_files = ["target/library.jar"]
end
task :package => :package_jar
What's happening here is that, for a clean build, it complains that it doesn't "know how to build task 'target/library.jar'". I have to run rake package_jar from the command line manually to get it to work, which is a bit of a nuisance. Is there any way I can make package depend on package_jar?
For what it's worth, I am using Rake version 0.9.2.2 with Ruby 1.8.7 on Linux.
When you run rake package (without previously running anything else to create any needed files) Rake sees that the package task needs the file target/library.jar. Since this file doesn’t yet exist Rake checks to see if it knows how to create it. It doesn’t know of any rules that will create this file, so it fails with the error you see.
Rake does have a task that it thinks will create a file named package_jar, and that task in fact creates the file target/library.jar, but it doesn’t realise this.
The fix is to tell Rake exactly what file is created in the file task. Rake will then automatically find the dependency.
Change
file :package_jar => [:compile] do
to
file 'target/library.jar' => [:compile] do
and then remove the line
task :package => :package_jar
since package_jar no longer exists and Rake will find the dependency on the file by itself.
In general in rake, if you want to add a dependency to a task, you need that task's name. So you need to figure out the name of the actual rake task that Rake::PackageTask is registering.
The easiest way to do this is by running with --trace — it lists each task's name as it is executing.
(I believe the name of a buildr package task is the filename of the package it produces, but I don't remember for certain. Use --trace to find out.)
You can add a dependency to any task by writing,
someTask.enhance [other, tasks]
where other and tasks can be either task names or task objects.
So in your case, you could write:
library = Rake::PackageTask.new(...) do
...
end
task(:package).enhance([library])

Rake delete files task

In msbuild I can delete part of files in certain directory like this
<ItemGroup>
<FilesToDelete Include="$(DeploymentDir)\**\*" exclude="$(DeploymentDir)\**\*.log"/>
</ItemGroup>
<Delete Files="#(FilesToDelete)" />
It will delete all files except *.txt
Is there some rake task I can similar thing?
Ruby has built in classes to make this easy:
Dir['deployment_dir/**/*'].delete_if { |f| f.end_with?('.txt') }
However, for some built in tasks, rake has helpers for this. Adapted from the API docs you can select files like so:
files_to_delete = FileList.new('deployment_dir/**/*') do |fl|
fl.exclude('*.txt')
end
Then you can feed this into your delete task.
Better yet, you can use the built in CLEAN/CLOBBER tasks:
# Your rake file:
require 'rake/clean'
# [] is alias for .new(), and we can chain .exclude
CLEAN = FileList['deployment_dir/**/*'].exclude('*.txt')
Then you can say on the cmd line:
rake clean
Read up the tutorial.
#adzdavies's answer is good, but assigning to CLEAN will produce the following warning since CLEAN is a constant:
warning: already initialized constant CLEAN
You should instead use CLEAN's instance methods. It is a Rake::FileList, so you can add something like this to your Rakefile:
require 'rake/clean'
# this is untested, but you get the idea
CLEAN.include('deployment_dir/**/*').exclude('*.txt')
Then run:
rake clean

Using generated sources in a buildr project

I'm trying to use a code generator inside a buildr-based java project. I would like to...
call the generator
compile the generated classes, package them
eclipse to see the generated stuff (i.e. have the .classpath contain those sources)
I've spend lots of time googling around for a complete example, but to no avail. the example here: https://cwiki.apache.org/confluence/display/BUILDR/How+to+generate+sources+before+compilation
gives be plenty of errors. this is what I've tried:
define 'generator' do
compile.with ALL_COMMON_MODULES
end
define 'extras' do
p 'calling generator..'
Java.classpath << ALL_COMMON_MODULES
Java.classpath << projects('generator')
Java.org.foo.generator.Main.main(['../modules/daos', 'target/generated-sources'])
sources = FileList[_("src/main/jeannie/*.*")]
generate = file(_("target/generated-sources") => sources).to_s do |dir|
puts 'generating...'
mkdir_p dir.to_s # ensure directory is created
end
compile.from generate
end
gives me an error like this:
RuntimeError: Circular dependency detected: TOP ...
so I'm obviously doing something very very wrong. I'd be very glad to see a working example or project that uses code generation.
I finally got it working with help from the buildr mailinglist. for anyone interested: The example mentioned here contains a problem. this:
compile.from generate
should be:
compile.from generate.to_s
Now it works beautifully! buildr also automatically extends the .classpath for eclipse (and idea, in case you use that) if 'compile.from' points to another location.
You cause the circular dependency by calling the parent project in your 'extras' project.
At that line: Java.classpath << projects('generator')
Maybe you should put everything on the same level, which is also what the example shows.
In this scenario your "generate" reference wouldn't be available either as it is in the 'extras' scope.
Something like this (untested):
define "generator" do
generate = file(_("target/generated-sources") => sources).to_s do |dir|
p 'calling generator..'
Java.classpath << ALL_COMMON_MODULES
Java.classpath << projects('generator')
Java.org.foo.generator.Main.main(['../modules/daos', 'target/generated-sources'])
sources = FileList[_("src/main/jeannie/*.*")]
puts 'generating...'
mkdir_p dir.to_s # ensure directory is created
end
compile.with ALL
compile.from generate
end

Resources