Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
# app/metal/poller.rb class Poller < Rails::Rack::Metal def call(env) if env["PATH_INFO"] =~ /^\/poller/ [200, {"Content-Type" => "application/json"}, Message.recent.to_json] else super end end end * There is a generator to help you get started `script/generate metal poller` * Also, metal bits can be ran standalone with rackup `rackup app/metal/poller.rb`
- Loading branch information
Showing
6 changed files
with
60 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
module Rails | ||
module Rack | ||
class Metal | ||
NotFound = lambda { |env| | ||
[404, {"Content-Type" => "text/html"}, "Not Found"] | ||
} | ||
|
||
def self.call(env) | ||
new(NotFound).call(env) | ||
end | ||
|
||
def initialize(app) | ||
@app = app | ||
end | ||
|
||
def call(env) | ||
@app.call(env) | ||
end | ||
end | ||
end | ||
end |
8 changes: 8 additions & 0 deletions
8
railties/lib/rails_generator/generators/components/metal/USAGE
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
Description: | ||
Cast some metal! | ||
|
||
Examples: | ||
`./script/generate metal poller` | ||
|
||
This will create: | ||
Metal: app/metal/poller.rb |
8 changes: 8 additions & 0 deletions
8
railties/lib/rails_generator/generators/components/metal/metal_generator.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
class MetalGenerator < Rails::Generator::NamedBase | ||
def manifest | ||
record do |m| | ||
m.directory 'app/metal' | ||
m.template 'metal.rb', File.join('app/metal', "#{file_name}.rb") | ||
end | ||
end | ||
end |
12 changes: 12 additions & 0 deletions
12
railties/lib/rails_generator/generators/components/metal/templates/metal.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# Allow the metal piece to run in isolation | ||
require(File.dirname(__FILE__) + "/../../config/environment") unless defined?(Rails) | ||
|
||
class <%= class_name %> < Rails::Rack::Metal | ||
def call(env) | ||
if env["PATH_INFO"] =~ /^\/<%= file_name %>/ | ||
[200, {"Content-Type" => "text/html"}, "Hello, World!"] | ||
else | ||
super | ||
end | ||
end | ||
end |
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kewl.. can somebody explain me, what is the metal about?
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great idea!
While the paint is still wet, how about calling it something that matches the descriptive names of “controllers” “models” and “views”?
I suggest “middleware”.
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No tests for this patch? :)
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems to be a recreation of the already simple idea of middleware… but I like it.
Also agree with calling it Middleware, though “Metal” is kinda badass. :)
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can’t kill the metal.
The metal will live on.
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Middleware is a more generic notion for anything that’s used for preprocessing of a request. Metal is intended to be end-points for things that are simple and needs to be really fast. So think of Metal < Middleware.
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Metal sounds much better then “middleware”. But as far as having a “built-in” place to run “middeware code”…. I’m down with that.
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, really? Sigh.
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this a lot. However, I am with drnic. I’d also like to see some “metals” test helpers added to the framework, since this doesn’t seem to fall under the category of model, functional or integration (well, maybe integration).
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@norbert just curious what you don’t dig?
@nakajima integration tests will work great since they test the entire call stack.
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be great for a project of mine if you can still use the session with it. Can you and if so is anything extra needed?
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What “regular” parts of Rails are bypassed in order to make this so much faster?
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty nice! It’s great to see Rails embracing Rack and Rack middleware.
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nakajima yeah I think I’d like to see a test/metal/my_metal_test.rb + some helpers. very sweet.
@josh glad it can still work via integration/cucumber etc
this is the merb-pastie integration that I always wanted; so nice.
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What “regular” parts of Rails are bypassed in order to make this so much faster?
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tjogin, josh replaced the old cgi engine with rack. Rails is just one big rack application now. I think this is pretty cool for intercepting requests that you dont want to be processed by actioncontroller. I’m going to use this for heartbeat monitoring with HAProxy. One caveat while developing: unlike regular controllers you need to restart mongrel/thin when you change any metal.
I think this should be renamed to spikes.
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@samgranieri: So the reason “metal” is so much faster is simply because it doesn’t load actioncontroller? That’s it?
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for “middleware”
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tjogin it would bypass the normal routing system too
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@drnic: Anything else?
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Blacker than the blackest black, times infinity.
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tjogin – http://soylentfoo.jnewland.com/articles/2008/12/16/rails-metal-a-micro-framework-with-the-power-of-rails-m has a speed summary, btw
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tjogin, that’s not entirely accurate.
When the rails app starts up, it ( loads | autoloads | ? ) the framework , including actioncontroller.
The metal is so much faster because it intercepts the Rack call. In the example, if the route containts poller, send a json message, if not, then pass the request to action controller via super
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wycats Glad you like it. I hope this means we can start sharing Rack compatible code between Rails and Merb.
@tjogin it bypasses everything. whatever you code in your metal bit talks directly to the server (mongrel/thin/etc).
Still a bit of confusion about metal == middleware? The answer is no. Metal bits are designed to be endpoints.
I think this commit did not get noticed: http://github.com/rails/rails/commit/06ed8e451198b2296d8b2752741e259b4f995081
I added `config.middleware.use Rack::Cache` to the initializer as a hook for any plugins that want to connect in as middleware.
Yes, I know its really all the same thing but metal does sound really cool :)
@drnic I think integration tests are a good fit here. Thats my opinion though. If you think some helpers are inorder, go for it. (Actually, if I had my way, everything would be an integration test ;)
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@josh: So, since metal bypasses “everything”, does that mean that “metal” code can’t use some of the stuff the rest of a Rails app uses? Like.. ActiveSupport, or anything like that? Maybe I’m curious for too much information too soon. Blogs are likely delve deeper into this.
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tjogin, yeah, ActiveSupport works. http://gist.github.com/36861
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From Ezra’s (sarcastic) tweet (http://twitter.com/ezmobius/statuses/1061662672) “rack middleware you cannot use outside of rails” – what would be the mechanism for a writing a plugin that contained a rack call hook, that could be used in different frameworks (rails/merb/other-rack-super-framework)? Given the rails-specific superclass, then the call behaviour would need to be in a module, and included into either a Rails::Rack::Metal subclass via the rails plugin’s init.rb or hooked into each specific Merb/other-rack-superframework in a specific way? Or can this be generic so its uber simple to write sharable rack plugins that are framework neutral?
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@drnic
config.middleware.use Rack::MyFanaticMiddleware
This is the same api as the rack builder syntax. Its totally compatible. Use any rack middleware with Rails now (on edge ;)
again metal != middleware
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/me found answer to his question in @josh’s comment above
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
drnic I’m assuming that Rails::Rack::Metal will become more featured over time. At the moment there doesn’t seem to be a big win in using it over regular middleware (but again, I expect that might change).
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here’s a novel use for metal: You can use http://gist.github.com/36865 to rickroll every non page cached url. Use at your own risk!
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lifo don’t you use config.middleware.use to set up the Metal classes?
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for naming it middleware.
In the Rack code itself, Rack::File is obviously an endpoint, yet is called middleware. It’s called middleware because it is in the middle of the request → application chain, not because it is an end point or not.
Naming this metal instead of middleware is just going to muddy the waters for newer developers not familiar with rack.
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wycats yes, under the hood the metal is middleware. we inject it into the middleware stack and thats how it intercepts the request. The focus is on the endpoint implementation. Metal bits should be application endpoints, not filters.
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
middlewares do not have to be filters. they can absolutely be endpoints and that is the point. Making a new concept just makes learning rack harder no?
Same concept i blogged ages ago here: brainspl.at/articles/2008/02/16/so-merb-core-is-built-on-rack-you-say-why-should-i-care
I love that you guys are adding this stuff. But I implore you to not embrace and extend but rather just embrace rack and make people learn it. This is just middleware in sheep’s clothing afaict.
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ezmobius The original idea was to have a single endpoint class, and force people use Rack::URLMap. But we didn’t like the idea of forcing people to use that for routing. So we moved the routing logic into the class (which is causing all this confusing). It may be clearer if it looked something like this.
class Poller
def self.call(env)
[200, ….]
end
end
class PollerRouterMiddleware
def call(env) if env[…] == /something/ Poller.call(env) else @app.call(env) end enddef initialize(app)
@app = app
end
end
However, we decided to merge the two for a nicer API. Okay, since Rack::Metal secretly takes an app instance under the hood, is not an endpoint but middleware. But thats not how we want to think of it.
I know still confusing.
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for “middleware”, or some other name that’s more descriptive than “metal”.
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lifo is there an important reason for people to think of it differently? might keeping the (tiny) implementation exposed help people understand what’s going on?
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wycats possibly, maybe that would clear up this mess :)
(btw, I’m not lifo)
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@josh oh snap. /me holds head
My typing fingers have betrayed me!
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, all good comments. If someone wants to propose a change, maybe we should take this to the ML or something. I’m getting lost :)
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for naming it Awesomeware
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think metal is an awesome name and reasonably descriptive. That said, middleware is probably more descriptive but doesn’t it clash nominatively with the generic concept of middleware in Rack?
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@peterc is is middleware in Rack
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for middleware
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pardon my ignorance but this means responses to requests intercepted by metal have to be completely generated manually or at least not with actionpack niceties, correct? Or is it just actioncontroller the one that is not loaded?
Where can I learn more about rack, metal and related subjects?
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Igomez http://rack.rubyforge.org/ and http://book.merbist.com/getting-started/request-path
Rails Edge now uses Rack like merb/sinatra/waves/ramaze/mack so the process is the same.
The Rack middleware receives a rack env and returns a simple tuple containing status, headers, body.
The middleware has access to your models.
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lgomez : Have a look at two posts I had made recently
- http://m.onkey.org/2008/11/17/ruby-on-rack-1
- http://m.onkey.org/2008/11/18/ruby-on-rack-2-rack-builder
Think of Metal as a minimal Rack application.
HTH.
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lifo great posts!
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this will help. Metals are “application-specific” mini apps. Not really designed to be shared. However, you want want to create a plugin, engine, etc you can wrap it in a boarder middleware wrapper that would work on any Rack platform.
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
neat!
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think looks pretty awesome. Excited about the future! I must admit that it took me a while to get the idea, though.
Metal is a cool name but to me it makes no sence. I don’t really like middleware either. I would prefer a plural noun like models, views, helpers, and controllers. I don’t know, maybe spikes. :)
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Horns \m/
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
app/wares? ;)
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tweaked the API:
http://github.com/rails/rails/commit/61a41154f7d50099da371e0d2f22fd25ab9113c2
Metals are now pure endpoints. Not fake middleware, nor any other type of middleware. They are applications, they do not accept a app in their initializer. Did I mention they were not middleware?
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+∞ for metal, but I like “awesomeware” too :-)
I find it really hard to believe that ppl don’t get the difference between “metal” and “middleware”. I don’t think it’s confusing at all. I mean, just look at the code, it’s all there!
@josh: just keep pulling great stuff like this
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mattetti Thanks!
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will really help me out in some stuff I am working on. Thanks!
As far as naming it “Metal”, um, there are 1 billion gems with different names. I think people new to Rails will understand the subject matter after it’s mentioned once or twice. But, maybe it should be named “Derailer” or “Sidetrack”. :D
Thanks again for all your work!
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi,
Is there any possibilities to do rack and metal in rails 2.2 version ?
Please any one help me ASAP.
Regards,
Bala
8c3a543
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bala,
you probably chose the single worst place of all to ask that question. May I suggest the rails-talk mailing list or Stack Overflow as alternatives.
/Jonas