<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
  <id>http://writelesscode.com/</id>
  <title>WriteLessCode Blog</title>
  <updated>2013-05-01T17:00:00Z</updated>
  <link rel="alternate" href="http://writelesscode.com/" />
  
  <author>
    <name>nomadcoder</name>
    <uri>http://twitter.com/nomadcoder</uri>
  </author>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/writelesscodeblog" /><feedburner:info uri="writelesscodeblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
    <id>tag:writelesscode.com,2013-05-02:/blog/2013/02/05/final-round-euruko/</id>
    <title type="html">Final round voting for EuRuKo speakers</title>
    <published>2013-05-01T17:00:00Z</published>
    <updated>2013-05-01T17:00:00Z</updated>
    <link rel="alternate" href="http://feedproxy.google.com/~r/writelesscodeblog/~3/t7dushexhFg/" />
    <content type="html">&lt;p&gt;With your support, I was honored to get to the list of EuRuKo speaker selection finalists. I'll admit I got a bit pessimistic about my chances first, as I'm standing on the very last place &lt;a href="http://cfp.euruko2013.org/proposals"&gt;on the list&lt;/a&gt;. However, today I got a very encouraging email from a Taiwanese friend who saw me speaking about Netzke at RubyConf Taiwan last year. He wrote me that himself, as well as a few colleagues of his who also were at the conference, have voted for my proposal in the final round, and are wishing me luck. Motivated by this, I decided that it may be worth trying to push it one more last time, so, I'm asking you again to spend 1 minute of your time to login with your GitHub account &lt;a href="http://cfp.euruko2013.org/proposals"&gt;here&lt;/a&gt;, and drag-and-drop my proposal (search for "Netzke") to the "Your selection" area, along with 9 other proposals. And if you could motivate one or two of your colleagues to do the same - that'd be extra-awesome!&lt;/p&gt;

&lt;p&gt;The voting ends in 3 days. Can't express how much I appreciate your support!&lt;/p&gt;&lt;br /&gt;---&lt;br /&gt; &lt;a href='http://twitter.com/nomadcoder'&gt;Follow me&lt;/a&gt; on Twitter for more updates.&lt;img src="http://feeds.feedburner.com/~r/writelesscodeblog/~4/t7dushexhFg" height="1" width="1"/&gt;</content>
    <summary type="html">I got to the final round of EuRuKo speaker selection, and now would appreciate you taking the last little action to help me get selected</summary>
  <feedburner:origLink>http://writelesscode.com/blog/2013/02/05/final-round-euruko/</feedburner:origLink></entry>
  <entry>
    <id>tag:writelesscode.com,2013-04-05:/blog/2013/04/05/call-for-support-netzke-at-euruko-this-year/</id>
    <title type="html">Call for support: Netzke at EuRuKo this year?</title>
    <published>2013-04-04T17:00:00Z</published>
    <updated>2013-04-04T17:00:00Z</updated>
    <link rel="alternate" href="http://feedproxy.google.com/~r/writelesscodeblog/~3/w7qybfyTX1E/" />
    <content type="html">&lt;p&gt;For the past weeks, I started receiving more high-quality pull requests for Netzke, so, I realised once more how important it is to grow a skilful community around the project - everyone of us who uses Netzke to build products would eventually benefit from it.&lt;/p&gt;

&lt;p&gt;Speaking at conferences is one of the things I'm doing to tell people about Netzke, and I'm trying constantly to raise the bar of the conference level. In case you don't know yet, in May,  encouraged by Matz (the author of Ruby) and his team, I'm speaking at RubyKaigi in Tokyo, which I consider a big step forward.&lt;/p&gt;

&lt;p&gt;This time I thought, with a little help from you, I might get a chance to speak at &lt;a href="http://euruko2013.org"&gt;EuRuKo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I want to kindly ask you to spend 1 minute to sign in with your GitHub/Twitter/Google account (one click) and vote up for my &lt;a href="http://cfp.euruko2013.org/proposals/29"&gt;proposal&lt;/a&gt;. And if you feel you have 5 minutes more, than a comment bellow my proposal would be even more helpful: you might want to ask me to change something in the proposal, or rephrase something, or you can just express your interest in the topic (but, please, back it up with some reasonable argument, as "It's cool, I would like to see it!" would not be enough).&lt;/p&gt;

&lt;p&gt;I will also appreciate a personal feedback (below in the comments or at nmcoder @ gmail dot com), even be it simply editorial (I have the right to update the proposal at any time).&lt;/p&gt;

&lt;p&gt;Thanks in advance! Together we could pretty much make it.&lt;/p&gt;&lt;br /&gt;---&lt;br /&gt; &lt;a href='http://twitter.com/nomadcoder'&gt;Follow me&lt;/a&gt; on Twitter for more updates.&lt;img src="http://feeds.feedburner.com/~r/writelesscodeblog/~4/w7qybfyTX1E" height="1" width="1"/&gt;</content>
    <summary type="html">Why I'm submitting a CFP to EuRuKo this year, and why I need your help.</summary>
  <feedburner:origLink>http://writelesscode.com/blog/2013/04/05/call-for-support-netzke-at-euruko-this-year/</feedburner:origLink></entry>
  <entry>
    <id>tag:writelesscode.com,2013-04-04:/blog/2013/04/04/changing-behavior-of-all-netzke-components-on-the-client-side/</id>
    <title type="html">Changing behavior of all Netzke components on the client side</title>
    <published>2013-04-03T17:00:00Z</published>
    <updated>2013-04-03T17:00:00Z</updated>
    <link rel="alternate" href="http://feedproxy.google.com/~r/writelesscodeblog/~3/cdm0j7rUmSM/" />
    <content type="html">&lt;p&gt;For those folks who didn't understand that my previous post was an &lt;a href="/blog/2013/01/04/end-of-netzke-development/"&gt;April Fool joke&lt;/a&gt; - I don't blame you, I may have just failed to make it sound ridiculous enough. Anyways, the reality is kind of opposite to what's advertised there: Netzke development is going as strong as ever, with some great support from the &lt;a href="http://groups.google.com/group/netzke/"&gt;community&lt;/a&gt; - in the form of skillful pull requests, interesting suggestions, and joint experiments. Thanks everyone who's been helping moving it forward! Besides, I'm going to present Netzke at &lt;a href="http://rubykaigi.org/2013"&gt;RubyKaigi&lt;/a&gt; in Tokyo, as well as a few other exciting things meant to give Netzke some exposure, are pending. You may want to follow Netzke on &lt;a href="https://twitter.com/netzke"&gt;Twitter&lt;/a&gt; if you want to stay up-to-date with that news that may not find its way to a blog post.&lt;/p&gt;

&lt;p&gt;In meanwhile, in this little tutorial I want to share a tip on how to extend each and every Netzke client-side class, and I'll do that on an example of implementing a custom feedback functionality. As you may know, each Netzke component, at the client side, has a method called &lt;code&gt;netzkeFeedback&lt;/code&gt;, which by default displays a little box on the top of the screen:&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/2013-04-03-1.png" alt="feedback"&gt;&lt;/p&gt;

&lt;p&gt;You may already know that by overriding this method in your component, you can replace the default implementation with whatever you find appropriate - &lt;em&gt;for that specific component&lt;/em&gt;. But what if you want to change the way feedback is displayed for &lt;em&gt;all&lt;/em&gt; Netzke components at once?&lt;/p&gt;

&lt;p&gt;The way to do that is to override the &lt;code&gt;netzkeFeedback&lt;/code&gt; method in &lt;code&gt;Netzke.classes.Core.Mixin&lt;/code&gt;, which gets mixed-in into each Netzke component. However, this has to be done &lt;em&gt;before&lt;/em&gt; any Netzke component class is defined, and for that we can use &lt;code&gt;Netzke::Core.ext_javascripts&lt;/code&gt; config option, which other Netzke gems (such as netzke-basepack) use to inject custom JavaScript code (which can be a patch for Ext JS or code shared by multiple components).&lt;/p&gt;

&lt;p&gt;A good place to configure &lt;code&gt;Netzke::Core&lt;/code&gt; is in &lt;code&gt;config/initializers&lt;/code&gt; (e.g. in a file named &lt;code&gt;netzke.rb&lt;/code&gt;):&lt;/p&gt;

&lt;p&gt;&lt;notextile&gt;&lt;/notextile&gt;&lt;/p&gt;

&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="constant"&gt;Netzke&lt;/span&gt;::&lt;span class="constant"&gt;Core&lt;/span&gt;.setup &lt;span class="keyword"&gt;do&lt;/span&gt; |config|
  config.ext_javascripts &amp;lt;&amp;lt; &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;#{&lt;/span&gt;&lt;span class="constant"&gt;File&lt;/span&gt;.dirname(&lt;span class="predefined-constant"&gt;__FILE__&lt;/span&gt;)&lt;span class="inline-delimiter"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="content"&gt;/javascripts/netzke_extensions.js&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;This will instruct Netzke to load &lt;code&gt;config/initializers/javascripts/netzke_extensions.js&lt;/code&gt; along with other initial JavaScript code when a Rails view with Netzke components gets loaded. As I said before, in that file we will override &lt;code&gt;netzkeFeedback&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;notextile&gt;&lt;/notextile&gt;&lt;/p&gt;

&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;Ext.define(&lt;span class="predefined-constant"&gt;null&lt;/span&gt;, {
  &lt;span class="key"&gt;override&lt;/span&gt;: &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;Netzke.classes.Core.Mixin&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="function"&gt;netzkeFeedback&lt;/span&gt;: &lt;span class="keyword"&gt;function&lt;/span&gt;(msg, options) {
    alert(msg); &lt;span class="comment"&gt;// anything you come up with&lt;/span&gt;
  }
});&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;That's it. After this every Netzke component will get this custom implementation of the &lt;code&gt;netzkeFeedback&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;In the following tutorial I'll show you how exactly the same technique can be used to change the way Netzke handles session expiration (currently it would simply hint you in the browser console that the &lt;code&gt;onNetzkeSessionExpired&lt;/code&gt; method should be overridden). Stay tuned.&lt;/p&gt;&lt;br /&gt;---&lt;br /&gt; &lt;a href='http://twitter.com/nomadcoder'&gt;Follow me&lt;/a&gt; on Twitter for more updates.&lt;img src="http://feeds.feedburner.com/~r/writelesscodeblog/~4/cdm0j7rUmSM" height="1" width="1"/&gt;</content>
    <summary type="html">Here I'll quickly explain how you can modify the behavior of each and every Netzke component at the client side.</summary>
  <feedburner:origLink>http://writelesscode.com/blog/2013/04/04/changing-behavior-of-all-netzke-components-on-the-client-side/</feedburner:origLink></entry>
  <entry>
    <id>tag:writelesscode.com,2013-04-01:/blog/2013/01/04/end-of-netzke-development/</id>
    <title type="html">End of Netzke development</title>
    <published>2013-03-31T17:00:00Z</published>
    <updated>2013-03-31T17:00:00Z</updated>
    <link rel="alternate" href="http://feedproxy.google.com/~r/writelesscodeblog/~3/GluDm4QrPSU/" />
    <content type="html">&lt;p&gt;It's been a tough decision. The doubts started to creep in my head after a concise but emotional discussion with one of those people that many of us see as personal heroes:&lt;/p&gt;

&lt;p&gt;&lt;img src="https://f.cloud.github.com/assets/33935/100720/e4dab128-6860-11e2-9dbd-b14265819484.PNG" alt="doomed"&gt;&lt;/p&gt;

&lt;p&gt;Slowly, but irreversibly, I started to believe that at the moment I decided to work on Netzke, I took a painfully wrong direction, which was bound to fail. You know, one of those failures that people like to mention when discussing their eventual success. So, in success I believe, but it's time to start from the beginning. My apologies to all the developers that have and have not managed to bring their Netzke-driven projects to production.&lt;/p&gt;&lt;br /&gt;---&lt;br /&gt; &lt;a href='http://twitter.com/nomadcoder'&gt;Follow me&lt;/a&gt; on Twitter for more updates.&lt;img src="http://feeds.feedburner.com/~r/writelesscodeblog/~4/GluDm4QrPSU" height="1" width="1"/&gt;</content>
    <summary type="html">After another critical look at Netzke in the context of the modern web development, I realized it would be unfair to delude myself and other developers on the future of this project.</summary>
  <feedburner:origLink>http://writelesscode.com/blog/2013/01/04/end-of-netzke-development/</feedburner:origLink></entry>
  <entry>
    <id>tag:writelesscode.com,2013-02-25:/blog/2013/02/25/testing-with-coffeescript-and-mocha-js/</id>
    <title type="html">Testing with CoffeeScript and Mocha</title>
    <published>2013-02-24T17:00:00Z</published>
    <updated>2013-02-24T17:00:00Z</updated>
    <link rel="alternate" href="http://feedproxy.google.com/~r/writelesscodeblog/~3/1Ptqg_aa--Q/" />
    <content type="html">&lt;p&gt;Integration testing of Netzke Core requires running a lot of JavaScript, which, before the rewrite, resulted in numerous custom Cucumber steps that served as wrappers around that JavaScript code. The tests used to read &lt;a href="https://github.com/netzke/netzke-core/blob/v0.8.1/test/core_test_app/features/component_loader.feature"&gt;pretty nicely&lt;/a&gt;, but the code overhead was too high, and performance very low, as for each spec a page containing the tested component would get reloaded. So, I decided to have a look at JavaScript testing frameworks, and after trying out &lt;a href="http://pivotal.github.com/jasmine/"&gt;Jasmine&lt;/a&gt; first, decided that &lt;a href="http://visionmedia.github.com/mocha/"&gt;Mocha&lt;/a&gt; would serve me better (thanks @ptico for &lt;a href="https://twitter.com/ptico/status/292310840013619202"&gt;pointing me&lt;/a&gt; in that direction). After enabling CoffeeScript for writing actual specs, and creating a few custom Ext JS-related helpers, I ended up with specs that read almost as good as Cucumber features,  at the same time written in a &lt;em&gt;real&lt;/em&gt; programming language, not Gherkin:&lt;/p&gt;

&lt;p&gt;&lt;notextile&gt;&lt;/notextile&gt;&lt;/p&gt;

&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;describe "Actions component", -&amp;gt;
  it "should handle clicking a button", -&amp;gt;
    click button "Simple action"
    expectToSee header "Simple action triggered"

  it "should show certain buttons disabled", -&amp;gt;
    expectDisabled button "Disabled action"

  it "should not show buttons for excluded actions", -&amp;gt;
    expectToNotSee button "Excluded action"&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;And for asynchronous scenarios:&lt;/p&gt;

&lt;p&gt;&lt;notextile&gt;&lt;/notextile&gt;&lt;/p&gt;

&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;describe "Plugins component", -&amp;gt;
  it "should be able to call its server part as defined in PluginWithEndpoints", (done) -&amp;gt;
    click tool 'gear'
    wait -&amp;gt;
      expectToSee header "Response from server side of PluginWithEndpoints"
      done()&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;You can find the rest of the Mocha features in &lt;a href="https://github.com/netzke/netzke-core/tree/master/spec/mocha"&gt;spec/mocha&lt;/a&gt;. Every file from that folder, corresponding to an equally named testing component, is being automatically picked up by the setup and turned into a separate RSpec spec. This way there's generally one Mocha feature for each component being tested. The specs inside that feature are being run all at once, without the need to reload the page. As a result, it's much faster now (also due to the fact that the assertions are now being executed directly in the browser).&lt;/p&gt;

&lt;p&gt;Individual features can be run manually in any browser (e.g. in order to analyze the failures) by appending "?spec={feature}" to the URL of a tested component, for example: &lt;code&gt;http://core-test-app.dev/components/Endpoints?spec=endpoints&lt;/code&gt;. This will run &lt;code&gt;spec/mocha/endpoints.js.coffee&lt;/code&gt; spec on the &lt;code&gt;test/core_test_app/components/endpoints.rb&lt;/code&gt; component:&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/2013-02-25.mocha-spec.png" alt="Mocha spec"&gt;&lt;/p&gt;

&lt;p&gt;I also want to add that most of the testing components have been re-worked and better named in order to give the developer a clear message of what exactly is being tested. Hopefully this will make understanding Netzke code an easier task, too.&lt;/p&gt;&lt;br /&gt;---&lt;br /&gt; &lt;a href='http://twitter.com/nomadcoder'&gt;Follow me&lt;/a&gt; on Twitter for more updates.&lt;img src="http://feeds.feedburner.com/~r/writelesscodeblog/~4/1Ptqg_aa--Q" height="1" width="1"/&gt;</content>
    <summary type="html">Specs for Netzke Core have been rewritten to make use of Mocha and CoffeeScript. Here I'll briefly show what I did, so you could consider this setup for testing your own Ext JS + Rails applications.</summary>
  <feedburner:origLink>http://writelesscode.com/blog/2013/02/25/testing-with-coffeescript-and-mocha-js/</feedburner:origLink></entry>
  <entry>
    <id>tag:writelesscode.com,2012-12-16:/blog/2012/12/17/nesting-netzke-components/</id>
    <title type="html">Nesting Netzke components</title>
    <published>2012-12-15T17:00:00Z</published>
    <updated>2012-12-15T17:00:00Z</updated>
    <link rel="alternate" href="http://feedproxy.google.com/~r/writelesscodeblog/~3/wb7nlloLSP8/" />
    <content type="html">&lt;p&gt;As I mentioned in the end of the &lt;a href="/blog/2012/10/20/extjs-rails-crud-application-in-7-minutes/"&gt;previous tutorial&lt;/a&gt;, Netzke lets you do much more than just quickly create a grid that seamlessly works with an ActiveRecord model without using any code generators. In fact, Netzke is &lt;a href="http://netzke-rubyconf-taiwan-2012.herokuapp.com"&gt;best suited&lt;/a&gt; for making complex one-page web applications that make use of hundreds of data models and implement sophisticated workflows. One of the many techniques that Netzke as a modular GUI framework provides to you, is component nesting. Here I'll show you how easy it is to nest 3 differently configured instances of the Tasks component created before in a tab panel.&lt;/p&gt;

&lt;h2&gt;Creating tab panel&lt;/h2&gt;

&lt;p&gt;Assuming you already have the &lt;a href="/blog/2012/10/20/extjs-rails-crud-application-in-7-minutes/"&gt;first part&lt;/a&gt; of the tutorial up-and-running, let's start by creating a new component called &lt;code&gt;TaskTabPanel&lt;/code&gt;, and indicate that its &lt;a href="http://rdoc.info/github/netzke/netzke-core#Client_class"&gt;client class&lt;/a&gt; should inherit from &lt;a href="http://docs.sencha.com/ext-js/4-1/#!/api/Ext.tab.Panel"&gt;Ext.tab.Panel&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;notextile&gt;&lt;/notextile&gt;&lt;/p&gt;

&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="class"&gt;TaskTabPanel&lt;/span&gt; &amp;lt; &lt;span class="constant"&gt;Netzke&lt;/span&gt;::&lt;span class="constant"&gt;Base&lt;/span&gt;
  js_configure &lt;span class="keyword"&gt;do&lt;/span&gt; |c|
    c.extend = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;Ext.tab.Panel&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Update &lt;code&gt;views/welcome/index.html.erb&lt;/code&gt; to show our newly created component:&lt;/p&gt;

&lt;p&gt;&lt;notextile&gt;&lt;/notextile&gt;&lt;/p&gt;

&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="tag"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Tasks&lt;span class="tag"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;&amp;lt;%=&lt;/span&gt; netzke &lt;span class="symbol"&gt;:task_tab_panel&lt;/span&gt;, height: &lt;span class="integer"&gt;400&lt;/span&gt; &lt;span class="inline-delimiter"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;If we reload our application now, it won't be much, as our tab panel has no tabs yet. We want to see 3 tabs containing our previously created Tasks component, each showing a different subset of tasks.&lt;/p&gt;

&lt;h2&gt;Nesting Tasks component&lt;/h2&gt;

&lt;p&gt;We need 2 simple steps to nest a few instances of an existing Netzke component in our tab panel. First, let's declare them as child components inside &lt;code&gt;TaskTabPanel&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;notextile&gt;&lt;/notextile&gt;&lt;/p&gt;

&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="class"&gt;TaskTabPanel&lt;/span&gt; &amp;lt; &lt;span class="constant"&gt;Netzke&lt;/span&gt;::&lt;span class="constant"&gt;Base&lt;/span&gt;
  js_configure &lt;span class="keyword"&gt;do&lt;/span&gt; |c|
    c.extend = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;Ext.tab.Panel&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  component &lt;span class="symbol"&gt;:incomplete_tasks&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; |c|
    c.klass = &lt;span class="constant"&gt;Tasks&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  component &lt;span class="symbol"&gt;:completed_tasks&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; |c|
    c.klass = &lt;span class="constant"&gt;Tasks&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  component &lt;span class="symbol"&gt;:all_tasks&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; |c|
    c.klass = &lt;span class="constant"&gt;Tasks&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Now, with child components declared, Netzke gives us 2 choices on how to show them to the user. We could nest them statically in the current component, or dynamically load them on the user request using &lt;code&gt;netzkeLoadComponent&lt;/code&gt; client-class method. Let's do the simplest thing now, and add all 3 of them statically as tabs. For this we use Ext JS's usual &lt;code&gt;items&lt;/code&gt; property:&lt;/p&gt;

&lt;p&gt;&lt;notextile&gt;&lt;/notextile&gt;&lt;/p&gt;

&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="class"&gt;TaskTabPanel&lt;/span&gt; &amp;lt; &lt;span class="constant"&gt;Netzke&lt;/span&gt;::&lt;span class="constant"&gt;Base&lt;/span&gt;
  js_configure &lt;span class="keyword"&gt;do&lt;/span&gt; |c|
    c.extend = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;Ext.tab.Panel&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  component &lt;span class="symbol"&gt;:incomplete_tasks&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; |c|
    c.klass = &lt;span class="constant"&gt;Tasks&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  component &lt;span class="symbol"&gt;:completed_tasks&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; |c|
    c.klass = &lt;span class="constant"&gt;Tasks&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  component &lt;span class="symbol"&gt;:all_tasks&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; |c|
    c.klass = &lt;span class="constant"&gt;Tasks&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;configure&lt;/span&gt;(c)
    &lt;span class="keyword"&gt;super&lt;/span&gt;
    c.items = [&lt;span class="symbol"&gt;:incomplete_tasks&lt;/span&gt;, &lt;span class="symbol"&gt;:completed_tasks&lt;/span&gt;, &lt;span class="symbol"&gt;:all_tasks&lt;/span&gt;]
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Note, that we didn't have to provide the detailed configuration for the tabs, and just used Symbols referring the child components - Netzke does the expansion of those behind the scenes.&lt;/p&gt;

&lt;p&gt;Now we have 3 tabs, each with an instance of &lt;code&gt;Tasks&lt;/code&gt; component, but they are all named equally and show the same list of incomplete tasks:&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/2012-12-17-3-tabs.png" alt="3 Tasks components as tabs"&gt;&lt;/p&gt;

&lt;h2&gt;Configuring nested components&lt;/h2&gt;

&lt;p&gt;One way to change this would be by extending our &lt;code&gt;Tasks&lt;/code&gt; component 3 times and configure each of them separately, for example, for completed tasks:&lt;/p&gt;

&lt;p&gt;&lt;notextile&gt;&lt;/notextile&gt;&lt;/p&gt;

&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="class"&gt;CompletedTasks&lt;/span&gt; &amp;lt; &lt;span class="constant"&gt;Tasks&lt;/span&gt;
  &lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;configure&lt;/span&gt;(c)
    &lt;span class="keyword"&gt;super&lt;/span&gt;
    c.title = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;Completed&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;
    c.scope = {done: &lt;span class="predefined-constant"&gt;true&lt;/span&gt;}
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Then we could use it without any further configuration in &lt;code&gt;TaskTabPanel&lt;/code&gt; by specifying &lt;code&gt;c.klass = CompletedTasks&lt;/code&gt; inside the &lt;code&gt;component&lt;/code&gt; block. However, in this case it would be an overkill, and we can simply configure the 3 nested grids directly in &lt;code&gt;TaskTabPanel&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;notextile&gt;&lt;/notextile&gt;&lt;/p&gt;

&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;component &lt;span class="symbol"&gt;:incomplete_tasks&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; |c|
  c.klass = &lt;span class="constant"&gt;Tasks&lt;/span&gt;
  c.title = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;Incomplete&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;
  c.scope = {done: [&lt;span class="predefined-constant"&gt;nil&lt;/span&gt;, &lt;span class="predefined-constant"&gt;false&lt;/span&gt;]}
&lt;span class="keyword"&gt;end&lt;/span&gt;

component &lt;span class="symbol"&gt;:completed_tasks&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; |c|
  c.klass = &lt;span class="constant"&gt;Tasks&lt;/span&gt;
  c.title = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;Completed&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;
  c.scope = {done: &lt;span class="predefined-constant"&gt;true&lt;/span&gt;}
&lt;span class="keyword"&gt;end&lt;/span&gt;

component &lt;span class="symbol"&gt;:all_tasks&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; |c|
  c.klass = &lt;span class="constant"&gt;Tasks&lt;/span&gt;
  c.title = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;All&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;
  c.scope = &lt;span class="predefined-constant"&gt;nil&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;After reloading the page, we see that the titles indeed have been changed, but our scope configuration didn't take any effect:&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/2012-12-17-fixed-titles.png" alt="Title updated"&gt;&lt;/p&gt;

&lt;p&gt;The problem is in our previously created &lt;code&gt;Tasks&lt;/code&gt; component, namely in the way we specify the scope there:&lt;/p&gt;

&lt;p&gt;&lt;notextile&gt;&lt;/notextile&gt;&lt;/p&gt;

&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="class"&gt;Tasks&lt;/span&gt; &amp;lt; &lt;span class="constant"&gt;Netzke&lt;/span&gt;::&lt;span class="constant"&gt;Basepack&lt;/span&gt;::&lt;span class="constant"&gt;Grid&lt;/span&gt;
  &lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;configure&lt;/span&gt;(c)
    &lt;span class="keyword"&gt;super&lt;/span&gt;
    &lt;span class="comment"&gt;# ...&lt;/span&gt;
    c.scope = {done: [&lt;span class="predefined-constant"&gt;nil&lt;/span&gt;, &lt;span class="predefined-constant"&gt;false&lt;/span&gt;]}
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the scope is set &lt;em&gt;after&lt;/em&gt; calling &lt;code&gt;super&lt;/code&gt;, where the configuration from the &lt;code&gt;component&lt;/code&gt; block is being applied. By moving it &lt;em&gt;before&lt;/em&gt; &lt;code&gt;super&lt;/code&gt; we'll ensure that it will get overridden from &lt;code&gt;TaskTabPanel&lt;/code&gt;, thus making our &lt;code&gt;Tasks&lt;/code&gt; component more configurable:&lt;/p&gt;

&lt;p&gt;&lt;notextile&gt;&lt;/notextile&gt;&lt;/p&gt;

&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="class"&gt;Tasks&lt;/span&gt; &amp;lt; &lt;span class="constant"&gt;Netzke&lt;/span&gt;::&lt;span class="constant"&gt;Basepack&lt;/span&gt;::&lt;span class="constant"&gt;Grid&lt;/span&gt;
  &lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;configure&lt;/span&gt;(c)
    c.scope = {done: [&lt;span class="predefined-constant"&gt;nil&lt;/span&gt;, &lt;span class="predefined-constant"&gt;false&lt;/span&gt;]}

    &lt;span class="keyword"&gt;super&lt;/span&gt;
    &lt;span class="comment"&gt;# ...&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Naturally, we could also remove it completely if we don't need any default scopes in &lt;code&gt;Tasks&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Now we have it fixed:&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/2012-12-17-final.png" alt="Final result"&gt;&lt;/p&gt;

&lt;h2&gt;Discussing the results&lt;/h2&gt;

&lt;p&gt;You have learnt how to build a simple compound component, and how to make a nested component configurable, which is an alternative to extending a component by sub-classing it. Both techniques have their values in different scenarios, so, it's up to the software designer which approach to choose.&lt;/p&gt;

&lt;h2&gt;Bonus: load tabs dynamically with Basepack::TabPanel&lt;/h2&gt;

&lt;p&gt;In our current implementation all the 3 instances of &lt;code&gt;Tasks&lt;/code&gt; are being instantiated and added to the tab panel at the page load. This can be a performance issue when you have many tabs each containing a complex Ext JS component as grid. An alternative approach would be to load the nested components dynamically at the moment the user activates a tab for the first time. A dedicated component in netzke-basepack can do just that. All we need to do is to inherit our TaskTabPanel from &lt;code&gt;Netzke::Basepack::TabPanel&lt;/code&gt;, and remove the &lt;code&gt;js_configure&lt;/code&gt; section:&lt;/p&gt;

&lt;p&gt;&lt;notextile&gt;&lt;/notextile&gt;&lt;/p&gt;

&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="class"&gt;TaskTabPanel&lt;/span&gt; &amp;lt; &lt;span class="constant"&gt;Netzke&lt;/span&gt;::&lt;span class="constant"&gt;Basepack&lt;/span&gt;::&lt;span class="constant"&gt;TabPanel&lt;/span&gt;
  component &lt;span class="symbol"&gt;:incomplete_tasks&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; |c|
    c.klass = &lt;span class="constant"&gt;Tasks&lt;/span&gt;
    c.title = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;Incomplete&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;
    c.scope = {done: [&lt;span class="predefined-constant"&gt;nil&lt;/span&gt;, &lt;span class="predefined-constant"&gt;false&lt;/span&gt;]}
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  component &lt;span class="symbol"&gt;:completed_tasks&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; |c|
    c.klass = &lt;span class="constant"&gt;Tasks&lt;/span&gt;
    c.title = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;Completed&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;
    c.scope = {done: &lt;span class="predefined-constant"&gt;true&lt;/span&gt;}
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  component &lt;span class="symbol"&gt;:all_tasks&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; |c|
    c.klass = &lt;span class="constant"&gt;Tasks&lt;/span&gt;
    c.title = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;All&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;
    c.scope = &lt;span class="predefined-constant"&gt;nil&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;configure&lt;/span&gt;(c)
    &lt;span class="keyword"&gt;super&lt;/span&gt;
    c.items = [&lt;span class="symbol"&gt;:incomplete_tasks&lt;/span&gt;, &lt;span class="symbol"&gt;:completed_tasks&lt;/span&gt;, &lt;span class="symbol"&gt;:all_tasks&lt;/span&gt;]
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/2012-12-17-dynamic-tabs.png" alt="Dynamic tabs loading"&gt;&lt;/p&gt;&lt;br /&gt;---&lt;br /&gt; &lt;a href='http://twitter.com/nomadcoder'&gt;Follow me&lt;/a&gt; on Twitter for more updates.&lt;img src="http://feeds.feedburner.com/~r/writelesscodeblog/~4/wb7nlloLSP8" height="1" width="1"/&gt;</content>
    <summary type="html">On the continuation of the popular tutorial teaching you how to set up a &lt;a href="/blog/2012/10/20/extjs-rails-crud-application-in-7-minutes/"&gt;CRUD web app in 7 minutes&lt;/a&gt;, I'll show you how easy it is to nest existing Netzke components in a tab panel.</summary>
  <feedburner:origLink>http://writelesscode.com/blog/2012/12/17/nesting-netzke-components/</feedburner:origLink></entry>
  <entry>
    <id>tag:writelesscode.com,2012-12-08:/blog/2012/12/08/at-rubyconf-taiwan/</id>
    <title type="html">At RubyConf Taiwan</title>
    <published>2012-12-07T17:00:00Z</published>
    <updated>2012-12-07T17:00:00Z</updated>
    <link rel="alternate" href="http://feedproxy.google.com/~r/writelesscodeblog/~3/Dq0fO5O6lV8/" />
    <content type="html">&lt;p&gt;My talk went smoothly. For the first time I didn't use Keynote, made my presentation with &lt;a href="https://github.com/schacon/showoff/"&gt;showoff&lt;/a&gt; (you might need to use someone's fork though) - and thus, didn't have a usual opportunity to see presenter notes during the talk. Nor did I miss them. For the first time I felt very confident about my talk - also thanks to the feedback I got from &lt;a href="http://twitter.com/hasclass"&gt;@hasclass&lt;/a&gt; just the night before. I &lt;a href="http://netzke-rubyconf-taiwan-2012.herokuapp.com"&gt;published the slides on Heroku&lt;/a&gt; - you may want to page through them, they are pretty self-explanatory. As soon as I have access to the video, I'll post an update.&lt;/p&gt;

&lt;p&gt;After the talk I came up to Matz (the creator of Ruby) and asked for his opinion. He started with his usual "Well, I'm not a web guy", and then continued: "But I like your concept. If I had to built a webapp like that, I would use your framework". A bit later, showing him the exact text, I asked him for a permission to quote him on &lt;a href="http://netzke.org"&gt;netzke.org&lt;/a&gt;, and he said "sure". I don't have to tell how excited I am about this. Other guys from the Ruby team seemed also quite &lt;a href="https://twitter.com/hsbt/status/277226452674568192"&gt;impressed&lt;/a&gt;, and recommended me to submit a proposal to &lt;a href="http://rubykaigi.org/2013"&gt;the rubykaigi&lt;/a&gt; in May, with Matz saying "we need this kind of talks at RubyKaigi". Sure enough, I'll give it a try.&lt;/p&gt;

&lt;p&gt;But for now, back to work on Netzke v0.8 - it's almost there!&lt;/p&gt;&lt;br /&gt;---&lt;br /&gt; &lt;a href='http://twitter.com/nomadcoder'&gt;Follow me&lt;/a&gt; on Twitter for more updates.&lt;img src="http://feeds.feedburner.com/~r/writelesscodeblog/~4/Dq0fO5O6lV8" height="1" width="1"/&gt;</content>
    <summary type="html">I spoke at RubyConf Taiwan this year, and, besides other nice folks, met the Japanese team that works on Ruby.</summary>
  <feedburner:origLink>http://writelesscode.com/blog/2012/12/08/at-rubyconf-taiwan/</feedburner:origLink></entry>
</feed>
