bio-gem 1.2.1 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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>
|