Maven, JRuby and Rails Migrations

Here’s how I managed to get Rails Migrations working with a Maven build process, enabling me to leverage Migrations to maintain the RDBMS schema of a Java application.

Add JRuby and Database dependencies

Add the following dependencies to your pom.xml (adjust for whatever is latest version of jruby and whatever your database is).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<dependency>
	<groupId>org.jruby</groupId>
	<artifactId>jruby-complete</artifactId>
	<version>1.3.0RC1</version>
</dependency>
<dependency>
	<groupId>oracle</groupId>
	<artifactId>jdbc</artifactId>
	<version>11.1.0</version>
</dependency>

Add a goal to install required Ruby gems

To get Rails migrations running we’ll need the following gems:

  • activerecord
  • activerecord-jdbc-adapter
  • your database specific jdbc adapter

We’ll set up a profile to install these gems if they are missing (based on a approach used by Binil Thomas):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<profiles>
	<profile>
		<id>first.time</id>
		<activation>
			<file>
				<missing>${user.home}/.gem/jruby/1.8/gems/activerecord-2.3.2</missing>
			</file>
		</activation>
		<build>
			<plugins>
				<plugin>
					<groupId>org.codehaus.mojo</groupId>
					<artifactId>exec-maven-plugin</artifactId>
					<executions>
						<execution>
							<id>install-active-record-gem</id>
							<phase>initialize</phase>
							<goals>
								<goal>java</goal>
							</goals>
							<configuration>
								<mainClass>org.jruby.Main</mainClass>
								<arguments>
									<argument>-S</argument>
									<argument>gem</argument>
									<argument>install</argument>
									<argument>activerecord</argument>
									<argument>activerecord-jdbc-adapter</argument>
									<argument>activerecord-oracle_enhanced-adapter</argument>
									<argument>--no-ri</argument>
									<argument>--no-rdoc</argument>
									<argument>--no-test</argument>
								</arguments>
							</configuration>
						</execution>
					</executions>
				</plugin>
			</plugins>
		</build>
	</profile>
</profiles>

Replace activerecord-oracle_enhanced-adapter with the name of your chosen database’s jdbc adapter.

Add a goal to run the migration

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<build>
	<plugins>
		<plugin>
			<groupId>org.codehaus.mojo</groupId>
			<artifactId>exec-maven-plugin</artifactId>
			<executions>
				<execution>
					<id>run-migrate</id>
					<phase>install</phase>
					<goals>
						<goal>java</goal>
					</goals>
					<configuration>
						<mainClass>org.jruby.Main</mainClass>
						<arguments>
							<argument>-S</argument>
							<argument>rake</argument>
							<argument>-f</argument>
							<argument>${basedir}/Rakefile</argument>
						</arguments>
					</configuration>
				</execution>
			</executions>
		</plugin>
	</plugins>
</build>

Create a Rakefile

You’ll need a Rakefile to carry out the migration, in my case I wanted to avoid depending on all of Rails so I just used the following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
require 'active_record'
require 'yaml'
 
RAILS_ROOT = "#{File.dirname(__FILE__)}" unless defined?(RAILS_ROOT)
 
task :default => :migrate
 
task :migrate => :environment do
  ActiveRecord::Migrator.migrate('db/migrate', ENV["VERSION"] ? ENV["VERSION"].to_i : nil )
end
 
task :environment do
  ActiveRecord::Base.establish_connection(YAML::load(File.open("#{RAILS_ROOT}/config/database.yml")))
  ActiveRecord::Base.logger = Logger.new(File.open('database.log', 'a'))
end

Write your migrations

Create your migrations in db/migrate.

Apply database changes

Finally type:

1
mvn install

to deploy your database changes.

The full POM

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
 
<project>
	<modelVersion>4.0.0</modelVersion>
	<groupId>org.example</groupId>
	<artifactId>schema</artifactId>
	<name>Example POM for doing Rails Migrations</name>
	<packaging>pom</packaging>
	<dependencies>
		<dependency>
			<groupId>org.jruby</groupId>
			<artifactId>jruby-complete</artifactId>
			<version>1.3.0RC1</version>
		</dependency>
		<dependency>
			<groupId>oracle</groupId>
			<artifactId>jdbc</artifactId>
			<version>11.2.0</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>exec-maven-plugin</artifactId>
				<executions>
					<execution>
						<id>run-migrate</id>
						<phase>install</phase>
						<goals>
							<goal>java</goal>
						</goals>
						<configuration>
							<mainClass>org.jruby.Main</mainClass>
							<arguments>
								<argument>-S</argument>
								<argument>rake</argument>
								<argument>-f</argument>
								<argument>${basedir}/Rakefile</argument>
							</arguments>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
	<profiles>
		<profile>
			<id>first.time</id>
			<activation>
				<file>
					<missing>${user.home}/.gem/jruby/1.8/gems/activerecord-2.3.2</missing>
				</file>
			</activation>
			<build>
				<plugins>
					<plugin>
						<groupId>org.codehaus.mojo</groupId>
						<artifactId>exec-maven-plugin</artifactId>
						<executions>
							<execution>
								<id>install-active-record-gem</id>
								<phase>initialize</phase>
								<goals>
									<goal>java</goal>
								</goals>
								<configuration>
									<mainClass>org.jruby.Main</mainClass>
									<arguments>
										<argument>-S</argument>
										<argument>gem</argument>
										<argument>install</argument>
										<argument>activerecord</argument>
										<argument>activerecord-jdbc-adapter</argument>
										<argument>activerecord-oracle_enhanced-adapter</argument>
										<argument>--no-ri</argument>
										<argument>--no-rdoc</argument>
										<argument>--no-test</argument>
									</arguments>
								</configuration>
							</execution>
						</executions>
					</plugin>
				</plugins>
			</build>
		</profile>
	</profiles>
</project> 
Ⓗ Home   Ⓑ Blog   Ⓐ About