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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head profile="http://gmpg.org/xfn/11">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Tender Lovemaking </title>
<meta name="generator" content="WordPress 2.6" /> <!-- leave this for stats -->
<link rel="stylesheet" href="http://tenderlovemaking.com/wp-content/themes/cherry-berry-pr/style.css" type="text/css" media="screen" />
<link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="http://tenderlovemaking.com/feed/" />
<link rel="alternate" type="text/xml" title="RSS .92" href="http://tenderlovemaking.com/feed/rss/" />
<link rel="alternate" type="application/atom+xml" title="Atom 0.3" href="http://tenderlovemaking.com/feed/atom/" />
<link rel="pingback" href="http://tenderlovemaking.com/xmlrpc.php" />
<link rel='archives' title='July 2008' href='http://tenderlovemaking.com/2008/07/' />
<link rel='archives' title='June 2008' href='http://tenderlovemaking.com/2008/06/' />
<link rel='archives' title='May 2008' href='http://tenderlovemaking.com/2008/05/' />
<link rel='archives' title='April 2008' href='http://tenderlovemaking.com/2008/04/' />
<link rel='archives' title='March 2008' href='http://tenderlovemaking.com/2008/03/' />
<link rel='archives' title='February 2008' href='http://tenderlovemaking.com/2008/02/' />
<link rel='archives' title='January 2008' href='http://tenderlovemaking.com/2008/01/' />
<link rel='archives' title='December 2007' href='http://tenderlovemaking.com/2007/12/' />
<link rel='archives' title='November 2007' href='http://tenderlovemaking.com/2007/11/' />
<link rel='archives' title='October 2007' href='http://tenderlovemaking.com/2007/10/' />
<link rel='archives' title='September 2007' href='http://tenderlovemaking.com/2007/09/' />
<link rel='archives' title='August 2007' href='http://tenderlovemaking.com/2007/08/' />
<link rel='archives' title='July 2007' href='http://tenderlovemaking.com/2007/07/' />
<link rel='archives' title='June 2007' href='http://tenderlovemaking.com/2007/06/' />
<link rel='archives' title='May 2007' href='http://tenderlovemaking.com/2007/05/' />
<link rel='archives' title='April 2007' href='http://tenderlovemaking.com/2007/04/' />
<link rel='archives' title='March 2007' href='http://tenderlovemaking.com/2007/03/' />
<link rel='archives' title='February 2007' href='http://tenderlovemaking.com/2007/02/' />
<link rel='archives' title='January 2007' href='http://tenderlovemaking.com/2007/01/' />
<link rel='archives' title='December 2006' href='http://tenderlovemaking.com/2006/12/' />
<link rel='archives' title='November 2006' href='http://tenderlovemaking.com/2006/11/' />
<link rel='archives' title='October 2006' href='http://tenderlovemaking.com/2006/10/' />
<link rel='archives' title='September 2006' href='http://tenderlovemaking.com/2006/09/' />
<link rel='archives' title='August 2006' href='http://tenderlovemaking.com/2006/08/' />
<link rel='archives' title='July 2006' href='http://tenderlovemaking.com/2006/07/' />
<link rel='archives' title='June 2006' href='http://tenderlovemaking.com/2006/06/' />
<link rel='archives' title='May 2006' href='http://tenderlovemaking.com/2006/05/' />
<link rel="stylesheet" href="http://tenderlovemaking.com/wp-content/plugins/codesnippet/codesnippet.css" type="text/css" />
<style type="text/css">
.codesnip-container {border:1px solid #ccc; background:#eee; padding: 5px;margin:10px;}
</style>
<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://tenderlovemaking.com/xmlrpc.php?rsd" />
<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://tenderlovemaking.com/wp-includes/wlwmanifest.xml" />
<meta name="generator" content="WordPress 2.6" />
<link rel="stylesheet" type="text/css" href="http://tenderlovemaking.com/wp-content/plugins/spell_checker/spell_checker.css" />
<script src="http://tenderlovemaking.com/wp-content/plugins/spell_checker/spell_checker.js" type="text/javascript"></script>
<script src="http://tenderlovemaking.com/wp-content/plugins/spell_checker/cpaint.inc.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="http://tenderlovemaking.com/wp-content/plugins/spell_checker/spellchecker.css" />
<script type="text/javascript" src="http://tenderlovemaking.com/wp-content/plugins/spell_checker/spellchecker.js"></script>
</head>
<body>
<div id="wrap">
<div id="header">
<h1><a href="http://tenderlovemaking.com">Tender Lovemaking</a></h1>
<small>The act of making love, tenderly.</small>
</div>
<!-- unComment only when you want a navigation bar like my site
how to use?
<a href="link">Linkname</a> • <a href="link2">Linkname2</a> •
just remember link<space>•<space>link
try not to exceeed 1 line, it may messed up.
simple rite? =D
<div id="navigation">
<a href="#">Link 1</a> •
<a href="#">Link 2</a> •
<a href="#">Link 3</a> •
<a href="#">Link 4</a> •
<a href="#">And so on...</a>
</div>
-->
<!-- end of header --><div id="body">
<div class="post" id="post-146">
<h2 class="postitle"><a href="http://tenderlovemaking.com/2008/07/08/back-home/" rel="bookmark" title="Permanent Link to Back Home!">Back Home!</a></h2>
<p class="postmeta">Tuesday, 8 July 2008 @ 11:34am • <a href="http://tenderlovemaking.com/category/life/" title="View all posts in life" rel="category tag">life</a></p>
<div class="postentry">
<p>I'm finally back home. I went to Japan a few weeks ago for vacation, and I also spoke at <a href="http://jp.rubyist.net/RubyKaigi2008/" onclick="javascript:urchinTracker ('/outbound/article/jp.rubyist.net');">Ruby Kaigi 2008</a>. Ruby Kaigi was so much fun! I've been studying Japanese for a little over a year, but I've never been to Japan. It was exciting and fun to talk to people, and I made a bunch of new Japanese friends. I'd really like to thank Leonard Chin for helping out at the Kaigi. My language skills aren't good enough, and he was kind enough to fill in the gaps. Thank you!</p>
<p>While I was in Japan, I noticed <a href="http://en.wikipedia.org/wiki/QR_Code" onclick="javascript:urchinTracker ('/outbound/article/en.wikipedia.org');">QR Codes</a> everywhere. QR Codes are basically really awesome bar codes. They can hold much more information in a smaller amount of space. They can be easily decoded from images taken with digital cameras. They have these codes everywhere in Japan, and the idea is that people can take a photo with the camera on their cell phone, then the phone decodes the QR Code. I believe most of the QR codes contain information about the company, or possibly a URL to the company's website.</p>
<p>The company that created the format says that the format is open, but unfortunately I have to pay for the spec. I can download the spec in Japanese for free, but my Japanese isn't that good! So unfortunately I'm stuck with either the <a href="http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=43655" onclick="javascript:urchinTracker ('/outbound/article/www.iso.org');">ISO spec</a> (which is over $200) or the <a href="https://www.aimglobal.org/estore/ProductDetails.aspx?ProductID=31" onclick="javascript:urchinTracker ('/outbound/article/www.aimglobal.org');">AIM spec</a> ($85). I don't understand why they are so expensive..... I think I'll buy the AIM one, and hope that it is the same as the ISO one.</p>
</div>
<p class="postfeedback">
Written by <a href="http://tenderlovemaking.com/author/admin/" title="Posts by Aaron Patterson">Aaron Patterson</a> •
<a href="http://tenderlovemaking.com/2008/07/08/back-home/" rel="bookmark" title="Permanent Link to Back Home!">Permalink</a> •
<a href="http://tenderlovemaking.com/2008/07/08/back-home/#comments">Comments (1)</a> •
<a href="http://tenderlovemaking.com/2008/07/08/back-home/#respond" title="Leave your Comment">Leave your Comment »</a>
</p>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description rdf:about="http://tenderlovemaking.com/2008/07/08/back-home/"
dc:identifier="http://tenderlovemaking.com/2008/07/08/back-home/"
dc:title="Back Home!"
trackback:ping="http://tenderlovemaking.com/2008/07/08/back-home/trackback/" />
</rdf:RDF> -->
</div>
<div class="post" id="post-141">
<h2 class="postitle"><a href="http://tenderlovemaking.com/2008/06/06/meow-meow-meow-meow-meow/" rel="bookmark" title="Permanent Link to Meow meow meow meow meow">Meow meow meow meow meow</a></h2>
<p class="postmeta">Friday, 6 June 2008 @ 12:56pm • <a href="http://tenderlovemaking.com/category/computadora/" title="View all posts in computadora" rel="category tag">computadora</a>, <a href="http://tenderlovemaking.com/category/computadora/meow/" title="View all posts in meow" rel="category tag">meow</a></p>
<div class="postentry">
<p>The other day I wrote an app called <a href="http://github.com/aaronp/dejour/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">dejour</a> to give me growl notifications from <a href="http://github.com/chad/gitjour/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">all</a> <a href="http://github.com/evanphx/gemjour/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">the</a> <a href="http://github.com/jbarnette/pastejour/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">*jour</a> gems out there. I used Eric Hodel's awesome <a href="http://segment7.net/projects/ruby/growl/" onclick="javascript:urchinTracker ('/outbound/article/segment7.net');">ruby-growl</a> library. Unfortunately it does all communications over the interweb, so you have to tweak some knobs in Growl to get it to work. I stumbled across a ruby/cocoa example using Growl, fixed it up, and released a gem called "Meow".</p>
<p>Meow lets you post notifications to your local machine without adjusting Growl. If you're on OS X 10.5, just do:</p>
<div class="codesnip-container" >$ gem install meow</div>
<p>Then you can do this:</p>
<div class="codesnip-container" >$ ruby -r rubygems -e'require "meow"; Meow.notify("meow", "meow", "meow")'</div>
<p>No growl tweaks required! Here is a code sample that is a little more explanatory:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;"><span class="kw3">require</span> 'rubygems'<br />
<span class="kw3">require</span> 'meow'</p>
<p>meep = Meow.<span class="me1">new</span><span class="br0">(</span>'My Application Name'<span class="br0">)</span><br />
meep.<span class="me1">notify</span><span class="br0">(</span>'Message Title', 'Message Description'<span class="br0">)</span></div>
</div>
<p>Be sure to check out <a href="http://meow.rubyforge.org/" onclick="javascript:urchinTracker ('/outbound/article/meow.rubyforge.org');">the documentation</a>.</p>
</div>
<p class="postfeedback">
Written by <a href="http://tenderlovemaking.com/author/admin/" title="Posts by Aaron Patterson">Aaron Patterson</a> •
<a href="http://tenderlovemaking.com/2008/06/06/meow-meow-meow-meow-meow/" rel="bookmark" title="Permanent Link to Meow meow meow meow meow">Permalink</a> •
<a href="http://tenderlovemaking.com/2008/06/06/meow-meow-meow-meow-meow/#comments">Comments (4)</a> •
<a href="http://tenderlovemaking.com/2008/06/06/meow-meow-meow-meow-meow/#respond" title="Leave your Comment">Leave your Comment »</a>
</p>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description rdf:about="http://tenderlovemaking.com/2008/06/06/meow-meow-meow-meow-meow/"
dc:identifier="http://tenderlovemaking.com/2008/06/06/meow-meow-meow-meow-meow/"
dc:title="Meow meow meow meow meow"
trackback:ping="http://tenderlovemaking.com/2008/06/06/meow-meow-meow-meow-meow/trackback/" />
</rdf:RDF> -->
</div>
<div class="post" id="post-139">
<h2 class="postitle"><a href="http://tenderlovemaking.com/2008/05/06/write-your-rails-view-in-javascript/" rel="bookmark" title="Permanent Link to Write your Rails view in……. JavaScript?">Write your Rails view in……. JavaScript?</a></h2>
<p class="postmeta">Tuesday, 6 May 2008 @ 11:33am • <a href="http://tenderlovemaking.com/category/computadora/johnson/" title="View all posts in johnson" rel="category tag">johnson</a>, <a href="http://tenderlovemaking.com/category/rails/" title="View all posts in rails" rel="category tag">rails</a></p>
<div class="postentry">
<p>In my <a href="/2008/04/23/take-it-to-the-limit-one-more-time/">last post about Johnson</a>, I said that next time I would talk about the JavaScript parse tree that <a href="http://github.com/jbarnette/johnson/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">Johnson</a> provides. Well, I changed my mind. Sorry.</p>
<p>I want to write about a rails plugin that I added to Johnson. <a href="http://www.yehudakatz.com/" onclick="javascript:urchinTracker ('/outbound/article/www.yehudakatz.com');">Brohuda Katz</a> wrote an <a href="http://github.com/jbarnette/johnson/tree/master/js/johnson/template.js" onclick="javascript:urchinTracker ('/outbound/article/github.com');">ERb type parser in JavaScript</a>, and added it to the (yet to be released) Johnson distribution. With that in mind, and looking at the new template handlers in edge rails, I was able to throw together a rails plugin that allows me to use JavaScript in my rails view code.</p>
<p>Lets get to the code. Here is my controller:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;"><span class="kw1">class</span> JohnsonController < ApplicationController<br />
<span class="kw1">def</span> index<br />
@users = User.<span class="me1">find</span><span class="br0">(</span>:all<span class="br0">)</span><br />
<span class="kw1">end</span><br />
<span class="kw1">end</span></div>
</div>
<p>And my EJS view (the file is named index.html.ejs):</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;"><% <span class="kw1">for</span><span class="br0">(</span><span class="kw2">var</span> user in at.users<span class="br0">)</span> <span class="br0">{</span> %><br />
<%= user.first_name<span class="br0">(</span><span class="br0">)</span> %><br /><br />
<% <span class="br0">}</span> %></div>
</div>
<p>The johnson rails plugin puts controller instance variables in to a special javascript variable called "at". The "at" variable is actually a proxy to the controller, lazily fetching instance variables from the controller and importing those objects in to javascript land.</p>
<p>Lets take a look at the plugin, its only a few lines:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;"><span class="kw1">class</span> EJSHandler < ActionView::TemplateHandler<br />
<span class="kw1">class</span> EJSProxy <span class="co1"># :nodoc:</span><br />
<span class="kw1">def</span> initialize<span class="br0">(</span>controller<span class="br0">)</span><br />
@controller = controller<br />
<span class="kw1">end</span></p>
<p> <span class="kw1">def</span> key?<span class="br0">(</span>pooperty<span class="br0">)</span><br />
@controller.<span class="me1">instance_variables</span>.<span class="kw1">include</span>?<span class="br0">(</span><span class="st0">"@#{pooperty}"</span><span class="br0">)</span><br />
<span class="kw1">end</span></p>
<p> <span class="kw1">def</span> <span class="br0">[</span><span class="br0">]</span><span class="br0">(</span>pooperty<span class="br0">)</span><br />
@controller.<span class="me1">instance_variable_get</span><span class="br0">(</span><span class="st0">"@#{pooperty}"</span><span class="br0">)</span><br />
<span class="kw1">end</span></p>
<p> <span class="kw1">def</span> <span class="br0">[</span><span class="br0">]</span>=<span class="br0">(</span>pooperty, value<span class="br0">)</span><br />
@controller.<span class="me1">instance_variable_set</span><span class="br0">(</span><span class="st0">"@#{pooperty}"</span>, value<span class="br0">)</span><br />
<span class="kw1">end</span><br />
<span class="kw1">end</span></p>
<p> <span class="kw1">def</span> initialize<span class="br0">(</span>view<span class="br0">)</span><br />
@view = view<br />
<span class="kw1">end</span></p>
<p> <span class="kw1">def</span> render<span class="br0">(</span>template<span class="br0">)</span><br />
ctx = Johnson::Context.<span class="me1">new</span><br />
ctx.<span class="me1">evaluate</span><span class="br0">(</span>'Johnson.<span class="kw3">require</span><span class="br0">(</span><span class="st0">"johnson/template"</span><span class="br0">)</span>;'<span class="br0">)</span><br />
ctx<span class="br0">[</span>'template'<span class="br0">]</span> = template.<span class="me1">source</span><br />
ctx<span class="br0">[</span>'controller'<span class="br0">]</span> = @view.<span class="me1">controller</span><br />
ctx<span class="br0">[</span>'at'<span class="br0">]</span> = EJSProxy.<span class="me1">new</span><span class="br0">(</span>@view.<span class="me1">controller</span><span class="br0">)</span></p>
<p> ctx.<span class="me1">evaluate</span><span class="br0">(</span>'Johnson.<span class="me1">templatize</span><span class="br0">(</span>template<span class="br0">)</span>.<span class="me1">call</span><span class="br0">(</span>at<span class="br0">)</span>'<span class="br0">)</span><br />
<span class="kw1">end</span><br />
<span class="kw1">end</span></p>
<p>ActionView::Template.<span class="me1">register_template_handler</span><span class="br0">(</span><span class="st0">"ejs"</span>, EJSHandler<span class="br0">)</span></div>
</div>
<p>When the template gets rendered (the render method), I wrap the controller with an EJS proxy, then compile the template into a javascript function, and call that function. The "at" variable is set to the EJSProxy before executing the template, and all property accessing on the "at" variable is passed along to fetching instance variables from the controller.</p>
<p>Server side javascript coding in rails. Weird, eh?</p>
</div>
<p class="postfeedback">
Written by <a href="http://tenderlovemaking.com/author/admin/" title="Posts by Aaron Patterson">Aaron Patterson</a> •
<a href="http://tenderlovemaking.com/2008/05/06/write-your-rails-view-in-javascript/" rel="bookmark" title="Permanent Link to Write your Rails view in……. JavaScript?">Permalink</a> •
<a href="http://tenderlovemaking.com/2008/05/06/write-your-rails-view-in-javascript/#comments">Comments (7)</a> •
<a href="http://tenderlovemaking.com/2008/05/06/write-your-rails-view-in-javascript/#respond" title="Leave your Comment">Leave your Comment »</a>
</p>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description rdf:about="http://tenderlovemaking.com/2008/05/06/write-your-rails-view-in-javascript/"
dc:identifier="http://tenderlovemaking.com/2008/05/06/write-your-rails-view-in-javascript/"
dc:title="Write your Rails view in……. JavaScript?"
trackback:ping="http://tenderlovemaking.com/2008/05/06/write-your-rails-view-in-javascript/trackback/" />
</rdf:RDF> -->
</div>
<div class="post" id="post-138">
<h2 class="postitle"><a href="http://tenderlovemaking.com/2008/04/23/take-it-to-the-limit-one-more-time/" rel="bookmark" title="Permanent Link to Take it to the limit one more time">Take it to the limit one more time</a></h2>
<p class="postmeta">Wednesday, 23 April 2008 @ 11:22am • <a href="http://tenderlovemaking.com/category/computadora/" title="View all posts in computadora" rel="category tag">computadora</a>, <a href="http://tenderlovemaking.com/category/ecma/" title="View all posts in ecma" rel="category tag">ecma</a>, <a href="http://tenderlovemaking.com/category/computadora/johnson/" title="View all posts in johnson" rel="category tag">johnson</a>, <a href="http://tenderlovemaking.com/category/rkelly/" title="View all posts in rkelly" rel="category tag">rkelly</a></p>
<div class="postentry">
<p>Sup bros. I need to post in this thing more often. Yesterday, someone tipped over <a href="http://flickr.com/photos/aaronp/150189237/" onclick="javascript:urchinTracker ('/outbound/article/flickr.com');">my scooter</a> again. I'm getting kind of tired of that.</p>
<p>Anyway, its time for me to write about this. <a href="http://rubyforge.org/projects/rkelly/" onclick="javascript:urchinTracker ('/outbound/article/rubyforge.org');">RKelly</a> is pretty much dead. For the past few months, <a href="http://geeksomnia.com/" onclick="javascript:urchinTracker ('/outbound/article/geeksomnia.com');">John</a> and I have been working on RKelly's replacement called <a href="http://github.com/jbarnette/johnson/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">Johnson</a>. Basically we're now putting a ruby wrapper around <a href="http://www.mozilla.org/js/spidermonkey/" onclick="javascript:urchinTracker ('/outbound/article/www.mozilla.org');">Mozilla's Spidermonkey</a>. The project is coming along quite nicely. Ruby objects can be passed in to javascript land, and javascript objects can be passed back in to ruby land.</p>
<p>For example, we can define an alert function in our javascript context:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;"><span class="kw3">require</span> 'johnson'</p>
<p>ctx = Johnson::Context.<span class="me1">new</span><br />
ctx<span class="br0">[</span>'alert'<span class="br0">]</span> = <span class="kw3">lambda</span> <span class="br0">{</span> |x| <span class="kw3">puts</span> x <span class="br0">}</span><br />
ctx.<span class="me1">evaluate</span><span class="br0">(</span>'alert<span class="br0">(</span><span class="st0">"Hello world!"</span><span class="br0">)</span>;'<span class="br0">)</span></div>
</div>
<p>Johnson::Context#evaluate will also return the last statement evaluated. We can evaluate an expression, and manipulate that expression in ruby land. For example, I'll create an object in javascript, return it to ruby land, then access a property of the javascript object:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;"><span class="kw3">require</span> 'johnson'</p>
<p>ctx = Johnson::Context.<span class="me1">new</span><br />
obj = ctx.<span class="me1">evaluate</span><span class="br0">(</span>'var foo = <span class="br0">{</span> x: <span class="st0">"hello world"</span> <span class="br0">}</span>; foo'<span class="br0">)</span><br />
<span class="kw3">puts</span> obj.<span class="me1">x</span> <span class="co1"># => 'hello world' </span></div>
</div>
<p>We can even do the reverse by stuffing ruby objects in to the context:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;">A = Struct.<span class="me1">new</span><span class="br0">(</span>:foo<span class="br0">)</span></p>
<p>ctx = Johnson::Context.<span class="me1">new</span><br />
ctx<span class="br0">[</span>'alert'<span class="br0">]</span> = <span class="kw3">lambda</span> <span class="br0">{</span> |x| <span class="kw3">puts</span> x <span class="br0">}</span><br />
ctx<span class="br0">[</span>'a'<span class="br0">]</span> = A.<span class="me1">new</span><span class="br0">(</span><span class="st0">"bar"</span><span class="br0">)</span><br />
ctx.<span class="me1">evaluate</span><span class="br0">(</span>'alert<span class="br0">(</span>a.<span class="me1">foo</span><span class="br0">)</span>;'<span class="br0">)</span> <span class="co1"># => 'bar' </span></div>
</div>
<p>But it gets better. We added a top level variable called "Ruby" that lets you access constants and globals from Ruby land. We can rewrite the previous example completely in javascript:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;">ctx = Johnson::Context.<span class="me1">new</span><br />
ctx.<span class="me1">evaluate</span><span class="br0">(</span><span class="st0">"var x = new (new Ruby.Struct(Johnson.symbolize('foo')));"</span><span class="br0">)</span><br />
ctx.<span class="me1">evaluate</span><span class="br0">(</span><span class="st0">"x.foo = 'bar'"</span><span class="br0">)</span><br />
<span class="kw3">puts</span> ctx.<span class="me1">evaluate</span><span class="br0">(</span>'x'<span class="br0">)</span>.<span class="me1">foo</span> <span class="co1"># => 'bar'</span><br />
<span class="kw3">puts</span> ctx.<span class="me1">evaluate</span><span class="br0">(</span>'x'<span class="br0">)</span>.<span class="kw1">class</span> <span class="co1"># => #<Class:0x49714> </span></div>
</div>
<p>Since the 'Ruby' constant delegates to Object, you can access any constant. Including ones you've defined yourself. We could, for example, look up a bunch of User records through rails:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;">ctx = Johnson::Context.<span class="me1">new</span><br />
ctx<span class="br0">[</span>'alert'<span class="br0">]</span> = <span class="kw3">lambda</span> <span class="br0">{</span> |x| <span class="kw3">puts</span> x <span class="br0">}</span><br />
ctx.<span class="me1">evaluate</span><span class="br0">(</span><<-<span class="kw1">END</span><br />
<span class="kw1">for</span><span class="br0">(</span>var user <span class="kw1">in</span> Ruby.<span class="me1">User</span>.<span class="me1">find</span><span class="br0">(</span>Johnson.<span class="me1">symbolize</span><span class="br0">(</span>'all'<span class="br0">)</span><span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span><br />
alert<span class="br0">(</span>user.<span class="me1">first_name</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>;<br />
<span class="br0">}</span><br />
<span class="kw1">END</span><br />
<span class="br0">)</span></div>
</div>
<p>You might be wondering what this Johnson.symbolize business is about. Since Javascript doesn't have a concept of a symbol, we've created a helper to "mark" a string as a symbol and pass it back in to ruby land.</p>
<p>To conclude this update about my Johnson, I'd like to show off an interactive shell for Johnson (thanks to <a href="http://www.yehudakatz.com/" onclick="javascript:urchinTracker ('/outbound/article/www.yehudakatz.com');">Brohuda Katz</a>). Johnson has an interactive shell that lets you try things out in javascript land or ruby land, and let you quickly switch between the two. Typing 'js' will put in you the javascript shell, 'rb' will switch you to the ruby shell. In the ruby shell, you can use the 'cx' variable to get ahold of you javascript context:</p>
<div class="codesnip-container" >$ ruby -I lib bin/johnson<br />
js> var x = { foo: 'bar', hello: function() { return 'world' } };<br />
=> nil<br />
js> rb<br />
rb> cx['x'].foo<br />
=> "bar"<br />
rb> cx['x'].hello()<br />
=> "world"<br />
rb></div>
<p>We aren't quite ready for a release yet, but if you'd like to play around with Johnson, you can pull it down from github <a href="http://github.com/jbarnette/johnson/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">here</a>. Just run 'rake', and you should have it compiled and running!</p>
<p>My next Johnson related post will be about Javascript parse trees and Javascript code generation.</p>
</div>
<p class="postfeedback">
Written by <a href="http://tenderlovemaking.com/author/admin/" title="Posts by Aaron Patterson">Aaron Patterson</a> •
<a href="http://tenderlovemaking.com/2008/04/23/take-it-to-the-limit-one-more-time/" rel="bookmark" title="Permanent Link to Take it to the limit one more time">Permalink</a> •
<a href="http://tenderlovemaking.com/2008/04/23/take-it-to-the-limit-one-more-time/#comments">Comments (11)</a> •
<a href="http://tenderlovemaking.com/2008/04/23/take-it-to-the-limit-one-more-time/#respond" title="Leave your Comment">Leave your Comment »</a>
</p>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description rdf:about="http://tenderlovemaking.com/2008/04/23/take-it-to-the-limit-one-more-time/"
dc:identifier="http://tenderlovemaking.com/2008/04/23/take-it-to-the-limit-one-more-time/"
dc:title="Take it to the limit one more time"
trackback:ping="http://tenderlovemaking.com/2008/04/23/take-it-to-the-limit-one-more-time/trackback/" />
</rdf:RDF> -->
</div>
<div class="post" id="post-137">
<h2 class="postitle"><a href="http://tenderlovemaking.com/2008/04/01/new-ruby-implementation-brobinius/" rel="bookmark" title="Permanent Link to New Ruby Implementation - Brobinius">New Ruby Implementation - Brobinius</a></h2>
<p class="postmeta">Tuesday, 1 April 2008 @ 3:00pm • <a href="http://tenderlovemaking.com/category/computadora/" title="View all posts in computadora" rel="category tag">computadora</a></p>
<div class="postentry">
<p>Brobinius version 1.0.0 has been released!</p>
<ul>
<li><a href="http://brobinius.org/" onclick="javascript:urchinTracker ('/outbound/article/brobinius.org');">http://brobinius.org/</a></li>
<li><a href="http://tenderlovemaking.com/" >http://tenderlovemaking.com/</a></li>
<li><a href="mailto:aaron@tenderlovemaking.com">aaron@tenderlovemaking.com</a></li>
</ul>
<p>I am happy to annouce the first release of my new fork of Ruby called<br />
Brobinius. The goal of Brobinius is to implement new language features<br />
that I have noticed to be completely missing.</p>
<p>For example, Object#tase! The tase method is featured in many other languages<br />
but is sadly missing from Ruby. Brobinius has a fully implemented tase! method.</p>
<div class="codesnip-container" >>> x = Class.new<br />
=> #<Class:0x3632ec><br />
>> x.tase!<br />
RuntimeError: Don't tase me bro<br />
from (irb):2:in `tase!'<br />
from (irb):6<br />
>></div>
<p>Brobinius also has fully serializable kittenuations. You can create and<br />
serialize your kittenuations, then pick up your snuggling where you left off.<br />
For example:</p>
<div class="codesnip-container" >>> lol = Kittenuation.new {<br />
?> look_cute<br />
>> throw :yarn<br />
>> look_cute<br />
>> }<br />
=> #<Kittenuation:0x366244><br />
>> lol.snuggle<br />
>> Marshal.load(Marshal.dump(lol)).snuggle</div>
<p>Since Brobinius's kittenuations are serializable, you can share them over the<br />
network with friends!</p>
<p>Brobinius also features screencasts with automatic YouTube uploads. All you<br />
have to do write your program, then pass the --screencast option to Brobinius.<br />
Brobinius will automatically create a screencast of your program and upload it<br />
to YouTube:</p>
<div class="codesnip-container" >$ brobinius --screencast my_code.rb</div>
<p>You can even add the --geoff flag to create screencasts with Geoffrey<br />
Grosenbach doing the voice over.</p>
<ul>
<li><a href="http://brobinius.org/" onclick="javascript:urchinTracker ('/outbound/article/brobinius.org');">http://brobinius.org/</a></li>
<li><a href="http://tenderlovemaking.com/" >http://tenderlovemaking.com/</a></li>
<li><a href="mailto:aaron@tenderlovemaking.com">aaron@tenderlovemaking.com</a></li>
</ul>
</div>
<p class="postfeedback">
Written by <a href="http://tenderlovemaking.com/author/admin/" title="Posts by Aaron Patterson">Aaron Patterson</a> •
<a href="http://tenderlovemaking.com/2008/04/01/new-ruby-implementation-brobinius/" rel="bookmark" title="Permanent Link to New Ruby Implementation - Brobinius">Permalink</a> •
<a href="http://tenderlovemaking.com/2008/04/01/new-ruby-implementation-brobinius/#comments">Comments (2)</a> •
<a href="http://tenderlovemaking.com/2008/04/01/new-ruby-implementation-brobinius/#respond" title="Leave your Comment">Leave your Comment »</a>
</p>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description rdf:about="http://tenderlovemaking.com/2008/04/01/new-ruby-implementation-brobinius/"
dc:identifier="http://tenderlovemaking.com/2008/04/01/new-ruby-implementation-brobinius/"
dc:title="New Ruby Implementation - Brobinius"
trackback:ping="http://tenderlovemaking.com/2008/04/01/new-ruby-implementation-brobinius/trackback/" />
</rdf:RDF> -->
</div>
<div class="post" id="post-136">
<h2 class="postitle"><a href="http://tenderlovemaking.com/2008/03/20/laser-etch-my-macbook-air/" rel="bookmark" title="Permanent Link to Laser Etch My Macbook Air">Laser Etch My Macbook Air</a></h2>
<p class="postmeta">Thursday, 20 March 2008 @ 3:03pm • <a href="http://tenderlovemaking.com/category/computadora/" title="View all posts in computadora" rel="category tag">computadora</a></p>
<div class="postentry">
<p>Dear Lazyweb,</p>
<p>I would really like to <a href="http://blog.makezine.com/archive/2008/02/macbook_air_yes_it_can_be.html" onclick="javascript:urchinTracker ('/outbound/article/blog.makezine.com');">Laser Etch</a> my Macbook Air with <a href="http://blogs1.marthastewart.com/martha/2008/03/my-new-macbook.html" onclick="javascript:urchinTracker ('/outbound/article/blogs1.marthastewart.com');">Martha Stewart's</a> face. Where can I get that done? How much would it cost?</p>
</div>
<p class="postfeedback">
Written by <a href="http://tenderlovemaking.com/author/admin/" title="Posts by Aaron Patterson">Aaron Patterson</a> •
<a href="http://tenderlovemaking.com/2008/03/20/laser-etch-my-macbook-air/" rel="bookmark" title="Permanent Link to Laser Etch My Macbook Air">Permalink</a> •
<a href="http://tenderlovemaking.com/2008/03/20/laser-etch-my-macbook-air/#comments">Comments (6)</a> •
<a href="http://tenderlovemaking.com/2008/03/20/laser-etch-my-macbook-air/#respond" title="Leave your Comment">Leave your Comment »</a>
</p>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description rdf:about="http://tenderlovemaking.com/2008/03/20/laser-etch-my-macbook-air/"
dc:identifier="http://tenderlovemaking.com/2008/03/20/laser-etch-my-macbook-air/"
dc:title="Laser Etch My Macbook Air"
trackback:ping="http://tenderlovemaking.com/2008/03/20/laser-etch-my-macbook-air/trackback/" />
</rdf:RDF> -->
</div>
<div class="post" id="post-135">
<h2 class="postitle"><a href="http://tenderlovemaking.com/2008/03/15/mechanize-version-075-has-been-released/" rel="bookmark" title="Permanent Link to mechanize version 0.7.5 has been released!">mechanize version 0.7.5 has been released!</a></h2>
<p class="postmeta">Saturday, 15 March 2008 @ 10:19am • <a href="http://tenderlovemaking.com/category/life/" title="View all posts in life" rel="category tag">life</a></p>
<div class="postentry">
<p>The Mechanize library is used for automating interaction with websites.<br />
Mechanize automatically stores and sends cookies, follows redirects,<br />
can follow links, and submit forms. Form fields can be populated and<br />
submitted. Mechanize also keeps track of the sites that you have visited as<br />
a history.</p>
<p>Changes:</p>
<p># Mechanize CHANGELOG</p>
<p>## 0.7.5</p>
<ul>
<li>
<p>Fixed a bug when fetching files and not pages. Thanks Mat Schaffer!</p>
</li>
<li>
<p><a href="http://mechanize.rubyforge.org/" onclick="javascript:urchinTracker ('/outbound/article/mechanize.rubyforge.org');">http://mechanize.rubyforge.org/</a></p>
</li>
</ul>
</div>
<p class="postfeedback">
Written by <a href="http://tenderlovemaking.com/author/admin/" title="Posts by Aaron Patterson">Aaron Patterson</a> •
<a href="http://tenderlovemaking.com/2008/03/15/mechanize-version-075-has-been-released/" rel="bookmark" title="Permanent Link to mechanize version 0.7.5 has been released!">Permalink</a> •
<a href="http://tenderlovemaking.com/2008/03/15/mechanize-version-075-has-been-released/#comments">Comments (0)</a> •
<a href="http://tenderlovemaking.com/2008/03/15/mechanize-version-075-has-been-released/#respond" title="Leave your Comment">Leave your Comment »</a>
</p>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description rdf:about="http://tenderlovemaking.com/2008/03/15/mechanize-version-075-has-been-released/"
dc:identifier="http://tenderlovemaking.com/2008/03/15/mechanize-version-075-has-been-released/"
dc:title="mechanize version 0.7.5 has been released!"
trackback:ping="http://tenderlovemaking.com/2008/03/15/mechanize-version-075-has-been-released/trackback/" />
</rdf:RDF> -->
</div>
<div class="post" id="post-133">
<h2 class="postitle"><a href="http://tenderlovemaking.com/2008/03/13/profiling-database-queries-in-rails/" rel="bookmark" title="Permanent Link to Profiling Database Queries in Rails">Profiling Database Queries in Rails</a></h2>
<p class="postmeta">Thursday, 13 March 2008 @ 2:16pm • <a href="http://tenderlovemaking.com/category/computadora/" title="View all posts in computadora" rel="category tag">computadora</a>, <a href="http://tenderlovemaking.com/category/rails/" title="View all posts in rails" rel="category tag">rails</a></p>
<div class="postentry">
<p>Despite the recent Ruby webserver <a href="http://www.rubyinside.com/ebb-web-framework-http-server-786.html" onclick="javascript:urchinTracker ('/outbound/article/www.rubyinside.com');">speed contests</a>, most of the slowness at <a href="http://adready.com/" onclick="javascript:urchinTracker ('/outbound/article/adready.com');">my job</a> results from slow (or too many) database queries.</p>
<p>To help keep database queries down, I added a stats to every page that shows the number of queries vs. cache hits, the number of rows returned, and the amount of data transferred from the database. In this screenshot I'm using the "live" environment, 3 cache hits, 169 misses, 577 rows returned, and 458.9k data transferred. Clicking the box hides it, and clicking "Super Hide!" hides the box and sets a cookie so that the box doesn't show up again for a while.</p>
<p><a href="http://www.flickr.com/photos/aaronp/2331927606/" title="Debug Window by fakebeard, on Flickr" onclick="javascript:urchinTracker ('/outbound/article/www.flickr.com');"><img src="http://farm3.static.flickr.com/2106/2331927606_46cc9fa937.jpg" width="500" height="187" alt="Debug Window" /></a></p>
<p>To get this working, first I monkey patch the MysqlAdapter to collect database stats:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;">ActiveRecord::ConnectionAdapters::MysqlAdapter.<span class="me1">module_eval</span> <span class="kw1">do</span><br />
@@stats_queries = @@stats_bytes = @@stats_rows = <span class="nu0">0</span></p>
<p> <span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">get_stats</span><br />
<span class="br0">{</span> :queries => @@stats_queries,<br />
:rows => @@stats_rows,<br />
:bytes => @@stats_bytes <span class="br0">}</span><br />
<span class="kw1">end</span><br />
<span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">reset_stats</span><br />
@@stats_queries = @@stats_bytes = @@stats_rows = <span class="nu0">0</span><br />
<span class="kw1">end</span></p>
<p> <span class="kw1">def</span> select_with_stats<span class="br0">(</span>sql, name<span class="br0">)</span><br />
bytes = <span class="nu0">0</span><br />
rows = select_without_stats<span class="br0">(</span>sql, name<span class="br0">)</span><br />
rows.<span class="me1">each</span> <span class="kw1">do</span> |row|<br />
row.<span class="me1">each</span> <span class="kw1">do</span> |key, value|<br />
bytes += key.<span class="me1">length</span><br />
bytes += value.<span class="me1">length</span> <span class="kw1">if</span> value<br />
<span class="kw1">end</span><br />
<span class="kw1">end</span><br />
@@stats_queries += <span class="nu0">1</span><br />
@@stats_rows += rows.<span class="me1">length</span><br />
@@stats_bytes += bytes<br />
rows<br />
<span class="kw1">end</span><br />
alias_method_chain :<span class="kw3">select</span>, :stats<br />
<span class="kw1">end</span></div>
</div>
<p>Next I patched the QueryCache to keep track of hits and misses:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;">ActiveRecord::ConnectionAdapters::QueryCache.<span class="me1">module_eval</span> <span class="kw1">do</span><br />
@@hits = @@misses = <span class="nu0">0</span></p>
<p> <span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">get_stats</span><br />
<span class="br0">{</span> :hits => @@hits,<br />
:misses => @@misses <span class="br0">}</span><br />
<span class="kw1">end</span><br />
<span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">reset_stats</span><br />
@@hits = @@misses = <span class="nu0">0</span><br />
<span class="kw1">end</span></p>
<p> <span class="kw1">def</span> cache_sql_with_stats<span class="br0">(</span>sql, &block<span class="br0">)</span><br />
<span class="kw1">if</span> @query_cache.<span class="me1">has_key</span>?<span class="br0">(</span>sql<span class="br0">)</span><br />
@@hits += <span class="nu0">1</span><br />
<span class="kw1">else</span><br />
@@misses += <span class="nu0">1</span><br />
<span class="kw1">end</span><br />
cache_sql_without_stats<span class="br0">(</span>sql, &block<span class="br0">)</span><br />
<span class="kw1">end</span><br />
alias_method_chain :cache_sql, :stats<br />
<span class="kw1">end</span></div>
</div>
<p>Then modify ActionController to reset stats for each request:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;">ActionController::Base.<span class="me1">module_eval</span> <span class="kw1">do</span><br />
<span class="kw1">def</span> perform_action_with_reset<br />
ActiveRecord::ConnectionAdapters::MysqlAdapter::reset_stats<br />
ActiveRecord::ConnectionAdapters::QueryCache::reset_stats<br />
perform_action_without_reset<br />
<span class="kw1">end</span></p>
<p> alias_method_chain :perform_action, :reset</p>
<p> <span class="kw1">def</span> active_record_runtime<span class="br0">(</span>runtime<span class="br0">)</span><br />
stats = ActiveRecord::ConnectionAdapters::MysqlAdapter::get_stats<br />
<span class="st0">"#{super} #{sprintf("</span>%.1fk<span class="st0">", stats[:bytes].to_f / 1024)} queries: #{stats[:queries]}"</span><br />
<span class="kw1">end</span><br />
<span class="kw1">end</span></div>
</div>
<p>Just drop all that inside the after_initialize in your development.rb and you'll get the nice stats. After that, just create a partial that displays the stats and include the partial at the bottom of your layout. Our partial looks like this:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;"><span class="sc2"><% unless %w<span class="br0">(</span>production test<span class="br0">)</span>.include?<span class="br0">(</span>RAILS_ENV<span class="br0">)</span> -%<span class="kw2">></span></span><br />
<span class="sc2"><a href="http://december.com/html/4/element/h4.html" onclick="javascript:urchinTracker ('/outbound/article/december.com');"><span class="kw2"><h4</span></a> <span class="kw3">id</span>=<span class="st0">"debug"</span> <span class="kw3">onclick</span>=<span class="st0">"$(this).remove()"</span> <span class="kw3">style</span>=<span class="st0">"background:pink;text-align:center;position:absolute;top:16px;left:35%;padding:0.5em;border: 2px solid red;"</span><span class="kw2">></span></span><br />
<span class="sc2"><%= RAILS_ENV %<span class="kw2">></span></span><br />
<span class="sc2"><a href="http://december.com/html/4/element/br.html" onclick="javascript:urchinTracker ('/outbound/article/december.com');"><span class="kw2"><br</span></a> /<span class="kw2">></span></span><br />
<span class="sc2"><% if ActiveRecord::ConnectionAdapters::QueryCache.respond_to?<span class="br0">(</span>:get_stats<span class="br0">)</span> %<span class="kw2">></span></span><br />
<span class="sc2"><% stats = ActiveRecord::ConnectionAdapters::QueryCache.get_stats %<span class="kw2">></span></span><br />
Queries: <span class="sc2"><%= stats<span class="br0">[</span>:hits<span class="br0">]</span> %<span class="kw2">></span></span> / <span class="sc2"><%= stats<span class="br0">[</span>:misses<span class="br0">]</span> %<span class="kw2">></span></span> /<br />
<span class="sc2"><%= number_to_percentage<span class="br0">(</span><span class="br0">(</span>stats<span class="br0">[</span>:hits<span class="br0">]</span>.to_f / <span class="br0">(</span>stats<span class="br0">[</span>:hits<span class="br0">]</span> + stats<span class="br0">[</span>:misses<span class="br0">]</span><span class="br0">)</span><span class="br0">)</span> * <span class="nu0">100</span>, :precision =<span class="kw2">></span></span> 0) %><br />
|<br />
<span class="sc2"><% end %<span class="kw2">></span></span><br />
<span class="sc2"><% if ActiveRecord::ConnectionAdapters::MysqlAdapter.respond_to?<span class="br0">(</span>:get_stats<span class="br0">)</span> %<span class="kw2">></span></span><br />
<span class="sc2"><% stats = ActiveRecord::ConnectionAdapters::MysqlAdapter.get_stats %<span class="kw2">></span></span><br />
Rows: <span class="sc2"><%= stats<span class="br0">[</span>:<span class="kw3">rows</span><span class="br0">]</span> %<span class="kw2">></span></span> |<br />
Transfer: <span class="sc2"><%= sprintf<span class="br0">(</span><span class="st0">"%.1fk"</span>, stats<span class="br0">[</span>:bytes<span class="br0">]</span>.to_f / <span class="nu0">1024</span><span class="br0">)</span> %<span class="kw2">></span></span><br />
<span class="sc2"><% end %<span class="kw2">></span></span><br />
<span class="sc2"><a href="http://december.com/html/4/element/p.html" onclick="javascript:urchinTracker ('/outbound/article/december.com');"><span class="kw2"><p</span></a> <span class="kw3">style</span>=<span class="st0">"margin:0"</span><span class="kw2">></span></span><br />
<span class="sc2"><a href="http://december.com/html/4/element/a.html" onclick="javascript:urchinTracker ('/outbound/article/december.com');"><span class="kw2"><a</span></a> <span class="kw3">style</span>=<span class="st0">"color:magenta"</span> <span class="kw3">href</span>=<span class="st0">"#"</span> <span class="kw3">onclick</span>=<span class="st0">"superHide()"</span><span class="kw2">></span></span>super hide!<span class="sc2"><span class="kw2"></a></span></span><br />
<span class="sc2"><span class="kw2"></p></span></span><br />
<span class="sc2"><span class="kw2"></h4></span></span><br />
<span class="sc2"><a href="http://december.com/html/4/element/script.html" onclick="javascript:urchinTracker ('/outbound/article/december.com');"><span class="kw2"><script</span></a> <span class="kw3">type</span>=<span class="st0">"text/javascript"</span><span class="kw2">></span></span><br />
function superHide() {<br />
document.cookie = 'debug=hidden; path=/; domain=<span class="sc2"><%= request.host %<span class="kw2">></span></span>; max-age=14400';<br />
}<br />
if(document.cookie.indexOf('debug=hidden') != -1) {<br />
$('debug').hide();<br />
}<br />
<span class="sc2"><span class="kw2"></script></span></span><br />
<span class="sc2"><% end -%<span class="kw2">></span></span></div>
</div>
<p>It's a little work, but it helps keep my mind on reducing the queries. With enough work, one of these days the speed of the webserver will matter to me. Thanks to <a href="http://gurge.com/blog/2006/11/09/rails-sql-logging-improvements/" onclick="javascript:urchinTracker ('/outbound/article/gurge.com');">Adam Doppelt</a> for the basis of this monkey patch. Any bugs are mine, not his!</p>
</div>
<p class="postfeedback">
Written by <a href="http://tenderlovemaking.com/author/admin/" title="Posts by Aaron Patterson">Aaron Patterson</a> •
<a href="http://tenderlovemaking.com/2008/03/13/profiling-database-queries-in-rails/" rel="bookmark" title="Permanent Link to Profiling Database Queries in Rails">Permalink</a> •
<a href="http://tenderlovemaking.com/2008/03/13/profiling-database-queries-in-rails/#comments">Comments (2)</a> •
<a href="http://tenderlovemaking.com/2008/03/13/profiling-database-queries-in-rails/#respond" title="Leave your Comment">Leave your Comment »</a>
</p>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description rdf:about="http://tenderlovemaking.com/2008/03/13/profiling-database-queries-in-rails/"
dc:identifier="http://tenderlovemaking.com/2008/03/13/profiling-database-queries-in-rails/"
dc:title="Profiling Database Queries in Rails"
trackback:ping="http://tenderlovemaking.com/2008/03/13/profiling-database-queries-in-rails/trackback/" />
</rdf:RDF> -->
</div>
<div class="post" id="post-132">
<h2 class="postitle"><a href="http://tenderlovemaking.com/2008/03/04/mechanize-version-071-has-been-released/" rel="bookmark" title="Permanent Link to mechanize version 0.7.1 has been released!">mechanize version 0.7.1 has been released!</a></h2>
<p class="postmeta">Tuesday, 4 March 2008 @ 8:42pm • <a href="http://tenderlovemaking.com/category/life/" title="View all posts in life" rel="category tag">life</a></p>
<div class="postentry">
<p>The Mechanize library is used for automating interaction with websites.<br />
Mechanize automatically stores and sends cookies, follows redirects,<br />
can follow links, and submit forms. Form fields can be populated and<br />
submitted. Mechanize also keeps track of the sites that you have visited as<br />
a history.</p>
<p>Changes:</p>
<p># Mechanize CHANGELOG</p>
<p>## 0.7.1</p>
<ul>
<li>Added iPhone to the user agent aliases. [#17572]</li>
<li>Fixed a bug with EOF errors in net/http. [#17570]</li>
<li>
<p>Handling 0 length gzipped responses. [#17471]</p>
</li>
<li>
<p><a href="http://mechanize.rubyforge.org/" onclick="javascript:urchinTracker ('/outbound/article/mechanize.rubyforge.org');">http://mechanize.rubyforge.org/</a></p>
</li>
</ul>
</div>
<p class="postfeedback">
Written by <a href="http://tenderlovemaking.com/author/admin/" title="Posts by Aaron Patterson">Aaron Patterson</a> •
<a href="http://tenderlovemaking.com/2008/03/04/mechanize-version-071-has-been-released/" rel="bookmark" title="Permanent Link to mechanize version 0.7.1 has been released!">Permalink</a> •
<a href="http://tenderlovemaking.com/2008/03/04/mechanize-version-071-has-been-released/#comments">Comments (1)</a> •
<a href="http://tenderlovemaking.com/2008/03/04/mechanize-version-071-has-been-released/#respond" title="Leave your Comment">Leave your Comment »</a>
</p>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description rdf:about="http://tenderlovemaking.com/2008/03/04/mechanize-version-071-has-been-released/"
dc:identifier="http://tenderlovemaking.com/2008/03/04/mechanize-version-071-has-been-released/"
dc:title="mechanize version 0.7.1 has been released!"
trackback:ping="http://tenderlovemaking.com/2008/03/04/mechanize-version-071-has-been-released/trackback/" />
</rdf:RDF> -->
</div>
<div class="post" id="post-131">
<h2 class="postitle"><a href="http://tenderlovemaking.com/2008/02/26/automated-youtube-uploads/" rel="bookmark" title="Permanent Link to Automated Youtube Uploads">Automated Youtube Uploads</a></h2>
<p class="postmeta">Tuesday, 26 February 2008 @ 10:38am • <a href="http://tenderlovemaking.com/category/computadora/" title="View all posts in computadora" rel="category tag">computadora</a>, <a href="http://tenderlovemaking.com/category/mechanize/" title="View all posts in mechanize" rel="category tag">mechanize</a></p>
<div class="postentry">
<p>I thought I would share the part of my <a href="http://twitterbrite.com/" onclick="javascript:urchinTracker ('/outbound/article/twitterbrite.com');">twitterbrite</a> scripts that uploads videos to <a href="http://youtube.com/" onclick="javascript:urchinTracker ('/outbound/article/youtube.com');">Youtube</a>. Its about 30 lines long, and took me an hour or so to write. Most of my time was spent figuring out form fields to fill out rather than writing code though....</p>
<p>I've broken the script down to three parts: logging in, setting the video attributes, and uploading the video file.</p>
<h3>Step 1: Logging In</h3>
<p>The first step is pretty simple. Just instantiate a new mechanize object, fetch youtube.com, set your login credentials, and submit!</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;">agent = WWW::Mechanize.<span class="me1">new</span> <span class="br0">{</span> |a|<br />
a.<span class="me1">user_agent_alias</span> = 'Mac Safari'<br />
<span class="br0">}</span><br />
page = agent.<span class="me1">get</span><span class="br0">(</span>'http://youtube.<span class="me1">com</span>/'<span class="br0">)</span></p>
<p><span class="co1"># Login</span><br />
page.<span class="me1">form</span><span class="br0">(</span>'loginForm'<span class="br0">)</span> <span class="br0">{</span> |f|<br />
f.<span class="me1">username</span> = 'username'<br />
f.<span class="me1">password</span> = 'password'<br />
<span class="br0">}</span>.<span class="me1">submit</span></div>
</div>
<h3>Step 2: Setting video attributes</h3>
<p>This is probably the most difficult step. Now that the agent is logged in, we have to fetch the upload page and fill out the video attributes form. You have to set the title, description, category, and keywords for your video. The you have to tell the agent to click a special button.</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;"><span class="co1"># Set the video attributes</span><br />
page = agent.<span class="me1">get</span><span class="br0">(</span>'http://youtube.<span class="me1">com</span>/my_videos_upload'<span class="br0">)</span><br />
form = page.<span class="me1">form</span><span class="br0">(</span>'theForm'<span class="br0">)</span><br />
form.<span class="me1">field_myvideo_title</span> = 'My video title'<br />
form.<span class="me1">field_myvideo_descr</span> = <span class="st0">"My video description"</span><br />
form.<span class="me1">field_myvideo_categories</span> = <span class="nu0">28</span><br />
form.<span class="me1">field_myvideo_keywords</span> = 'my tag'<br />
page = form.<span class="me1">submit</span><span class="br0">(</span>form.<span class="me1">buttons</span>.<span class="me1">name</span><span class="br0">(</span>'action_upload'<span class="br0">)</span>.<span class="me1">first</span><span class="br0">)</span></div>
</div>
<p>The number "28" is just the value from the category drop down list. You can iterate over the select options using mechanize, but I leave that as an exercise to the reader.</p>
<h3>Step 3: Upload the video file</h3>
<p>My script expects that the video file name will be supplied on the command line, so ARGV[0] should point to the file you want to upload. In this step, you simply set the video file name, then submit the form.</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;"><span class="co1"># Upload the video</span><br />
page = page.<span class="me1">form</span><span class="br0">(</span>'theForm'<span class="br0">)</span> <span class="br0">{</span> |f|<br />
f.<span class="me1">file_uploads</span>.<span class="me1">name</span><span class="br0">(</span>'field_uploadfile'<span class="br0">)</span>.<span class="me1">first</span>.<span class="me1">file_name</span> = ARGV<span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span><br />
<span class="br0">}</span>.<span class="me1">submit</span><br />
page.<span class="me1">body</span> =~ /<textarea<span class="br0">[</span>^><span class="br0">]</span>*><span class="br0">(</span>.<span class="me1">*</span><span class="br0">)</span><\/textarea>/m<br />
<span class="kw3">puts</span> $<span class="nu0">1</span></div>
</div>
<p>The last two lines grab the html needed to display the video and prints it.</p>
<p>There you go. Upload lots of videos now! Yay!</p>
</div>
<p class="postfeedback">
Written by <a href="http://tenderlovemaking.com/author/admin/" title="Posts by Aaron Patterson">Aaron Patterson</a> •
<a href="http://tenderlovemaking.com/2008/02/26/automated-youtube-uploads/" rel="bookmark" title="Permanent Link to Automated Youtube Uploads">Permalink</a> •
<a href="http://tenderlovemaking.com/2008/02/26/automated-youtube-uploads/#comments">Comments (0)</a> •
<a href="http://tenderlovemaking.com/2008/02/26/automated-youtube-uploads/#respond" title="Leave your Comment">Leave your Comment »</a>
</p>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description rdf:about="http://tenderlovemaking.com/2008/02/26/automated-youtube-uploads/"
dc:identifier="http://tenderlovemaking.com/2008/02/26/automated-youtube-uploads/"
dc:title="Automated Youtube Uploads"
trackback:ping="http://tenderlovemaking.com/2008/02/26/automated-youtube-uploads/trackback/" />
</rdf:RDF> -->
</div>
<a href="http://tenderlovemaking.com/page/2/">Next Page »</a>
</div>
<div id="sidebar">
<div style="margin-top: 2em;">
<form method="get" id="searchform" action="/index.php">
<input type="text" value="" name="s" id="search" />
<input type="submit" id="searchsubmit" value="Search" />
</form></div>
<br />
<ul>
<li class="pagenav"><h2>Pages</h2><ul><li class="page_item page-item-2"><a href="http://tenderlovemaking.com/about/" title="About">About</a></li>
</ul></li>
<!-- unComment if you wan to use the author thing :D
<li><h2>The Author</h2>
<ul>
<li>This is all about me :D</li>
</ul>
</li>
-->
<li><h2>Categories</h2>
<ul>
<li class="cat-item cat-item-6"><a href="http://tenderlovemaking.com/category/computadora/betabrite/" title="View all posts filed under betabrite">betabrite</a> (4)
</li>
<li class="cat-item cat-item-2"><a href="http://tenderlovemaking.com/category/computadora/" title="View all posts filed under computadora">computadora</a> (42)
</li>
<li class="cat-item cat-item-15"><a href="http://tenderlovemaking.com/category/csspool/" title="View all posts filed under csspool">csspool</a> (2)
</li>
<li class="cat-item cat-item-5"><a href="http://tenderlovemaking.com/category/daap/" title="View all posts filed under daap">daap</a> (3)
</li>
<li class="cat-item cat-item-10"><a href="http://tenderlovemaking.com/category/ecma/" title="View all posts filed under ecma">ecma</a> (7)
</li>
<li class="cat-item cat-item-14"><a href="http://tenderlovemaking.com/category/icanhasaudio/" title="View all posts filed under icanhasaudio">icanhasaudio</a> (2)
</li>
<li class="cat-item cat-item-33"><a href="http://tenderlovemaking.com/category/computadora/johnson/" title="View all posts filed under johnson">johnson</a> (2)
</li>
<li class="cat-item cat-item-4"><a href="http://tenderlovemaking.com/category/life/" title="View all posts filed under life">life</a> (69)
</li>
<li class="cat-item cat-item-3"><a href="http://tenderlovemaking.com/category/mechanize/" title="View all posts filed under mechanize">mechanize</a> (14)
</li>
<li class="cat-item cat-item-34"><a href="http://tenderlovemaking.com/category/computadora/meow/" title="View all posts filed under meow">meow</a> (1)
</li>
<li class="cat-item cat-item-13"><a href="http://tenderlovemaking.com/category/objectgraph/" title="View all posts filed under objectgraph">objectgraph</a> (1)
</li>
<li class="cat-item cat-item-9"><a href="http://tenderlovemaking.com/category/rails/" title="View all posts filed under rails">rails</a> (4)
</li>
<li class="cat-item cat-item-12"><a href="http://tenderlovemaking.com/category/raop/" title="View all posts filed under raop">raop</a> (2)
</li>
<li class="cat-item cat-item-11"><a href="http://tenderlovemaking.com/category/rkelly/" title="View all posts filed under rkelly">rkelly</a> (6)
</li>
<li class="cat-item cat-item-28"><a href="http://tenderlovemaking.com/category/rubygems/" title="View all posts filed under rubygems">rubygems</a> (1)
</li>
</ul>
</li>
<li><h2>Archive</h2>
<ul>
<li><a href='http://tenderlovemaking.com/2008/07/' title='July 2008'>July 2008</a></li>
<li><a href='http://tenderlovemaking.com/2008/06/' title='June 2008'>June 2008</a></li>
<li><a href='http://tenderlovemaking.com/2008/05/' title='May 2008'>May 2008</a></li>
<li><a href='http://tenderlovemaking.com/2008/04/' title='April 2008'>April 2008</a></li>
<li><a href='http://tenderlovemaking.com/2008/03/' title='March 2008'>March 2008</a></li>
<li><a href='http://tenderlovemaking.com/2008/02/' title='February 2008'>February 2008</a></li>
<li><a href='http://tenderlovemaking.com/2008/01/' title='January 2008'>January 2008</a></li>
<li><a href='http://tenderlovemaking.com/2007/12/' title='December 2007'>December 2007</a></li>
<li><a href='http://tenderlovemaking.com/2007/11/' title='November 2007'>November 2007</a></li>
<li><a href='http://tenderlovemaking.com/2007/10/' title='October 2007'>October 2007</a></li>
<li><a href='http://tenderlovemaking.com/2007/09/' title='September 2007'>September 2007</a></li>
<li><a href='http://tenderlovemaking.com/2007/08/' title='August 2007'>August 2007</a></li>
</ul>
</li>
<li id="linkcat-7" class="linkcat"><h2>My Friends</h2>
<ul>
<li><a href="http://blog.segment7.net/" rel="friend met">Eric Hodel</a></li>
<li><a href="http://blog.fallingsnow.net/" rel="friend met">Evan Phoenix</a></li>
<li><a href="http://grapefruitgallery.com/">gfg</a></li>
<li><a href="http://metametta.blogspot.com/" rel="friend met" title="Gregory Brown’s blog.">Gregory Brown</a></li>
<li><a href="http://obvio171.wordpress.com/" rel="friend">Helder Ribeiro</a></li>
<li><a href="http://highwayinsomnia.com/" rel="friend met" title="BFF">Jackie</a></li>
<li><a href="http://geeksomnia.com/" rel="friend met co-worker">John Barnette</a></li>
<li><a href="http://donkeyonwheels.com/" rel="friend met neighbor">Pam</a></li>
<li><a href="http://ruby.sadi.st/" title="Holler!">Ruby Sadist</a></li>
<li><a href="http://blog.zenspider.com/" rel="friend met neighbor">Ryan Davis</a></li>
<li><a href="http://tersesystems.com/" rel="friend met">Will Sargent</a></li>
</ul>
</li>
<li id="linkcat-8" class="linkcat"><h2>My Ruby Projects</h2>
<ul>
<li><a href="http://rubyforge.org/projects/betabrite/" title="BetaBrite Sign Library">BetaBrite Sign Library</a></li>
<li><a href="http://csspool.rubyforge.org/">csspool</a></li>
<li><a href="http://seattlerb.rubyforge.org/icanhasaudio/" title="icanhasaudio">icanhasaudio</a></li>
<li><a href="http://lamestore.com/">lamestore</a></li>
<li><a href="http://daapclient.rubyforge.org/">Net::DAAP::Client</a></li>
<li><a href="http://raop.rubyforge.org/" title="Stream music to your airport express.">Net::RAOP::Client</a></li>
<li><a href="http://seattlerb.rubyforge.org/ograph/" title="Graph your ruby objects.">Object Graph</a></li>
<li><a href="http://mechanize.rubyforge.org/">WWW::Mechanize</a></li>
</ul>
</li>
<li><h2>Meta</h2>
<ul>
<li><a href="http://tenderlovemaking.com/wp-login.php">Log in</a></li>
<li><a href="http://tenderlovemaking.com/feed/">RSS Feed Entries</a></li>
<li><a href="http://tenderlovemaking.com/comments/feed/">RSS Feed Comments</a></li>
<li><a href="http://tenderlovemaking.com/feed/atom/">Atom Feed</a></li>
<li><a href="http://gmpg.org/xfn/"><abbr title="XHTML Friends Network">XFN</abbr></a></li>
<li><a href="http://wordpress.org/" title="Powered by WordPress, state-of-the-art semantic personal publishing platform.">WordPress</a></li>
</ul>
</li>
</ul>
</div>
<div id="abc.123" class='special.character'>Special character div</div>
<div id="footer">
A design by <a href="http://blog.geminigeek.com/wordpress-theme">GeminiGeek</a> • Powered by <a href="http://wordpress.org">Wordpress</a><!--• <a href="#">CSS</a> • <a href="#">xHTML 1.0</a>-->
</div>
</div><!-- wrap close -->
<!--
Google Analytics Plugin for Wordpress and BBPress
http://boakes.org/analytics
-->
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-1260604-1";
urchinTracker();
</script>
</body>
</html>
|