I'm really enjoying your Rails 2.3 screencasts.
Thanks again.
Hi Ryan,
another great screencast as usual - thanks! A quick question - you mention that it wouldn't be a good idea to use your example in a production environment - why not? I'd liker to display the response time on a page (like Google does on a search results page for example), and this looks like a good way to do it. Is there a performance hit by using this perhaps?
Ah, the #151 is here ! Very good Ryan, as always ! ;-) I hope a #1000 and even a #2000. ^^
Sounds useful, but I have to admit you lost me on this one Ryan. Lots of unfamiliar territory.
Awesome!
Maybe not a huge concern for your example, but it is not threadsafe. You should never modify instance variables in the call method.
However, there is a quick trick to get around this: http://pastie.org/404695
If anyone wants a more in-depth look at how to write Rack Middleware (and Rack apps), you might like my Rack Middleware screencast:
http://remi.org/2009/02/28/rack-part-3-middleware.html
Thanks for showing off all of the sweet things that we get with Rails 2.3, now that Rails has such awesome Rack support :)
A really nice overview, but with a potential gotcha for those that that use the example in a real app:
Nothing should ever appear before the DOCTYPE.
You'll start seeing some definite quirks in different browsers if anything not-DOCTYPE comes first, including comments.
Nice episode. Keep it going.
Ryan, can you give me some more specific areas where it can be used in production environment? I mean more scenarios where it makes sense to use RACK middleware!
I think, that @headers['Content-Length'] should by updated to reflect the change in the response length. Otherwise Rack::Lint will complain.
Middleware seems quite powerfull. I am currently using Sven Fuchs routing-filter plugin so I can support more search friendly urls. I am using it so my cms can respond to resource path's stored in the database (like: host/research/forums). Maybe it could be solved with a middleware instead?
@wlodek yep, if you do this for real, you absolutely need to update the Content-Length, and not just for Rack::Lint.
If you add text to the response body without updating the Content-Length, the HTML you see in the browser may be truncated (because the browser is only displaying the *original* number of characters, before you added more text to the response body).
Ofcourse, you can use another middleware to ensure that Content-Length is always set to the length of the response body. Rack comes out of the box with Rack::ContentLength for doing something like this, but I think it only works under certain conditions. It would be easy to write your own middleware to accomplish this, if need be, but it's a good idea for your middleware to always make sure to update the Content-Length, itself.
@Dave Hollingworth: I'm pretty sure Ryan ment that adding a _comment_ before the DTD would not be really useful in production environment. If you want the user to see the response time it might be useful.
Cheers,
David Knorr.
@Ryan: Nice screencast, as usual.
@Joshua Peek: +1, except I would rename '_call' to the more conventional 'call!'.
Hi Ryan, thanks for this nice episode. One thing I need to request you. It would be too nice of you if you could dedicate one episode on GSA (Google Search Appliance) search. I know many people are using it and it would really help people learn it further if you produce one episode on how to implement GSA search in Rails App.
@Shreyans:
I blogged a little while back about how I used middleware to help with a flash file uploader:
http://tinyurl.com/desshu
While the middleware doesn't look like it does much, it replaces a much more hacky and lengthy solution that had to be used in the 'olden days' :D
@Dave, I would not use this specific middleware in production because it is not the best way to measure performance. Instead you should use something like NewRelic's RPM. It is also bad to add an HTML comment to the very top of the page before the doctype.
I think Google's response time display is primarily the time the search took to process, I would do that within the Rails app itself and not though middleware.
@Graham, sorry to lose you. This is a fairly advanced topic. Expect some more intermediate content soon.
@Joshua, thanks for pointing this out! I'll update the code so it is thread safe.
@Stephen, right, placing a comment above the doctype is not ideal. This is one reason why I mentioned to not do this in production.
@Shreyans, check out the rack-contrib project linked to in the show notes. That has a lot of production ready middleware examples.
@wlodek, @remi good point! I'll add a note about this.
Ryan,
I've been a big fan for some time now, however one comment:
It seems to me that your essentially using instance variables instead of parameter passing. With the addition to what @Joshua pointed out, this makes this code very hard to test. This example is maybe too simple to illustrate this, but more complex certainly would need some unit tests.
This structure means you would have to either invoke call before invoking each in your tests, or use Object#instance_variable_get, which is ugly at best.
Perhaps a better way might be to create a business object that wrapped response with all the other variables you need:
http://pastie.org/406393
This is both thread safe *and* testable
@Amit, good suggestion. That does make things easier to test and elegantly handles the thread-safety issue. One might also consider nesting the body class within the timer. I feel better about keeping them in the same file this way.
http://pastie.org/406597
Thanks Ryan, a very interesting railscast, and the link to rack-contrib helps newbies like me understand what all this rack middleware stuff is good for. :)
Hello Ryan,
Great screencast as usual. Can you explain a little about
block.call( "... stuff .... ")
@response.each(&block)
How is it that "...stuff..." gets inserted into the response.body by calling the block? And how is that equivalent to "...stuff...." + response.body?
Thank you,
David :)
Ryan,
I've been watching your railscasts and liked them very much.
In one of them you are watching the contents of development.log on OS X terminal as it changes.
Please let me know the command/tool to watch the runtime changes to the files.
Thanks in advance.
Regards,
Rajan
@DavidBeckwith: the answers to your questions can be found in the Rack interface specification:
http://rack.rubyforge.org/doc/files/SPEC.html
Note that the body of a Rack app (and middleware are Rack apps) is anything that responds to #each and returns String values. Ryan could have built the body of the response and then prepended it with "..." but, instead, he basically says "the first time #each is called, i'll return my custom string, then i'll just pass the block along to the response's #each".
For more, definitely check out the Rack interface specification or my Rack screencasts @ http://remi.org
Thanks Ryan! Here's my notes for this screencast (also available at:
http://railsnotes.wordpress.com/2009/03/08/rails-rack-middleware-screencast-notes )
RailsCasts #151 Rack Middleware Notes
* Rack Middleware = filter which you can use to intercept a request and handle the behavior a little differently as it goes to and from the application
* Different between middleware & metal = Metal is an endpoint & middleware is designed to be more of a filter (changes behavior if it needs to.)
* Goes into /lib directory as a .rb file?
* All middleware takes a initialize(app) method. The app variable will hold the rails application
* Adding a call(env) method will make it override rails. This needs to return a array with the same 3 elements as a metal.
* to make rails use your middleware, add this to your environment.rb file inside the Initializer block: config.middleware.use "NameOfClass"
* 'rake middleware' will list out the middlewares used by your app
* You'll need to restart the server every time you create/change a middleware
* To execute your rails app from your middleware, just run .call on the rails app, ex: @app.call(env)
* you can assign parts of the response from a rails app to variables using something like this:
status, headers, response = @app.call(env)
* and then you can call return those back to the real response using something like this:
[status, headers, "Add stuff" + response.body]
* response.body assumes that the app is a rails app. this is not best practice.
* a better approach is to use [status, headers, self] together with def each(&block) `
Rajan,
You can watch live changes to your development.log file by doing "tail -f log/development.log"
Ryan, thanks for that as always.
I've Been putting off moving over to 2.3 for a while now, but this convinced me that rack is the perfect solution for a problem I've been seeing with cookieless sessions whereby some phones won't send get and post parameters as part of the same request.
Great screencast as usual, thanks Ryan.
It's worth re-iterating that whenever you write middleware, it's always worth sticking Rack::Lint *on either side of it*, to check you don't inadvertantly break requests and responses.
Essentially, Rack::Lint *is* the Rack spec, so it saves you a lot of reading :)
It is nice screencast for Rails 2.3. What about Rails 2.1? How do I use Rack in Rails 2.1? Any screencast for that?
Hi Ryan,
Great screencast for rails 2.3.Take care of commenter Melvin Ram above,he also explains extras.
Please let me know the command/tool to watch the runtime changes to the file.
Good post.It is very usefu.I like to see it because I am learn it now.Thank you.
Hey, just thought i'd say i had a problem running the 'hello world' bit, i was just getting a '#' on the screen. Sorted it by putting the 'Hello world' in square brackets.
def call(env)
[200, {"Content-Type" => "text/html"}, ["Hello world"]]
end
This is a good post, I stumbled across your article while looking for song downloads. Thanks for sharing, I’ll be sure to recommend this site to others.
I had received the first edition of “Make” magazine as a gift and it was really awesome…
This is really fabulous!
I already have some of them but I am still going to save all of them.
Thanks for your wonderful sharing.
Great resource. Thanks for sharing.
Your site is amazing so I have featured it in my design blog..
Thanks For posting,Very Nice Keep up date a more article.
commission must impose fines or other sanctions against those who may have violated rules.
I am looking to Skype for the first time with other HS students who are learning Spanish. Please
let me know if you are interested!
I am looking to Skype for the first time with other HS students who are learning Spanish. Please
let me know if you are interested!
It is always important to split up the site as much as possible so that certain pages can focus on certain services. The user experience is much better as well.
Three blonde women were stranded on an island. While trying to dig their way out, one of them came across a buried lamp. Suddenly a genie appears and offers to grant each one of them one wish, in return for saving him.
These kind of post are always inspiring and I prefer to read quality content so I happy to find many good point here in the post, writing is simply great, thank you for the post
I think my brain just exploded when reading this post. Awesome work.
Great post you have here, please keep up this great work
Interesting,Keep up the good work,
Thanks for writing, most people don't bother.
Very good blog.Thank you for sharing.Best wishes !
nice consept wiht good stuff, i has bookmark it
With the help of the online stores,we can buy the cheap prom dresses.If you are lucky,you can buy the <a href="http://www.promdressesin.com/dress-between-50-100-37">prom dresses under 100 dollars</a>.Do not hesitate,hurry up to have a look!
Considerably, this post is really the sweetest on this notable topic. I harmonise with your conclusions and will thirstily look forward to your incoming updates. Saying
thanks will not just be sufficient, for the phenomenal clarity in your writing.
Cracking screencast, thanks. I just used metal to load Nesta (a Sinatra CMS) into the same process as a Rails 2.3 app.
I'm sure I wouldn't have found out how to do it so smoothly if I hadn't watched this.
Great!This article is creative,there are a lot of new idea,it gives me inspiration.I think I will also inspired by you and think about more new ideas
Gucci world welcomes you very much.If you are in search of the famous gucci sneakers,please come to us to have more choices.Top quality with cheap price.
that's really a fantastic post ! added to my favourite blogs list.. I have been reading your blog last couple of weeks and enjoy every bit. Thanks.
I was just doing some web browsing on my Garmin Phone during my break at my work place, and I came across something I thought was interesting . It linked over to your website so I clicked over. I can’t really find the relevance between your site and the one I came from, but your site good none the less.thanks for sharing thoes informations , It is interesting, i like it!
I recently came across your blog and have been reading along. I thought I would leave my first comment. I don't know what to say except that I have enjoyed reading. Nice blog. I will keep visiting this blog very often.
we provide our buyers with an efficient and manageable procurement process covering every phase of the international supply chain and
streamlining trade channels. Also welcome wholesaling, feedback now!
it is so useful to me.
thanks for your share.i will see next time,looking for your next article.
maybe you can see<a href="http://www.poloshirtsb2c.com/lacoste-polo-shirts-womens-lacoste-polo-c-2_10.html">womens lacoste polo</a>it is so useful to me.
very nice post.middle ware are truly becoming and integral part of the infrastructure for every organization
Excellent news, I look forward to more of the HTML5 form stuff and especially its incorporation into JavaScript UI libraries. Except... how will web developers eat if they
can't charge for "Enter search term here" form enhancements ;-)
middle ware truly, make possible to sue application in an optimal way by taking of load from the application server and handling request
Thanks for the post. I enjoying your Rails 2.3 screencasts.
Thanks again.
High quality post you did here, thanks for your great effort to share this post with us
I found your blog on Yahoo and I just wanted to say that I think your writing is simply stunning! Thanks again for providing this content for free.
it is interesting and informative article. This has been very helpful understanding a lot
of things. I’m sure a lot of other people will agree with me.
lots of good advice on your post. and as a return,i will buy a Cheap nfl jerseys to you for my thanking.
There are some very great sources here and thank you for being so kind to post them here. So we can read them and give our opinion on subject.
thanks for your share.i will see next time,looking for your next article. Thanks again for providing this content for free. lots of good advice on your post. and as a return,i will buy a Cheap nfl jerseys to you for my thanking.
These are wonderful! Thank you for finding and sharing
Thanks for sharing your article. I really enjoyed it. I put a link to my site to here so other people can read it. My readers have about the same interets
Discount Wholesale Electronics, Wholesale Cell Phones, Electronic Gadgets and More from the Best Dropship Wholesaler
Thanks for sharing this - it is important to change the headers["Content-Length"] value to reflect the new body length. See their comments for details.
Thanks Ryan, a very interesting railscast, and the link to rack-contrib helps newbies like me understand what all this rack middleware stuff is good for. :)
I feel like I’m often looking for interesting things to read about a variety of subjects, but I manage to include your blog among my reads every day because you have interesting entries that I look forward to. Here’s hoping there’s a lot more great material coming!
A number of low carb versions require the consumption of more fat. Others limit the fat intake or require certain amounts of various fats. Playing a definitive statement of the role of calories it really, there is currently not as the opinions are too much apart.






