bio-gem 1.2.1 → 1.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -3
- data/Gemfile.lock +3 -4
- data/LICENSE.txt +1 -1
- data/README.rdoc +27 -10
- data/Rakefile +12 -10
- data/Tutorial.rdoc +4 -5
- data/VERSION +1 -1
- data/bin/biogem +9 -1
- data/bio-gem.gemspec +22 -16
- data/doc/biogem-hacking.md +396 -0
- data/lib/bio-gem.rb +2 -1
- data/lib/bio-gem/application.rb +1 -1
- data/lib/bio-gem/generator/render.rb +144 -0
- data/lib/bio-gem/mod/biogem-rails.rb +14 -0
- data/lib/bio-gem/mod/biogem.rb +107 -0
- data/lib/bio-gem/mod/jeweler.rb +33 -185
- data/lib/bio-gem/mod/jeweler/options.rb +5 -1
- data/lib/bio-gem/templates/README.rdoc +40 -0
- data/lib/bio-gem/templates/{bin → bin/bio-plugin} +1 -3
- data/lib/bio-gem/templates/ffi/ext.c +8 -0
- data/lib/bio-gem/templates/ffi/ext.h +10 -0
- data/lib/bio-gem/templates/gitignore +3 -0
- data/lib/bio-gem/templates/lib/bioruby-plugin.rb +18 -0
- data/lib/bio-gem/templates/lib/plugin.rb +3 -0
- data/test/test_bio-gem.rb +7 -8
- metadata +34 -36
- data/lib/bio-gem/templates/lib +0 -17
data/Gemfile
CHANGED
@@ -3,7 +3,7 @@ source "http://rubygems.org"
|
|
3
3
|
# Example:
|
4
4
|
# gem "activesupport", ">= 2.3.5"
|
5
5
|
gem "bundler", "~> 1.0.18"
|
6
|
-
gem "jeweler", "
|
6
|
+
gem "jeweler", ">= 1.7.0"
|
7
7
|
gem "rdoc"
|
8
8
|
|
9
9
|
|
@@ -12,7 +12,6 @@ gem "rdoc"
|
|
12
12
|
group :development do
|
13
13
|
gem "shoulda", ">= 0"
|
14
14
|
gem "bundler", "~> 1.0.18"
|
15
|
-
gem "jeweler", "
|
16
|
-
gem "rcov", ">= 0"
|
15
|
+
gem "jeweler", ">= 1.7.0"
|
17
16
|
gem "rdoc"
|
18
17
|
end
|
data/Gemfile.lock
CHANGED
@@ -2,13 +2,13 @@ GEM
|
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
4
|
git (1.2.5)
|
5
|
-
jeweler (1.
|
5
|
+
jeweler (1.7.0)
|
6
6
|
bundler (~> 1.0)
|
7
7
|
git (>= 1.2.5)
|
8
8
|
rake
|
9
|
+
rdoc
|
9
10
|
json (1.6.4)
|
10
11
|
rake (0.9.2.2)
|
11
|
-
rcov (0.9.11)
|
12
12
|
rdoc (3.12)
|
13
13
|
json (~> 1.4)
|
14
14
|
shoulda (2.11.3)
|
@@ -18,7 +18,6 @@ PLATFORMS
|
|
18
18
|
|
19
19
|
DEPENDENCIES
|
20
20
|
bundler (~> 1.0.18)
|
21
|
-
jeweler (
|
22
|
-
rcov
|
21
|
+
jeweler (>= 1.7.0)
|
23
22
|
rdoc
|
24
23
|
shoulda
|
data/LICENSE.txt
CHANGED
data/README.rdoc
CHANGED
@@ -21,11 +21,15 @@ versioning, releasing it to github.com and/or rubygems.org and
|
|
21
21
|
packaging. Bundler is used used for setting up a predefined developing
|
22
22
|
environment.
|
23
23
|
|
24
|
-
Also Biogem makes use of webservices.
|
24
|
+
Also Biogem makes use of webservices. Currently
|
25
25
|
|
26
|
-
* GitHub.com
|
27
|
-
|
28
|
-
|
26
|
+
* GitHub.com
|
27
|
+
is used for maintaining the source tree, tracking changes and
|
28
|
+
issues. Create a github account if you don't have one.
|
29
|
+
* RubyGems.org
|
30
|
+
publishes your software for other people to install and use
|
31
|
+
* biogems.info
|
32
|
+
tracks all biogems, so people can find them
|
29
33
|
|
30
34
|
== Installation
|
31
35
|
|
@@ -45,8 +49,12 @@ Also Biogem makes use of webservices. E.g.
|
|
45
49
|
$ git config --global github.token "TOKEN ASSIGNED BY GITHUB"
|
46
50
|
|
47
51
|
Note: another Ruby version management system used in BioRuby community is https://github.com/sstephenson/rbenv but for now we can not provide support for it.
|
52
|
+
|
48
53
|
==== IMPORTANT NOTE
|
49
|
-
|
54
|
+
|
55
|
+
Rubygems will not let you install Biogem in an environment with a Ruby
|
56
|
+
interpreter older than 1.9.X. Biogem can create gems for Ruby 1.8.7 -
|
57
|
+
but you need a recent version of Ruby and tools to run Biogem itself.
|
50
58
|
|
51
59
|
=== Download
|
52
60
|
|
@@ -95,6 +103,7 @@ Note: the above list of dependencies is just an example and it may vary from you
|
|
95
103
|
|
96
104
|
During the installation you may note how Rubygems install the documentation for you, for each library installed.
|
97
105
|
Is possible to access to all the documentations and API installed simply typing in the command line:
|
106
|
+
|
98
107
|
$ gem server
|
99
108
|
Server started at http://0.0.0.0:8808
|
100
109
|
Server started at http://[::ffff:0.0.0.0]:8808
|
@@ -107,10 +116,12 @@ Note: the above link must be update with your current version of Biogem
|
|
107
116
|
== Biogem Tutorial HowTo Develop a plugins
|
108
117
|
|
109
118
|
Please follow the guide reported in tutorial https://github.com/helios/bioruby-gem/blob/master/Tutorial.rdoc, which is the most up to date version.
|
110
|
-
You'll find out how to create
|
119
|
+
You'll find out how to create
|
120
|
+
|
111
121
|
* a simple plugin
|
112
122
|
* embed a database
|
113
123
|
* create a Biogem Engine to embed your gem into a Ruby on Rails web application
|
124
|
+
|
114
125
|
and much more
|
115
126
|
|
116
127
|
|
@@ -121,11 +132,13 @@ and much more
|
|
121
132
|
== Contributing to Biogem
|
122
133
|
|
123
134
|
The source code repositories for Biogem and http://biogems.info
|
124
|
-
website are on github
|
135
|
+
website are on github
|
136
|
+
|
125
137
|
* https://github.com/helios/bioruby-gem
|
126
138
|
* https://github.com/pjotrp/biogems.info
|
127
|
-
|
128
|
-
|
139
|
+
|
140
|
+
Use Biogem for all purposes DRY. If you want to contribute, feel free! Clone the
|
141
|
+
project! Submit! Send us a pull request!
|
129
142
|
|
130
143
|
== BioRuby's Wiki Official Documentation
|
131
144
|
|
@@ -171,9 +184,13 @@ e.g. biogem the-perfect-gem
|
|
171
184
|
--rdoc use rdoc for documentation
|
172
185
|
-h, --help display this help and exit
|
173
186
|
|
187
|
+
Recent versions of Biogem may have more options. For a full list run
|
188
|
+
|
189
|
+
bundle exec rake -T
|
190
|
+
|
174
191
|
== Copyright
|
175
192
|
|
176
|
-
Copyright (c) 2010
|
193
|
+
Copyright (c) 2010-2012 Raoul J.P. Bonnal. See LICENSE.txt for
|
177
194
|
further details.
|
178
195
|
|
179
196
|
|
data/Rakefile
CHANGED
@@ -15,11 +15,11 @@ Jeweler::Tasks.new do |gem|
|
|
15
15
|
gem.name = "bio-gem"
|
16
16
|
gem.homepage = "http://github.com/helios/bioruby-gem"
|
17
17
|
gem.license = "MIT"
|
18
|
-
gem.summary = %Q{
|
19
|
-
gem.description = %Q{
|
20
|
-
The basic idea is to simplify and promote a modular approach to
|
18
|
+
gem.summary = %Q{Biogem is a software generator for Ruby in bioinformatics}
|
19
|
+
gem.description = %Q{Biogem is a software generator for those bioinformaticans who want to start coding an application or a library for using/extending BioRuby core library and sharing it through rubygems.org .
|
20
|
+
The basic idea is to simplify and promote a modular approach to bioinformatics software development}
|
21
21
|
gem.email = "ilpuccio.febo@gmail.com"
|
22
|
-
gem.authors = ["Raoul J.P. Bonnal"]
|
22
|
+
gem.authors = ["Raoul J.P. Bonnal", "Pjotr Prins"]
|
23
23
|
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
24
24
|
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
25
25
|
#gem.version='0.0.1'
|
@@ -46,12 +46,14 @@ Rake::TestTask.new(:test) do |test|
|
|
46
46
|
test.verbose = true
|
47
47
|
end
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
49
|
+
# No proper rcov support in 1.9
|
50
|
+
#
|
51
|
+
# require 'rcov/rcovtask'
|
52
|
+
# Rcov::RcovTask.new do |test|
|
53
|
+
# test.libs << 'test'
|
54
|
+
# test.pattern = 'test/**/test_*.rb'
|
55
|
+
# test.verbose = true
|
56
|
+
# end
|
55
57
|
|
56
58
|
task :default => :test
|
57
59
|
|
data/Tutorial.rdoc
CHANGED
@@ -41,7 +41,7 @@ In case you are not connected to internet the following message will appear:
|
|
41
41
|
|
42
42
|
Note the name of the plugin is important. Plugins are published as Ruby gems on http://rubygems.org/. All plugins that start with the name bio dash (bio-) are automatically listed on the Biogem website http://biogems.info/ !
|
43
43
|
|
44
|
-
The first step is to open Rakefile and modify the gem.summary and gem.description.
|
44
|
+
The first step is to open the Rakefile and modify the gem.summary and gem.description.
|
45
45
|
|
46
46
|
gem.summary = %Q{TODO: one-line summary of your gem}
|
47
47
|
gem.description = %Q{TODO: longer description of your gem}
|
@@ -402,11 +402,11 @@ Biogem, like other frameworks, offers a bunch of predefined and common operation
|
|
402
402
|
|
403
403
|
$ rake -T
|
404
404
|
|
405
|
-
but because we are in a "development environment"
|
405
|
+
but because we are in a "development environment" we suggest to use
|
406
406
|
|
407
407
|
$ bundle exec rake -T
|
408
408
|
|
409
|
-
which guarantees that all the called programs/tasks will be executed inside the current development environment (bound to specific libraries versions).
|
409
|
+
which guarantees that all the called programs/tasks will be executed inside the current development environment (bound to specific libraries versions). rake -T displays the list of tasks
|
410
410
|
|
411
411
|
rake build # Build gem into pkg/
|
412
412
|
rake clobber_rcov # Remove rcov products for rcov
|
@@ -443,7 +443,6 @@ which guarantees that all the called programs/tasks will be executed inside the
|
|
443
443
|
rake version:bump:patch # Bump the patch version by 1
|
444
444
|
rake version:write # Writes out an explicit version.
|
445
445
|
|
446
|
-
|
447
446
|
== Advanced Developers
|
448
447
|
|
449
448
|
* Remember to modify .gitignore to exclude unwanted files.
|
@@ -463,5 +462,5 @@ which guarantees that all the called programs/tasks will be executed inside the
|
|
463
462
|
|
464
463
|
== Copyright
|
465
464
|
|
466
|
-
Copyright (c) 2010 Raoul J.P. Bonnal, Toshiaki Katayama, and Pjotr Prins. See LICENSE.txt for further details.
|
465
|
+
Copyright (c) 2010-2012 Raoul J.P. Bonnal, Toshiaki Katayama, and Pjotr Prins. See LICENSE.txt for further details.
|
467
466
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.2.
|
1
|
+
1.2.2
|
data/bin/biogem
CHANGED
@@ -16,8 +16,16 @@ if (application_exit[:exit]==0)
|
|
16
16
|
pwd = FileUtils.pwd
|
17
17
|
FileUtils.cd "bioruby-#{application_exit[:options][:project_name]}"
|
18
18
|
ARGV.clear << "install"
|
19
|
+
|
19
20
|
Bundler::CLI.start
|
20
21
|
#TODO: call rake directly not from shell
|
22
|
+
# print "Note: if rake gives an error try running biogem from an installed gem\n"
|
23
|
+
print "\trake version:write\n"
|
21
24
|
sh "rake version:write"
|
25
|
+
print "\trake gemspec\n"
|
22
26
|
sh "rake gemspec"
|
23
|
-
|
27
|
+
print "Done!\n"
|
28
|
+
else
|
29
|
+
$stderr.print "\nERROR: Biogem failed!\n"
|
30
|
+
end
|
31
|
+
|
data/bio-gem.gemspec
CHANGED
@@ -5,12 +5,12 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "bio-gem"
|
8
|
-
s.version = "1.2.
|
8
|
+
s.version = "1.2.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
-
s.authors = ["Raoul J.P. Bonnal"]
|
12
|
-
s.date = "2012-
|
13
|
-
s.description = "
|
11
|
+
s.authors = ["Raoul J.P. Bonnal", "Pjotr Prins"]
|
12
|
+
s.date = "2012-02-16"
|
13
|
+
s.description = "Biogem is a software generator for those bioinformaticans who want to start coding an application or a library for using/extending BioRuby core library and sharing it through rubygems.org .\n The basic idea is to simplify and promote a modular approach to bioinformatics software development"
|
14
14
|
s.email = "ilpuccio.febo@gmail.com"
|
15
15
|
s.executables = ["biogem"]
|
16
16
|
s.extra_rdoc_files = [
|
@@ -29,22 +29,31 @@ Gem::Specification.new do |s|
|
|
29
29
|
"VERSION",
|
30
30
|
"bin/biogem",
|
31
31
|
"bio-gem.gemspec",
|
32
|
+
"doc/biogem-hacking.md",
|
32
33
|
"lib/bio-gem.rb",
|
33
34
|
"lib/bio-gem/application.rb",
|
35
|
+
"lib/bio-gem/generator/render.rb",
|
36
|
+
"lib/bio-gem/mod/biogem-rails.rb",
|
37
|
+
"lib/bio-gem/mod/biogem.rb",
|
34
38
|
"lib/bio-gem/mod/jeweler.rb",
|
35
39
|
"lib/bio-gem/mod/jeweler/github_mixin.rb",
|
36
40
|
"lib/bio-gem/mod/jeweler/options.rb",
|
37
|
-
"lib/bio-gem/templates/
|
41
|
+
"lib/bio-gem/templates/README.rdoc",
|
42
|
+
"lib/bio-gem/templates/bin/bio-plugin",
|
38
43
|
"lib/bio-gem/templates/database",
|
39
44
|
"lib/bio-gem/templates/db_connection",
|
40
45
|
"lib/bio-gem/templates/db_model",
|
41
46
|
"lib/bio-gem/templates/engine",
|
47
|
+
"lib/bio-gem/templates/ffi/ext.c",
|
48
|
+
"lib/bio-gem/templates/ffi/ext.h",
|
42
49
|
"lib/bio-gem/templates/foos_controller",
|
43
50
|
"lib/bio-gem/templates/foos_view_example",
|
44
51
|
"lib/bio-gem/templates/foos_view_index",
|
45
52
|
"lib/bio-gem/templates/foos_view_new",
|
46
53
|
"lib/bio-gem/templates/foos_view_show",
|
47
|
-
"lib/bio-gem/templates/
|
54
|
+
"lib/bio-gem/templates/gitignore",
|
55
|
+
"lib/bio-gem/templates/lib/bioruby-plugin.rb",
|
56
|
+
"lib/bio-gem/templates/lib/plugin.rb",
|
48
57
|
"lib/bio-gem/templates/library",
|
49
58
|
"lib/bio-gem/templates/migration",
|
50
59
|
"lib/bio-gem/templates/rakefile",
|
@@ -59,38 +68,35 @@ Gem::Specification.new do |s|
|
|
59
68
|
s.require_paths = ["lib"]
|
60
69
|
s.required_ruby_version = Gem::Requirement.new("~> 1.9")
|
61
70
|
s.rubygems_version = "1.8.10"
|
62
|
-
s.summary = "
|
71
|
+
s.summary = "Biogem is a software generator for Ruby in bioinformatics"
|
63
72
|
|
64
73
|
if s.respond_to? :specification_version then
|
65
74
|
s.specification_version = 3
|
66
75
|
|
67
76
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
68
77
|
s.add_runtime_dependency(%q<bundler>, ["~> 1.0.18"])
|
69
|
-
s.add_runtime_dependency(%q<jeweler>, ["
|
78
|
+
s.add_runtime_dependency(%q<jeweler>, [">= 1.7.0"])
|
70
79
|
s.add_runtime_dependency(%q<rdoc>, [">= 0"])
|
71
80
|
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
72
81
|
s.add_development_dependency(%q<bundler>, ["~> 1.0.18"])
|
73
|
-
s.add_development_dependency(%q<jeweler>, ["
|
74
|
-
s.add_development_dependency(%q<rcov>, [">= 0"])
|
82
|
+
s.add_development_dependency(%q<jeweler>, [">= 1.7.0"])
|
75
83
|
s.add_development_dependency(%q<rdoc>, [">= 0"])
|
76
84
|
else
|
77
85
|
s.add_dependency(%q<bundler>, ["~> 1.0.18"])
|
78
|
-
s.add_dependency(%q<jeweler>, ["
|
86
|
+
s.add_dependency(%q<jeweler>, [">= 1.7.0"])
|
79
87
|
s.add_dependency(%q<rdoc>, [">= 0"])
|
80
88
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
81
89
|
s.add_dependency(%q<bundler>, ["~> 1.0.18"])
|
82
|
-
s.add_dependency(%q<jeweler>, ["
|
83
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
90
|
+
s.add_dependency(%q<jeweler>, [">= 1.7.0"])
|
84
91
|
s.add_dependency(%q<rdoc>, [">= 0"])
|
85
92
|
end
|
86
93
|
else
|
87
94
|
s.add_dependency(%q<bundler>, ["~> 1.0.18"])
|
88
|
-
s.add_dependency(%q<jeweler>, ["
|
95
|
+
s.add_dependency(%q<jeweler>, [">= 1.7.0"])
|
89
96
|
s.add_dependency(%q<rdoc>, [">= 0"])
|
90
97
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
91
98
|
s.add_dependency(%q<bundler>, ["~> 1.0.18"])
|
92
|
-
s.add_dependency(%q<jeweler>, ["
|
93
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
99
|
+
s.add_dependency(%q<jeweler>, [">= 1.7.0"])
|
94
100
|
s.add_dependency(%q<rdoc>, [">= 0"])
|
95
101
|
end
|
96
102
|
end
|
@@ -0,0 +1,396 @@
|
|
1
|
+
# Hacking biogem
|
2
|
+
|
3
|
+
Biogem is a Ruby code generator for bioinformatics. It generates a plugin, in
|
4
|
+
the form of a gem, which is published automatically on both github and
|
5
|
+
rubygems.org.
|
6
|
+
|
7
|
+
In this document we discuss ways to modify Biogem, so you can generate your own
|
8
|
+
code, and avoid repetitious work. The design of the biogem code generator is based on
|
9
|
+
templates, and there are accessible ways to hack it, or even add your own templates.
|
10
|
+
|
11
|
+
This document is divided into two sections. In the first section we will create
|
12
|
+
a directory, generate a file through a template, and add a test through a
|
13
|
+
helper. In the second section we will modify some undesired behaviour in biogem
|
14
|
+
through meta-programming.
|
15
|
+
|
16
|
+
## Check out the source
|
17
|
+
|
18
|
+
|
19
|
+
To change biogem, checkout the source tree to your local machine. E.g.
|
20
|
+
|
21
|
+
```sh
|
22
|
+
git clone https://github.com/helios/bioruby-gem.git
|
23
|
+
cd bioruby-gem
|
24
|
+
bundle
|
25
|
+
```
|
26
|
+
|
27
|
+
Make sure you are running a supported version of Ruby (check the README).
|
28
|
+
Now you can invoke biogem with
|
29
|
+
|
30
|
+
```sh
|
31
|
+
bundle exec ./bin/biogem foo
|
32
|
+
```
|
33
|
+
|
34
|
+
which will create the bioruby-foo plugin for testing. Every time you rerun biogem, make
|
35
|
+
sure to remove the bioruby-foo directory first
|
36
|
+
|
37
|
+
```sh
|
38
|
+
rm -rf bioruby-foo
|
39
|
+
```
|
40
|
+
|
41
|
+
Recommended biogem switches are --with-bin and --rspec
|
42
|
+
|
43
|
+
```sh
|
44
|
+
bundle exec ./bin/biogem --with-bin --rspec foo
|
45
|
+
```
|
46
|
+
|
47
|
+
Note that we are running biogem here within bundler. This may cause a rakefile
|
48
|
+
error after generating the plugin (nesting bundler is not a good idea). This can simply be fixed by running the rake by hand in the plugin directory after generation
|
49
|
+
|
50
|
+
```sh
|
51
|
+
cd bioruby-foo
|
52
|
+
bundle
|
53
|
+
bundle exec rake version:write
|
54
|
+
bundle exec rake gemspec
|
55
|
+
```
|
56
|
+
|
57
|
+
Alternatively, install an updated version of biogem, and run biogem without
|
58
|
+
bundler with
|
59
|
+
|
60
|
+
```sh
|
61
|
+
bundle exec rake install
|
62
|
+
biogem --with-bin --rspec foo
|
63
|
+
```
|
64
|
+
|
65
|
+
## Invoking the Biogem code generator
|
66
|
+
|
67
|
+
In the file ./bin/biogem rake, jeweler and bundler support are loaded and
|
68
|
+
Bio::Gem::Generator::Application invoked, which generates the new directory and
|
69
|
+
files. After generating code biogem changes directory and runs some rake
|
70
|
+
commands in the newly generated plugin.
|
71
|
+
|
72
|
+
## Add an CLI option to Biogem
|
73
|
+
|
74
|
+
In the first step we want to add a switch to the biogem command line. For our
|
75
|
+
purpose we will add --with-ffi, a switch which will create a template for a foreign
|
76
|
+
function interface. Switches are defined in [options.rb](https://github.com/helios/bioruby-gem/blob/master/lib/bio-gem/mod/jeweler/options.rb). We add
|
77
|
+
a switch with
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
o.on('--with-ffi', 'generate a foreign function interface (FFI)') do
|
81
|
+
self[:biogem_ffi] = true
|
82
|
+
end
|
83
|
+
```
|
84
|
+
|
85
|
+
This switch will be available as *options[:biogem_ffi]* further on.
|
86
|
+
|
87
|
+
## Create a directory
|
88
|
+
|
89
|
+
In the method *create_files* in Biogem [jeweler.rb](https://github.com/helios/bioruby-gem/blob/master/lib/bio-gem/mod/jeweler.rb) directories and files get
|
90
|
+
created. For example the plugin library file is generated with
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
# Fill lib/bio-plugin.rb with some default comments
|
94
|
+
output_template_in_target_generic 'lib', File.join(lib_dir, lib_filename)
|
95
|
+
```
|
96
|
+
|
97
|
+
which also creates the directory. We explicitly add a directory to store C
|
98
|
+
source files and headers with
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
create_ffi_structure if options[:biogem_ffi]
|
102
|
+
```
|
103
|
+
|
104
|
+
and
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
def create_ffi_structure
|
108
|
+
# create ./ext/src and ./ext/include for the .c and .h files
|
109
|
+
mkdir_in_target(ext_dir)
|
110
|
+
mkdir_in_target(File.join(ext_dir,"src"))
|
111
|
+
# create ./lib/ffi for the Ruby ffi
|
112
|
+
mkdir_in_target(File.join(lib_dir,"ffi"))
|
113
|
+
end
|
114
|
+
```
|
115
|
+
|
116
|
+
## Generate file from template
|
117
|
+
|
118
|
+
Templates are stored in lib/bio-gem/templates. We create a template for
|
119
|
+
our C extension named [ext.c](https://github.com/helios/bioruby-gem/tree/master/lib/bio-gem/templates/ffi/ext.c), e.g. the C function
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
int add_one(int number) {
|
123
|
+
return number + 1;
|
124
|
+
}
|
125
|
+
```
|
126
|
+
|
127
|
+
which gets copied into the plugins ./ext/src directory with
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
output_template_in_target_generic File.join('ffi','ext.c'), File.join(src_dir, "ext.c" )
|
131
|
+
```
|
132
|
+
|
133
|
+
Likewise, an include file ext.h gets copied, a Makefile, and the Ruby ffi file, which defines the bindings to ext.c.
|
134
|
+
|
135
|
+
(to be continued)
|
136
|
+
|
137
|
+
## Modify a generated file with a helper
|
138
|
+
|
139
|
+
Similar to Ruby on Rails, we use erb to modify templates based on input parameters.
|
140
|
+
Erb is part of the Ruby [standard library](http://ruby-doc.org/stdlib-1.9.3/libdoc/erb/rdoc/ERB.html).
|
141
|
+
To use erb we create helper functions. A good example is the main library file that
|
142
|
+
gets included by everyone using your plugin using
|
143
|
+
|
144
|
+
```ruby
|
145
|
+
require 'bio-myawesomeplugin'
|
146
|
+
```
|
147
|
+
|
148
|
+
The generated file is in your module *lib* directory. The template for that file can be found [here](https://github.com/pjotrp/bioruby-gem/blob/master/lib/bio-gem/templates/lib/bioruby-plugin.rb).
|
149
|
+
Another example generates the
|
150
|
+
binary from a [template](https://github.com/pjotrp/bioruby-gem/blob/master/lib/bio-gem/templates/bin/bio-plugin), when generating with the --with-bin switch. It contains the line
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
require '<%= project_name %>'
|
154
|
+
```
|
155
|
+
|
156
|
+
*project_name* is a helper, a method which is defined in *lib/bio-gem/mod/jeweler.rb* as
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
alias original_project_name project_name
|
160
|
+
def project_name
|
161
|
+
name = original_project_name
|
162
|
+
return 'bio-'+name if name !~ /^bio-/
|
163
|
+
name
|
164
|
+
end
|
165
|
+
```
|
166
|
+
|
167
|
+
Here, original_project_name is the original method in jeweler. The main thing to note is that you
|
168
|
+
can easily create your own helpers - they are available in the erb based templates when they
|
169
|
+
exist in the Jeweler::Generator namespace.
|
170
|
+
|
171
|
+
## Adapt the Rakefile
|
172
|
+
|
173
|
+
For our FFI (DRY) the Rakefile needs to be adapted to compile the C file(s) properly. For this
|
174
|
+
implementatin I am adding a working example of a C binding, similar to what we do for tests.
|
175
|
+
|
176
|
+
(to be continued)
|
177
|
+
|
178
|
+
# Hacking jeweler for Biogem
|
179
|
+
|
180
|
+
The following section discusses surgical changes to biogem.
|
181
|
+
|
182
|
+
''Warning, the rest of this document is about Ruby meta-programming. It is not for the faint of
|
183
|
+
heart.''
|
184
|
+
|
185
|
+
Biogem builds on [Jeweler](https://github.com/technicalpickles/jeweler).
|
186
|
+
|
187
|
+
jeweler comes with a library for managing and releasing RubyGem projects, and
|
188
|
+
a scaffold generator for starting new RubyGem projects. Using typical Ruby
|
189
|
+
overrides of jeweler methods, also known as meta-programming, Biogem subverts
|
190
|
+
Jeweler for our bioinformatics needs (see jeweler::Generator.new example below).
|
191
|
+
|
192
|
+
## Invoking the Biogem code generator
|
193
|
+
|
194
|
+
In the file ./bin/biogem rake, jeweler and bundler support are loaded and
|
195
|
+
Bio::Gem::Generator::Application invoked, which generates the new directory and
|
196
|
+
files. Thereafter biogem changes directory and runs some rake commands.
|
197
|
+
|
198
|
+
## Inside Bio::Gem::Generator::Application
|
199
|
+
|
200
|
+
First Jeweler::Generator.run is run, so the basic scaffolding exists for Rake,
|
201
|
+
tests etc. Nothing special so far. Where it gets interesting is that biogem
|
202
|
+
overrides Jeweler classes in [./lib/bio-gem/mod/jeweler.rb](https://github.com/helios/bioruby-gem/blob/master/lib/bio-gem/mod/jeweler.rb). In this file, at runtime,
|
203
|
+
Jeweler::Generator.new is replaced with our own version, which calls the
|
204
|
+
original first, but continues to plug in information. Any time jeweler::Generator.new is called,
|
205
|
+
our edition is called. Even from within jeweler!
|
206
|
+
|
207
|
+
It is important to check out this file, as many overrides are defined here.
|
208
|
+
Also have a look at the *create_files* function. That is where directories and
|
209
|
+
files are generated from templates.
|
210
|
+
|
211
|
+
## Biogem options
|
212
|
+
|
213
|
+
The application generator is programmed from biogem command line options. These
|
214
|
+
options are listed in [jeweler/options.rb](https://github.com/helios/bioruby-gem/blob/master/lib/bio-gem/mod/jeweler/options.rb).
|
215
|
+
|
216
|
+
## Biogem templates
|
217
|
+
|
218
|
+
Biogem templates are listed in [./lib/bio-gem/templates](https://github.com/helios/bioruby-gem/tree/master/lib/bio-gem/templates). These templates use erb to tune content within.
|
219
|
+
|
220
|
+
Templates are by in the jeweler.rb override (described above). For example the Rakefile is
|
221
|
+
generated with
|
222
|
+
|
223
|
+
```ruby
|
224
|
+
output_template_in_target 'Rakefile'
|
225
|
+
```
|
226
|
+
|
227
|
+
it is all fairly straightforward.
|
228
|
+
|
229
|
+
## Check out the jeweler source code
|
230
|
+
|
231
|
+
From the above you can see how we reprogram jeweler for our needs. To find new
|
232
|
+
ways of generating code, we strongly suggest to also check out the [jeweler
|
233
|
+
source code](https://github.com/technicalpickles/jeweler/tree/master/lib). The
|
234
|
+
jeweler code base is well thought out, and stable.
|
235
|
+
|
236
|
+
## Changing jeweler behaviour
|
237
|
+
|
238
|
+
Just as an example we are going to override code generated by Jeweler. Jeweler generates
|
239
|
+
a dependency for rcov, a Ruby code coverage analyzer. We are going to remove this dependency,
|
240
|
+
without touching the Jeweler code base.
|
241
|
+
|
242
|
+
In the Jeweler source code tree rcov is used in two files:
|
243
|
+
|
244
|
+
```ruby
|
245
|
+
grep -r rcov *
|
246
|
+
jeweler/generator.rb: development_dependencies << ["rcov", ">= 0"]
|
247
|
+
jeweler/templates/other_tasks.erb:RSpec::Core::RakeTask.new(:rcov) do |spec|
|
248
|
+
jeweler/templates/other_tasks.erb: spec.rcov = true
|
249
|
+
jeweler/templates/other_tasks.erb:Micronaut::RakeTask.new(:rcov) do |examples|
|
250
|
+
jeweler/templates/other_tasks.erb: examples.rcov_opts = '-Ilib -I<%= test_dir %>'
|
251
|
+
jeweler/templates/other_tasks.erb: examples.rcov = true
|
252
|
+
jeweler/templates/other_tasks.erb:require 'rcov/rcovtask'
|
253
|
+
jeweler/templates/other_tasks.erb: <%= test_task %>.rcov_opts << '--exclude "gems/*"'
|
254
|
+
```
|
255
|
+
|
256
|
+
The first step is to remove the rcov entry from development_dependencies. This can be
|
257
|
+
done by adding a line in Biogems lib/bio-gem/mod/jeweler.rb. Change it to
|
258
|
+
|
259
|
+
```ruby
|
260
|
+
class Jeweler
|
261
|
+
class Generator
|
262
|
+
alias original_initialize initialize
|
263
|
+
def initialize(options = {})
|
264
|
+
original_initialize(options)
|
265
|
+
development_dependencies << ["bio", ">= 1.4.2"]
|
266
|
+
development_dependencies.delete_if { |k,v| k == "rcov" }
|
267
|
+
(...)
|
268
|
+
```
|
269
|
+
|
270
|
+
You can see here that BioRuby support is always added. The next step is to change
|
271
|
+
the behaviour of jeweler/templates/other_tasks.erb. The code to generate the
|
272
|
+
Rakefile lists is
|
273
|
+
|
274
|
+
```ruby
|
275
|
+
<% case testing_framework %>
|
276
|
+
<% when :rspec %>
|
277
|
+
(...)
|
278
|
+
<% when :micronaut %>
|
279
|
+
(...)
|
280
|
+
<% else %>
|
281
|
+
require 'rcov/rcovtask'
|
282
|
+
Rcov::RcovTask.new do |<%= test_task %>|
|
283
|
+
(...)
|
284
|
+
end
|
285
|
+
<% end %>
|
286
|
+
```
|
287
|
+
|
288
|
+
and, annoyingly, shows that rcov is always added by default (in the final
|
289
|
+
'else'). We should communicate with the author of Jeweler to fix this. However, we
|
290
|
+
also have the option to override the Rakefile generator. The jeweler Rakefile
|
291
|
+
template has the form
|
292
|
+
|
293
|
+
```ruby
|
294
|
+
require 'rubygems'
|
295
|
+
<%= render_template 'bundler_setup.erb' %>
|
296
|
+
require 'rake'
|
297
|
+
<%= render_template 'jeweler_tasks.erb' %>
|
298
|
+
<%= render_template 'other_tasks.erb' %>
|
299
|
+
```
|
300
|
+
|
301
|
+
The two important functions in jeweler.rb are:
|
302
|
+
|
303
|
+
```ruby
|
304
|
+
def render_template(source)
|
305
|
+
template_contents = File.read(File.join(template_dir, source))
|
306
|
+
template = ERB.new(template_contents, nil, '<>')
|
307
|
+
# squish extraneous whitespace from some of the conditionals
|
308
|
+
template.result(binding).gsub(/\n\n\n+/, "\n\n")
|
309
|
+
end
|
310
|
+
|
311
|
+
def output_template_in_target(source, destination = source)
|
312
|
+
final_destination = File.join(target_dir, destination)
|
313
|
+
template_result = render_template(source)
|
314
|
+
File.open(final_destination, 'w') {|file| file.write(template_result)}
|
315
|
+
$stdout.puts "\tcreate\t#{destination}"
|
316
|
+
end
|
317
|
+
```
|
318
|
+
|
319
|
+
these find the templates and render them through ERB.
|
320
|
+
|
321
|
+
Naturally, Biogem has needed some overriding behaviour. In this case Biogems jeweler.rb
|
322
|
+
has
|
323
|
+
|
324
|
+
```ruby
|
325
|
+
def output_template_in_target_generic_update(source, destination = source, template_dir = template_dir_biogem)
|
326
|
+
final_destination = File.join(target_dir, destination)
|
327
|
+
template_result = render_template_generic(source, template_dir)
|
328
|
+
File.open(final_destination, 'a') {|file| file.write(template_result)}
|
329
|
+
$stdout.puts "\tcreate\t#{destination}"
|
330
|
+
end
|
331
|
+
```
|
332
|
+
|
333
|
+
and, in the case of the --with-db option, the Rakefile already gets modified by Biogem
|
334
|
+
|
335
|
+
```ruby
|
336
|
+
output_template_in_target_generic 'rakefile', 'Rakefile', template_dir_biogem
|
337
|
+
```
|
338
|
+
|
339
|
+
So, what would be the best route here, to change biogem behaviour? We have to rewrite
|
340
|
+
the Rakefile template to remove the rcov lines. We can
|
341
|
+
change the *render_template* to allow rewriting the template. Unfortunately there is no
|
342
|
+
existing hook for that in jeweler. So, let us inject a hook named *after_render_template*
|
343
|
+
to a *render_template* override. First we open the Jeweler::Generator class and move the method to biogem jeweler.rb, renaming the original method to original_render_template:
|
344
|
+
|
345
|
+
```ruby
|
346
|
+
class Jeweler
|
347
|
+
class Generator
|
348
|
+
alias original_render_template render_template
|
349
|
+
def render_template(source)
|
350
|
+
buf = original_render_template(source)
|
351
|
+
# call hook (returns edited buf)
|
352
|
+
after_render_template(source,buf)
|
353
|
+
end
|
354
|
+
|
355
|
+
# new hook for removing stuff
|
356
|
+
def after_render_template(source,buf)
|
357
|
+
if source == 'other_tasks.erb'
|
358
|
+
# remove rcov related lines
|
359
|
+
buf.gsub!(/require 'rcov/rcovtask'/,'')
|
360
|
+
(...)
|
361
|
+
end
|
362
|
+
end
|
363
|
+
```
|
364
|
+
|
365
|
+
you probably get the gist (the stuff you can do with Ruby meta-programming!).
|
366
|
+
The solution chosen overrides original jeweler behaviour without touching
|
367
|
+
jeweler itself. Naturally, if it can be handled in jeweler, it is strongly
|
368
|
+
preferred. With our solution a small change in jeweler may now break biogem
|
369
|
+
(in software engineering terms: the fix is brittle).
|
370
|
+
|
371
|
+
In fact, the jeweler author has responded that the default behaviour for rcov will change now. I.e.
|
372
|
+
our fix will go upstream.
|
373
|
+
|
374
|
+
Still, for stuff that will not go into jeweler, this is a way of changing
|
375
|
+
behaviour.
|
376
|
+
|
377
|
+
# DRY (Do not repeat yourself)
|
378
|
+
|
379
|
+
This document should help you preventing repeating yourself. Code generation
|
380
|
+
can be very useful. When you have something that is useful to yourself, or
|
381
|
+
others, and is bioinformatics related, add it to biogem. When it is more
|
382
|
+
generic, add it to jeweler. You may make a lot of people happy.
|
383
|
+
|
384
|
+
# More on meta-programming
|
385
|
+
|
386
|
+
Thanks to Ruby meta-programming we do not have to change jeweler. With another
|
387
|
+
computer language, we would have cloned jeweler and modified the source code
|
388
|
+
for our purposes. This would imply a fork of the code base - and the projects
|
389
|
+
would have diverged irrevocably. As it stands, we can build on the existing
|
390
|
+
jeweler project. Some 'brittleness' may get introduced, as explained above, but in
|
391
|
+
general we should normally be able to continue adapting our code base to that
|
392
|
+
of jeweler.
|
393
|
+
|
394
|
+
The Pragmatic programmers book on [Ruby metaprogramming](http://www.amazon.com/Metaprogramming-Ruby-Program-Like-Pros/dp/1934356476/ref=cm_cr_pr_product_top) is recommended reading.
|
395
|
+
|
396
|
+
Copyright (C) 2012 Pjotr Prins <pjotr.prins@thebird.nl>
|