This is the version of my Create talk I gave at Railsconf 2009.
Sometimes the best solution is a standalone application that you can give to a client or customer to just drop on a machine and run. Maybe it is a web service, or a desktop data entry application, or mass deployed background agent, or you have no control of the deployment environment. In any case, there are situations where deploying a full ruby stack may not be an option.
This talk will cover the Crate project and how it may be used to package your application, be it commandline, server, or web application. The end result is a statically built, standalone executable of the ruby interpreter and all dependent binary extensions. The application code, ruby stdlib, dependent gems, and other assets are packed into one or more SQLite databases.
29. MY NEEDS
• Minimally Invasive
• do not unpack to a temporary location
• small as can be
30. MY NEEDS
• Minimally Invasive
• do not unpack to a temporary location
• small as can be
• Wide deployment capabilities
• more than linux, mac, windows, cygwin
31. embedded Ruby
+ ruby extensions
+ main wrapper
+ standard library
+ application code
Crate based application
32. embedded Ruby
C + ruby extensions
+ main wrapper
+ standard library
+ application code
Crate based application
33. embedded Ruby
C + ruby extensions
+ main wrapper
+ standard library
Ruby + application code
Crate based application
34. Statically Compile
embedded Ruby
C + ruby extensions
+ main wrapper
+ standard library
Ruby + application code
Crate based application
35. Statically Compile
embedded Ruby
C + ruby extensions
+ main wrapper
+ standard library
Ruby + application code
Crate based application
Amalgalite
36. Statically Compile
embedded Ruby
C + ruby extensions
+ main wrapper
+ standard library
Ruby + application code
Crate based application
Pack into Amalgalite
38. Inexact Size Measurements
Executable + C
Ruby libs
extensions
Ruby 1.8.6 2.4 M 8.4 M
Crate/ruby 1.8.6 2.9 M 1.9 M
39. 1 module Kernel
2 # alias the original require away to use later
3 alias :amalgalite_original_require :require
4
5 #
6 # hook into the system 'require' to allow for required text or blobs from an
7 # amalgalite database.
8 #
9 def require( filename )
10 loaded = amalgalite_original_require( filename )
11 rescue LoadError => load_error
12 if load_error.message =~ /#{Regexp.escape filename}z/ then
13 loaded = Amalgalite::Requires.require( filename )
14 else
15 raise load_error
16 end
17 end
18
19 private :require
20 private :amalgalite_original_require
21 end
44. ISSUE #1 - AUTOLOAD
• Problem
• bypasses the require chain setup by amalgalite
• used by rack, active_support, active_record
45. ISSUE #1 - AUTOLOAD
• Problem
• bypasses the require chain setup by amalgalite
• used by rack, active_support, active_record
• Solution
• Port tree style patches?
• custom gem builds?
47. ISSUE #2 - VIEWS IN WEB
FRAMEWORKS
• Problem
• layout and templates loaded from disk
48. ISSUE #2 - VIEWS IN WEB
FRAMEWORKS
• Problem
• layout and templates loaded from disk
• Solution
• wait for Rails 3
• sinatra, others, make patches for upstream, if needed.
49. ISSUE #3 - CLASS RELOADING
• Problem
• Development mode reloads classes
• Solution ( for now )
• production mode when running as crate based apps
How many of you have full control over your application deployment?
How many of your know how many instance of your application there will be?
Desktop applications?
IT Shops? distribute small apps to your company for command / control monitoring ?
Anyone, in the audience have any ideas?
eee is an exractor written in pascal
eee.gz is ruby + extensions + the application
trailer at the end.
mac, windows, linux, cygwin
Shooes is pretty cool, and targeted towards gui based applications.
I do not want to worry about cleaning up temporary files.
I want to deployt to Solaris, AIX, HPUX, virtually anywhere ruby can run, I want crate to run.
I do not want to worry about cleaning up temporary files.
I want to deployt to Solaris, AIX, HPUX, virtually anywhere ruby can run, I want crate to run.
Create a table to store all the ruby code from the standard library and gems
Very similar to how rubygems works.
1. initialize the ruby interpreter
2. set ARGV for ruby
3. initialize all statically compiled extensions
4. bootstrap the Amalgalite driver
5. remove all filesystem directories from the $LOAD_PATH
6. switch to using Amalgalite backed require
7. require the file in the C constant CRATE_MAIN_FILE
8. instantiate a single instance of the class named in the C constant CRATE_MAIN_CLASS
9. invoke run( ARGV, ENV) on the newly instantiated class
10. exit
I left out a fair bit of nitty gritty details
would you like me to expand on anything, show some more code, yell and scream at me,