Category Archive for Ruby

Our Git deployment workflow

August 03, 2008

At weplay, we recently switched to pure git version control from git-svn. Now that we've had a couple weeks for the dust to settle, I'd like to share our workflow for managing deployments to our staging and production clusters.

We started by outlining the goals of our system:

  • All code that's pushed to our staging and production environments must be in GitHub. Nothing goes straight from a local repository to our servers.

  • Any developer can deploy our most recent work to staging.

  • Any developer can deploy the code on staging into production. We (try to) avoid deploying anything to production that hasn't been pushed to staging first.

  • Any developer can see a diff between "What is deployed" and "What I'm about to deploy."

  • Any developer can branch from the production codebase for time sensitive tweaks and fixes. These need to be staged before they're deployed to production too.

  • That functionality is available in an automated, safe, easy to use form. (Hint: rake)

We ruled out having "production" and "staging" tags because updating tags across a tree of remotes doesn't seem to work smoothly. We also ruled out doing git merges from master into our staging branch. Our staging server/codebase jumps around from the latest changes to the production code (up to a week old) based on what we need to test, so we really just want to replace it.

We settled on using remote git branches for production and staging on origin and hard resetting them to other branches to simulate a copy. We treat these branches more like tags and never commit to them directly. This has worked great so far.

Here's what our rake tasks look like:

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
88
89
90
class GitCommands

  def diff_staging
    `git fetch`
    puts `git diff origin/production origin/staging`
  end
  
  def tag_staging(branch_name)
    verify_working_directory_clean
    
    `git fetch`
    `git branch -f staging origin/staging`
    `git checkout staging`
    `git reset --hard origin/#{branch_name}`
    `git push -f origin staging`
    `git checkout master`
    `git branch -D staging`
  end
  
  def tag_production
    verify_working_directory_clean
    
    `git fetch`
    `git branch -f production origin/production`
    `git checkout production`
    `git reset --hard origin/staging`
    `git push -f origin production`
    `git checkout master`
    `git branch -D production`
  end

  def branch_production(branch_name)
    verify_working_directory_clean
    
    `git fetch`
    `git branch -f production origin/production`
    `git checkout production`
    `git branch #{branch_name}`
    `git checkout #{branch_name}`
    `git push origin #{branch_name}`
  end
  
protected

  def verify_working_directory_clean
    return if `git status` =~ /working directory clean/
    raise "Must have clean working directory"
  end
end


namespace :tag do
  desc <<-DESC
    Update the staging branch to prepare for a staging deploy.
    Defaults to master. Optionally specify a BRANCH=name
  DESC
  
  task :staging do
    branch_name = ENV['BRANCH'] || "master"
    GitCommands.new.tag_staging(branch_name)
  end

  desc "Update the remove production branch to prepare for a release"
  task :production => ['diff:staging'] do
    GitCommands.new.tag_production
  end
end

namespace :diff do
  desc "Show the differences between the staging branch and the production branch"
  task :staging do
    GitCommands.new.diff_staging
  end
end

namespace :branch do
  desc "Branch from production for tweaks or bug fixs. Specify BRANCH=name"
  task :production do
    branch_name = ENV['BRANCH']
    raise "You must specify a branch name using BRANCH=name" unless branch_name
    GitCommands.new.branch_production
  end
end

namespace :deploy do
  desc "Tag and deploy staging"
  task :staging => "tag:staging" do
    `cap staging deploy:long`
  end
end

The last one (rake deploy:staging) simply wraps up the common task of tagging our latest code to be pushed to staging and initiating a staging deploy.

Note: To use most of these commands, your local working directory must be clean. If we have outstanding changes in our tree when we need to run them, we use git-stash to temporarily move them out of the way.

Thanks to Scott Chacon for helping us work this out. Be sure to check out his GitCasts and Git Internals PDF.

Story Driven Development slides posted

April 26, 2008

Just wrapped up my Story Driven Development talk at GoRuCo 2008. There were some great questions at the end, and I'm looking forward to more hallway track conversations about SDD.

Download the slides as a PDF (1.6 MB)

Note: Confreaks is recording the talks today, so a full video of my presentation should be online soon.

Presenting at GoRuCo in NYC

February 09, 2008

I just received word that my proposal to speak at NYC’s very own second annual GoRuCo has been accepted. The conference is set for Saturday, April 26th at Pace University downtown. My topic will be the same as my Scotland on Rails presentation.

I’m really excited to have the opportunity to present at home, in front of many of my friends and colleagues. Now I just need to make sure I don’t suck. Better get back to working on my slide deck…

Presenting at Scotland on Rails

January 31, 2008

I’m going to be presenting on Story Driven Development at the first Scottish Ruby on Rails conference, Scotland on Rails. I’ll be exploring the concept of Story-first development from both an agile process and implementation standpoint.

Topics will include:

  • Collaborating with the product owner on stories
  • What makes good stories and scenarios?
  • Driving stories with a browser simulator like Webrat
  • Potential pitfalls and ways to avoid them

If you’re going to be in Edinburgh for the conference, let me know.

"What's new in Rails 2?" slides posted

December 12, 2007

Thanks to everyone who attended my “What’s new in Rails 2?” talk last night at NYC.rb. The questions were great, and I picked up a few tips myself from the discussions we had.

Download the slides as a PDF (1.4 MB).

Save the date: GoRuCo will be April 26th, 2008

December 08, 2007

The second annual Gotham Ruby Conference a.k.a. GoRuCo will be held Saturday, April 26th 2008 at Pace University in Manhattan. Last year was a great day of learning and socializing with fellow Ruby geeks, and we expect this year to be even better. I’ll see you there!

Speaking at NYC.rb on Tuesday

December 08, 2007

On Tuesday, December 11th, I’ll be speaking at NYC.rb about “What’s new in Rails 2?”. Come by and watch or check back after then and I’ll be sure to have my slides up.

Webrat 0.1.0 released

December 08, 2007

Last week I pushed Webrat 0.1.0 out the door. So far the response has been great, and I’ve already received a couple patched (Thanks, David!). Here’s a quick usage example (from the README):

1
2
3
4
5
6
7
8
def test_sign_up
    visits "/"
    clicks_link "Sign up"
    fills_in "Email", :with => "good@example.com"
    select "Free account"
    clicks_button "Register"
    ...
  end

Behind the scenes, this will perform the following work:

  1. Verify that loading the home page is successful
  2. Verify that a “Sign up” link exists on the home page
  3. Verify that loading the URL pointed to by the “Sign up” link leads to a successful page
  4. Verify that there is an “Email” input field on the Sign Up page
  5. Verify that there is an select field on the Sign Up page with an option for “Free account”
  6. Verify that there is a “Register” submit button on the page
  7. Verify that submitting the Sign Up form with the values “good@example.com” and “Free account” leads to a successful page

Take special note of the things not specified in that test, that might cause tests to break unnecessarily as your application evolves:

  • The input field IDs or names (e.g. “user_email” or “user[email]”), which could change if you rename a model
  • The ID of the form element (Webrat can do a good job of guessing, even if there are multiple forms on the page.)
  • The URLs of links followed
  • The URL the form submission should be sent to, which could change if you adjust your routes or controllers
  • The HTTP method for the login request

A test written with Webrat can handle these changes smoothly.

SVN is at http://svn.eastmedia.net/public/plugins/webrat/. Check out the full README.

Scourging your Ruby code with Flog

September 13, 2007

Flog is a tool build by Ryan Davis to analyze Ruby code complexity. It’s dead simple to run, and immediately provides useful metrics in the form of a “Flog score” per method. Don’t get too hung up on the actual values, but high outliers are prime candidates for refactoring.

I ran this on a couple recent projects I worked on, and it proved quite accurate in identifying the areas of code that seem to be in the most pain. Flog doesn’t replace hands-on code review, but it is still a helpful aid.

Below is a rake task I threw together for running Flog on a Rails project. Seems like a great candidate to install via Chris Wanstrath’s Sake, a system for handling Rake tasks that you want to be available from anywhere.

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
def flog(output, *directories)
  `find #{directories.join(" ")} -name \\*.rb|xargs flog > #{RAILS_ROOT}/tmp/flog/#{output}.txt`
end

desc "Flog models, controller, helpers and lib"
task :flog do
  flog "all", *%w[app/models app/controllers app/helpers lib]
end

namespace :flog do
  desc "Flog code in app/models"
  task :models do
    flog "models", "app/models"
  end
  
  desc "Flog code in app/controllers"  
  task :controllers do
    flog "controllers", "app/controllers"
  end
  
  desc "Flog code in app/helpers"  
  task :helpers do
    flog "helpers", "app/helpers"
  end
  
  desc "Flog code in lib"  
  task :lib do
    flog "lib", "lib"
  end
end

Export Rails ActiveRecords to CSV

April 28, 2007

For a recent “enterprisey” project I’m working on, we had to offer a variety of CSV exports for many of the models in our system. Ruby’s FasterCSV library is great for raw parsing and generation of CSV data, so I used that as the basis for a quick and dirty system to easily provide customizable exports.

The main features are:

  • Transform an array of exportable records into a whole CSV file. (By default, FasterCSV transforms arrays into a single CSV row.)
  • Export a whole table my calling .to_csv on the ActiveRecord subclass.
  • By default, export all of an ActiveRecord’s columns except for created_at and updated_at.
  • Allow simple customization of exportable columns by overriding the export_columns method in your ActiveRecord class.
  • Allow multiple CSV formats by conditionally branching inside the export_columns method depending on the format parameter.
  • Allow complete customization of the export by overriding the to_row method. (I haven’t actually needed this much customization yet.)

The simplest example:


Address.to_csv

Customizing the columns included in the CSV:

1
2
3
4
5
class Address < ActiveRecord::Base
  def export_columns(format = nil)
    %w[city state postal_code]
  end
end

Multiple output formats:

1
2
3
4
5
6
7
8
9
10
class Address < ActiveRecord::Base
  def export_columns(format = nil)
    case format
    when :local
      %w[street1 street2 city state postal_code]
    else
      %w[city state postal_code]
    end
  end
end

Here’s the code:

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
require "fastercsv"

class ActiveRecord::Base
  def self.to_csv(*args)
    find(:all).to_csv(*args)
  end
  
  def export_columns(format = nil)
    self.class.content_columns.map(&:name) - ['created_at', 'updated_at']
  end
  
  def to_row(format = nil)
    export_columns(format).map { |c| self.send(c) }
  end
end

class Array
  def to_csv(options = {})
    if all? { |e| e.respond_to?(:to_row) }
      header_row = first.export_columns(options[:format]).to_csv
      content_rows = map { |e| e.to_row(options[:format]) }.map(&:to_csv)
      ([header_row] + content_rows).join
    else
      FasterCSV.generate_line(self, options)
    end
  end
end

GoRuCo talk: Business Natural Language

April 21, 2007

Presented by Jay Fields

  • Business Natural Language (BNL) is Domain Specific Language (DSL)
  • Traditional feedback loop: Business <- Developer -> QA
  • With DSLs: Business stakeholders update logic

Benefits

  • Managers—Improve efficiency
  • Developers—Technical decisions not business decisions
  • Business—Reduce time to market

(BNL == BSL) # => false

So?

  • Concise or verbose?
    • Less technical users might need more verbose DSL
  • Who’s the author?

“DSL” is too general

  • BNL is a subset of DSL
  • BNL characteristics differ from general DSL characteristics

The Difference

  • Written as natural language
  • Written by business people
    • Subject matter experts

Example specification

  • “Award 2 points if the fare class is A, C, D, J, Z”
  • account.award 2.points if [A,C,D,J,Z].include?(fare)

How?

  • Use preprocessor…
  • account.instance_eval removes need for account.
  • Use gsub to downcase fares (to avoid them being read as constants)
  • Fixnum.point does nothing. It’s syntax sugar.
  • Remove the word “class”. Not needed by Ruby.
  • gsub to add brackets around a list
  • gsub to remove words without business meaning (i.e. “the”)

Result: Specification == Code

  • Specification is code
  • Specification is readable documentation

Descriptive and maintainable phrases (DAMP)

  • More verbose, but verbosity makes them maintainable.
  • Since the business users control the logic, it’s easier to maintain

Do not sacrifice readability for conciseness

  • Staff changes
  • Other people will eventually need to read it

Who is the user?

  • Who are you designing for?
  • Verbose phrases are not strictly necessary but help subject matter expert maintain the language

Training

  • BNL has room for improvement if it requires any training to understand
  • Make your language fit the requirements instead of the requirements fitting your language
Applications can be built 80% faster with DSL
  • Actually, that’s bullshit.
  • But… “A change that used to take 3-4 days now takes 10 minutes.”

Why not offload non-interesting parts of the application to people who actually care about the rules?

Getting it to execute

  • BusinessLogic returns the rules from the DB
  • eval it once when we change the method, then save it as a method
  • One run eval again when rules change

Deployment?

  • New workflow: Business <> Approver <> Production
  • Developer not in the process
  • Flag scripts as “active”, expire old scripts

Programmers: Are you out of a job?

  • Absolutely not
  • Still need:
    • Language workbench
    • Workflow
    • Syntax checking
    • Test environment

Syntax checking

  • Very important
  • Needed for subject matter experts
  • Usually need contextual recommendations (i.e. “when the far” => “Did you mean ‘fare flass’?”)
  • Can be done with AJAX

Commercial language workbenches

  • MPS – JetBrains
    • Beta, but usable
    • Fowler has “hello world” examples
  • Intentional—Not available

Another example—Employee compensation

  • Verbose, but everyone can read it

When is BNL a bad choice?

  • Broad, unrelated project
  • Not necessary for programmers

How to decide?

  • Who is the author?
  • How frequently will the logic change?

How is this relevant to Ruby?

  • Not required, but easier than in Java or others
  • Need eval

More information

GoRuCo talk: Contexts, mocks, and stubs. Oh my!

April 21, 2007

Presented by Trotter Cashion

Beyond Test::Unit

  • FlexMock
  • Mocha and Stubba
  • Test/Spec – Brings RSpec to Test::Unit
  • spec-unit—Written by Trotter. Similar to Test/Spec. Has nested contexts.
  • RSpec—Total Test::Unit replacement.
    • Switching to RSpec is not necessary to use these concepts.

Why should you care?

  • Contests
    • Let you organize specs with shared setup
    • Isolate specs that should not be affecting eachother
  • Mocks versus stubs
    • Mocks validate the method calls
    • Stubs don’t care
  • Use mocks when you need to be sure
  • Use stubs when you don’t care—helps avoid brittle tests

What I’m not talking about

  • RSpec
  • Mocha and stubba
  • Test/Spec

That leaves…

  • Spec-unit
  • FlexMock

Risks

  • Active development—APIs still changing
  • You might get too excited

Benefits of mocking

  • More focused testing
  • Better application design
    • Mocking lets you think about the interface without building client classes

Code walkthroughs followed…

GoRuCo talk: Classifying documents using Ruby

April 21, 2007

Presented by Paul Dix

UPDATE: Paul posted a zip file of the code he referenced in his talk.

What are classifiers?

  • Most common application is spam vs. ham (usually naive bayes)
  • Supervised machine learning

Useful For…

  • Detecting language (French, English, etc.)
  • Categorizing news and blogs
  • Spam detection (email, trackback, wiki, comment, etc.)
  • Sentiment detection (for example, determine positive vs. negative movie reviews)

Things You Do

  • Get training data
    • Set of documents that are labeled
    • The more the better
  • Document preprocessing—convert it to a form that machine learning programs can deal with
  • Feature selection (optional)—improves accuracy
  • Train the classifier
  • Test and update

Text classification represents documents as a vector of features

Basic representation

  • Count of terms
  • Steps:
    • Clean text of punctuation
    • Lowercase
    • Split on spaces
    • Stem all words
    • Return an array of counts

Document by term (or feature) matrix

  • Count of term frequency by document

Additional features

  • You can create complicated preprocessing
  • Examples:
    • Include link structure
    • Include metadata
    • Include social data

High dimensionality

  • Noisy features (i.e. count of the word “the”)
  • Non-discrimating features (i.e. a word only once)
  • Words that are too similar

Stemming

  • Most popular: Porter Stemmer – Dr. Martin Porter ‘79
  • "cats".stem # => "cat"
  • "international".stem # => "intern"
  • "finalize".stem # => "final"
  • "ruby".stem # => "rubi"

Advantages of features selection

  • Limits size of vocabulary and matrix
  • Increase classification accuracy
  • Avoids noisy features and over-fitting

Methods for feature selection

  • Mutual information
  • Chi-squared (statistical independence of two variables)
  • Frequency based

The process of feature selection

  • Add each document from training set
  • Calculate features
  • Select best features

Feature extraction

  • Selected features from each document

Linear classifiers

  • Finds hyperplane
  • Simple decision boundary
  • Binary classification (i.e. spam vs. not spam)

Naive Bayes

  • Classifier gem
    • Doesn’t give you much control of how everything works
  • Generative model using probabilities
  • Bayes formula

Why is it called “naive”?

  • Positional independence (words location in document does not matter)
  • Conditional independence (one word does not impact other words)
  • Also known as “Idiot’s Bayes”

Naive Bayes advantages

  • Simple
  • Very fast (runs in linear time)
  • Very effective for text classification

Other considerations

  • Binomial (occurs/does not occur) vs. multinomal (how many occurrences?) models
  • Probabilities of classes based on training set
    • Overall probability between classes (is it 50/50, or 90%/10%?)

Support vector machines (SVM)

  • State of the art
  • Hard to use
  • Ruby has bindings for SVM

Kernels

  • a.k.a. “the kernel trick”
  • Method that transforms the kernel space
  • Non-linear classification
  • Four main ones: linear, polynomial, radial basis function, sigmoid
  • Use existing code… you don’t write your own

Perceptron

  • Neural network
  • Linear classifier
  • Converges through iterations
  • Not guaranteed to converge

k nearest neighbors

  • Non-linear
  • Arbitrarily complex decision boundary
  • No traditional training
  • Can be slow for large training sets

Others

  • Decision trees
  • Rocchio
  • Compression
    • Squish by Bob Aman
    • “Mind meltingly slow”
  • Latent semantic analyxix
  • Weka—Java-based processing library
    • Could be used with JRuby

Multiple classes

  • “Any of” classification – Not mutually exclusive
    • Train classifier for each classification (for example, “about Ruby” and “not about Ruby”, “about CSS” and “not about CSS”)
  • “One of” classification
    • i.e. language identification
    • Becomes hard as number of classifications increases

Bias-variance tradeoff

  • Linear classifiers are high bias
  • Non-linear classifiers are high variance

Testing classification

  • Each classification task is different
    • Hard to predict
    • Need to test and tune
  • Constant testing

Basic methods

  • Training and test sets
  • Accuracy – # correct/# total
  • Cross validation
    • 10 fold is common

Closing observations

  • Some tasks are easier than others
    • Can expect >90% on easy tasks
  • Best for triage
  • Naive Bayes is simplest to work with

Q & A

  • Q: How much training data?
  • A: The more the better. 50 is not going to give you good results.
  • Q: What about using temporal proximity as a feature?
  • A: You could do that by having features like “close in time to X”, “close in time to Y”, etc.

GoRuCo talk: Going Camping

April 21, 2007

Presented by Jeremy McAnally

History of the tent…

  • Native Americans
  • Hippie fests
  • Crazy diagrams

What is Camping?

  • MVC architecture
  • ActiveRecord for models
  • Markaby for the views
  • Everything goes in one file
  • File has modules for each MVC component
  • Run camping

When should you use Camping instead of Rails?

  • When Rails is too fat
  • Right tool for the right job
  • You ain’t gonna need it

Controllers in Camping

  • Classes define actions instead of methods in Rails
  • Methods within those classes handle HTTP method types (GET, POST, etc.)
  • Routes baked into action definitions

Camping Views

  • Markaby is “Markup in Ruby”
  • No more ERb!
  • Methods define tags
  • Will complain about invalid HTML
  • Blocks build tag heirarchy
  • Attributes as a hash

Models in Camping

  • Simply ActiveRecord models
  • Defaults to SQLite
  • You can also use migrations
    • No down migrations, but you can script that
  • Can use acts_as_versioned and other AR-specific plugins

Deployment

  • Much easier than in Rails
  • Don’t use Camping server (just like we don’t use Webrick)
  • Can be deployed in a variety of environments
    • Mongrel!

What if my application gets big?

  • Possible to split a Camping app into multiple files (use require)
  • At that point, you should probably use Rails

Databases

  • Camping defaults to SQLite
  • But supports other RDBMS options

Sessions

  • Camping has support
  • Include a module, it acts like Rails

Testing

  • Use Mosquito for bug-free Camping
  • Not in the default package, but still available

Form helpers

  • Gregory Brown wrote a snippet to get form helper support in Camping
  • Can use form_for syntax

Serving static files

  • Does not work like Rails
  • Static files can be embedded in a Camping application
  • They can be read from disk using File.read (better)
  • Have the web server do it (best)

Before/after filters

  • Override the service method and put logic before and after it
  • Not as flexible as Rails’ filter DSL

Decamper

  • Converts Camping application to Rails applications
  • Status is unknown

Kindling

  • Library I started to pull top 5-10 “Railsisims” in Camping
    • before/after filters
    • file upload
    • etc.

Q & A

  • Q: Is it possible to use something other than Markaby with Camping like XMLBuilder? (from Jay Phillips)
  • A: Yes. Extend my ERb templating code to use Builder or something else. The code is simple.
  • Q: Can you exaplain the syntax for inheriting a class from R?
  • A: Uses regular expression to do routing. You have to use your own.

GoRuCo talk: JRuby: Ready for Prime Time

April 21, 2007

_Presented by Nick Sieger

JRuby: Java on the JVM

  • Currently targetting Ruby 1.8
  • Some work on trunk Ruby also
  • Started in 2002 with a direct C to Java port
  • JRuby aims to be a great way for running Ruby applications

But really… Java?

  • “COBOL of the Internet age”
  • Applets never fulfilled their promise—“Really cool!”
  • It’s Enterprisey!
  • “Write one, run anywhere” = “Write once, run nowhere” (Linux)

Seriously though…

  • Java brings battle-tested performance in the form of the JVM to Ruby
  • Makes up for deficiencies in C Ruby implementation

HotSpot: World Class VM

  • Dynamic analog to a C compiler
  • We used to optimize C by writing assembly
  • HotStop will compile your code down to bytecode
  • Determines “hot spots” in code and optimizes
    • Method inlining
    • Removing sync bottlenecks
    • Lots of other stuff

Threading

  • Ruby uses green threads
  • To use multiple CPUs you must have multiple processes
  • JRuby maps Ruby threads to Java native threads
  • Let you stay in-process and leverage multiple CPUs

Unicode

  • Ruby’s take—String is just a byte array
  • Java’s take—Everything is Unicode
  • JRuby must bridge this gap
  • Uses strings as byte arrays, but performs conversion

Garbage Collection

  • HotSpot has four GCs
  • Seperates long-lived and short-lived objects
  • Has options for optimizing GC performance
  • Lots of tuning variables
  • Ruby doesn’t have these

Runtime GUI

  • Java has a GUI to let you see CPU usage, threads, memory of running JVM
  • This could be hooked up to JRuby

JRuby Compiler

  • Not everything, but “good enough”
  • Can run in ahead-of-time or “just in time” (JIT) mode
  • Can fall back to interpretted mode
  • A compiler (JRuby Compiler) on top of another compiler (HotSpot)

Dual-Compilation

  • Multiple steps of compilation and optimization
  • Potentially have Ruby code compiled down to native code in the future

YARV Benchmarks – Ruby vs. JRuby

  • JRuby in interpretted mode slower than C Ruby, but getting better
  • JRuby in compiled mode is faster than C Ruby for some benchmarks

What’s Coming

  • 0.9.9 release coming on Monday
  • 0.9.9 is focused mostly on compatibility
  • 0.9.9 overall approx. 40% faster than 0.9.8

Compatibility – Test Suites

  • Using whatever we can find
  • Rubicon, Rubinius specs, ruby_test, Rails tests, RSpec’s specs, etc.
  • Two Google Summer of Code projects using RSpec to spec Ruby language

What’s Supported?

  • Rubygems
  • RSpec
  • Rails
  • Rake
  • Hpricot
  • Camping

Automated Builds

  • JRuby has over 900 tests

Demo Time!

  • Swing GUI in Ruby
    • Avoid ridiculous amount of Java code for Swing apps
  • RSpec

Deployment

  • WAR file is a web application in a package
  • J2EE spec says you can drop in WAR files for easy deployment (Sometimes not actually the case)
  • We want to allow the same database.yml file for JRuby deployment in the next few months
  • Mephisto running under JRuby from a WAR file. \m/

Q & A

  • Q: Is it possible to have Java class files dynamically compiled and loaded into Ruby?
  • A: There’s no straightforward way to do that. Ryan should do Java version of Ruby inline.
  • Q: Is there any effort for one-step JRuby web serving?
  • A: WAR plugin has support for Jetty. It would be good to have a Locomotive-style package. We haven’t done it yet. Still working on making it easier for plain vanilla Java deployment.
  • Q: Can you compare JRuby with Jython?
  • A: Similar projects. Jython is not as far along. Jython is compiled only. Serving same purpose for respective languages. Jython has been around longer. We’ve got some Jython users on the JRuby mailing list.

Resources