Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Inspired by @JEG2's talk at Rubyconf... Any ruby object, as a webapp! 'Cause we can. :-)
require 'rubygems'
require 'rack'
class Object
def webapp
class << self
define_method :call do |env|
func, *attrs = env['PATH_INFO'].split('/').reject(&:empty?)
[200, {}, send(func, *attrs)]
end
end
self
end
end
Rack::Handler::Mongrel.run [].webapp, :Port => 9292
# ^^^^^^^^^^^
# | (x)
# ROFLSCALE DB ---/
#
# http://localhost:9292/push/1 -> 1
# http://localhost:9292/push/2 -> 12
# http://localhost:9292/push/3 -> 123
# http://localhost:9292/to_a -> 123
# http://localhost:9292/pop -> 3
# http://localhost:9292/shift -> 1
# Implementations in other languages (thanks guys!):
# Node.js: https://gist.github.com/700995
# Groovy: https://gist.github.com/702337
# Python: https://gist.github.com/702001
# Perl w/ plack: https://gist.github.com/703620
# Perl w/ continuity: https://gist.github.com/703651
# Io: https://gist.github.com/703431
# Great explanation of how this works in Ruby on Stackoverflow:
# http://stackoverflow.com/questions/4198883/exposing-any-ruby-object-over-the-web
@mtodd
Copy link

mtodd commented Nov 17, 2010

ROFLSCALE! \m/

@Oshuma
Copy link

Oshuma commented Nov 17, 2010

@igrigorik
Copy link
Author

igrigorik commented Nov 17, 2010

@Oshuma: Nice! :-)

@jinleileiking
Copy link

jinleileiking commented Nov 18, 2010

nice!

@draegtun
Copy link

draegtun commented Nov 18, 2010

Very nice. Here are some implementations I did in Perl & Io:

https://gist.github.com/703620 - Perl using plack
https://gist.github.com/703651 - Perl using Continuity
https://gist.github.com/703431 - Io

@igrigorik
Copy link
Author

igrigorik commented Nov 18, 2010

@draegtun: awesome, thanks! Added your gist links to the one above.

@lucj
Copy link

lucj commented Nov 21, 2010

Hello, this is really great but there are some things I am not really sure. For instance, I cannot get the object class with http://localhost:9292/class.

After:
http://localhost:9292/push/1 -> 1
http://localhost:9292/push/2 -> 12
http://localhost:9292/push/3 -> 123
http://localhost:9292/to_a -> 123

I would expect
http://localhost:9292/class -> Array

Sorry if I'm wrong, just trying to understand :)

Regards,
Luc

@igrigorik
Copy link
Author

igrigorik commented Nov 21, 2010

Luc, you have to be careful with your version of Ruby. Rack expects an object on which you can call "each". Under Ruby 1.9, String does not have an .each method. Chances are, Rack is erroring out because of that. A simple workaround would be wrap every returned object into a "StringIO.new(send(...).to_s))".

@lucj
Copy link

lucj commented Nov 22, 2010

Hello,
Hmm, sounds strange. In fact I'm using Ruby 1.8.7

luc@venus:~/Projects/rubyobject ruby --version
ruby 1.8.7 (2009-06-12 patchlevel 174) [universal-darwin10.0]

Should it work with this version ?
Thanks a lot for your help.
Regards,
Luc

@igrigorik
Copy link
Author

igrigorik commented Nov 23, 2010

Yep, 1.8.7 should work. What does your console output when you run the server and make that request?

@lucj
Copy link

lucj commented Nov 24, 2010

hmmm, you'r right, it's talking about the each method... but I'm running ruby 1.8.7

config.ru:1:in new' config.ru:1 Wed Nov 24 16:03:46 +0100 2010: Read error: #<NoMethodError: undefined methodeach' for Array:Class>
/Library/Ruby/Gems/1.8/gems/rack-1.2.1/lib/rack/chunked.rb:37:in each' /Library/Ruby/Gems/1.8/gems/rack-1.2.1/lib/rack/handler/mongrel.rb:80:inprocess'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:159:in process_client' /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:158:ineach'
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:158:in `process_cli

@igrigorik
Copy link
Author

igrigorik commented Nov 25, 2010

Right, you're seeing the problem I described below. You need to convert everything to a StringIO and then you're good to go.

@danny
Copy link

danny commented Dec 12, 2010

So I updated it a bit in my fork; it removes url encoding and returns json serialization of results

https://gist.github.com/737959

@igrigorik
Copy link
Author

igrigorik commented Dec 12, 2010

@danny: nice!

@Burgestrand
Copy link

Burgestrand commented Jan 25, 2011

How come you didn’t settle with def self.call(env) instead?

require 'rack'

class Object
  def to_webapp
    def self.call(env)
      func, *attrs = env['PATH_INFO'].split('/').reject(&:empty?)
      [200, {}, send(func || :inspect, *attrs)]
    end
    self
  end
end

Rack::Handler::WEBrick.run [].to_webapp, :Port => 9292

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment