<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>My Notes - thinksimple.pl</title>
    <link>http://thinksimple.pl/entries</link>
    <pubDate>Sat, 23 Jul 2011 06:28:30 GMT</pubDate>
    <description>Me and my notes.</description>
    <item>
      <title>Naming things</title>
      <link>http://thinksimple.pl/entries/94-Naming-things</link>
      <description>&lt;p&gt;Am I obsessing over naming things? Is it really that much of a difference if I say &lt;code&gt;loc&lt;/code&gt; instead of &lt;code&gt;location&lt;/code&gt;? For a local variable? In a ~10LOC method? Yes, it occupies a part of my brain, and it&amp;#8217;s slightly annoying once you get used to having everything pretty, but is it worth nitpicking and deny someone a few saved keystrokes?&lt;/p&gt;
&lt;p&gt;As I&amp;#8217;m typing this, I have already realised what the answer is. Yes. Yes it is worth it. Because the writer only writes it once, but the reader reads it multiple times. Maybe hundreds of times. And every single time this small part of the reader&amp;#8217;s brain is occupied with decoding the variables, what the cryptic name stands for and what the variable contains. Overtime, it adds to productivity loss. Greater than saving those keystrokes. Long term, it&amp;#8217;s not worth it. Short term&amp;#8230; If you&amp;#8217;re coding for short term only, then you&amp;#8217;re either lucky, or mistaken. Probably the latter.&lt;/p&gt;</description>
      <pubDate>Sat, 23 Jul 2011 06:28:30 GMT</pubDate>
      <guid>http://thinksimple.pl/entries/94-Naming-things</guid>
    </item>
    <item>
      <title>Capybara, Selenium and SSL</title>
      <link>http://thinksimple.pl/entries/93-Capybara-Selenium-and-SSL</link>
      <description>&lt;p&gt;I&amp;#8217;ve been looking for a way to get Selenium set up with Capybara. We have a fairly standard dev config, nginx with passenger running the site, Rspec for unit tests, Capybara for integration tests. One bit that was missing was Javascript tests, so I decided to give it a go with Selenium.&lt;/p&gt;
&lt;p&gt;First of all, Selenium did not like me trying to log in with &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt;. To be honest, it wasn&amp;#8217;t really Selenium as much as Webrick which Capybara starts for Selenium. I kept getting &lt;code&gt;ssl_error_rx_record_too_long&lt;/code&gt;. Solution: let nginx deal with the &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; bit of the communication and send through a simple &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; request to Webrick. Bonus points for setting a header which tells Rails that initially it was an &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; request.&lt;/p&gt;
&lt;p&gt;Next up: database issues. Our tests rely on two things: seed data and transactions. The idea is to get the seed data in the db and then run each test within a transaction so that it&amp;#8217;s quicker to reset. Unfortunately Selenium opens a new database connection, and a new transaction to go with it. Solution: &lt;a href=&quot;https://github.com/bmabey/database_cleaner&quot;&gt;database_cleaner&lt;/a&gt;. Strategy &amp;#8211; truncation, as mentioned on numerous websites&amp;#8230; Oh wait, leave the seed data in! You can pass an &lt;code&gt;:except&lt;/code&gt; option to DatabaseCleaner, except that you then can&amp;#8217;t create models which are seeded as they will just stay in the db. Oh well, Truncation and loading seeds before each test it is. After painful waiting for the test suite to finish (28min instead of the usual 10) it was clear that this is not a sensible solution. So I tried switching strategies in between tests, from &lt;code&gt;transaction&lt;/code&gt; for most tests to &lt;code&gt;truncation&lt;/code&gt; for Selenium tests. Worked like a charm.&lt;/p&gt;
&lt;p&gt;Lastly, a minor thing compared to everything else &amp;#8211; did you know that fixtures are cached? Well they are. So if you try loading them again while running the tests it won&amp;#8217;t work. Need a special fix for that.&lt;/p&gt;
&lt;p&gt;All in all, it was a painful experience. Below is the code I used, some of it will be deprecated once new Capybara is out, and I might have omitted something accidentally. If so, let me know in the comments. Other than that, enjoy!&lt;/p&gt;
&lt;p&gt;&lt;code&gt;nginx.conf&lt;/code&gt;:&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
http {
&lt;span class=&quot;Comment&quot;&gt;  &lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; your usual server config goes here&lt;/span&gt;

  upstream testing {
    server &lt;span class=&quot;Constant&quot;&gt;127.0&lt;/span&gt;.&lt;span class=&quot;Constant&quot;&gt;0.1&lt;/span&gt;:&lt;span class=&quot;Constant&quot;&gt;9000&lt;/span&gt;; &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; Capybara will start Webrick on this port&lt;/span&gt;
  }

  server {
    listen &lt;span class=&quot;Constant&quot;&gt;80&lt;/span&gt;;
    server_name myapp.&lt;span class=&quot;Entity&quot;&gt;testing&lt;/span&gt;;
    location &lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt; {
      proxy_pass http&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;/&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;testing;
      proxy_set_header &lt;span class=&quot;Variable&quot;&gt;Host&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;$&lt;/span&gt;host&lt;/span&gt;;
    }
  }

  server {
    listen &lt;span class=&quot;Constant&quot;&gt;443&lt;/span&gt;;
    server_name myapp.&lt;span class=&quot;Entity&quot;&gt;testing&lt;/span&gt;;
    location &lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt; {
      proxy_pass http&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;/&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;testing;
      proxy_set_header &lt;span class=&quot;Variable&quot;&gt;Host&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;$&lt;/span&gt;host&lt;/span&gt;; &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; forward the host so that urls use this&lt;/span&gt;
      proxy_set_header &lt;span class=&quot;Variable&quot;&gt;X_FORWARDED_PROTO&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;https&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;; &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; this is how Rails finds out if it's an https request&lt;/span&gt;
    }
    ssl on;
    ssl_certificate &lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;etc&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;ssl&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;certs&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;myssl.&lt;span class=&quot;Entity&quot;&gt;crt&lt;/span&gt;;
    ssl_certificate_key &lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;etc&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;ssl&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;myssl.&lt;span class=&quot;Entity&quot;&gt;key&lt;/span&gt;;
  }
}
&lt;/pre&gt;&lt;p&gt;&lt;code&gt;Gemfile&lt;/code&gt;&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
  gem &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;capybara&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  gem &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;database_cleaner&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;&lt;code&gt;spec_helper.rb&lt;/code&gt;&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
  config.&lt;span class=&quot;Entity&quot;&gt;use_transactional_fixtures&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;false&lt;/span&gt;

  config.&lt;span class=&quot;Entity&quot;&gt;before&lt;/span&gt;(&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;suite&lt;/span&gt;) &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;Support&quot;&gt;DatabaseCleaner&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;strategy&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;transaction&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

  config.&lt;span class=&quot;Entity&quot;&gt;before&lt;/span&gt;(&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;each&lt;/span&gt;) &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;Support&quot;&gt;DatabaseCleaner&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;start&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

  config.&lt;span class=&quot;Entity&quot;&gt;after&lt;/span&gt;(&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;each&lt;/span&gt;) &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;Support&quot;&gt;DatabaseCleaner&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;clean&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;Support&quot;&gt;Capybara&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;server_port&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;9000&lt;/span&gt;
  &lt;span class=&quot;Support&quot;&gt;Capybara&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;app_host&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;http://myapp.testing&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;We also have a special &lt;code&gt;integration_helper.rb&lt;/code&gt; included only in integration tests. The DatabaseCleaner mess is to make sure switching from &lt;code&gt;transaction&lt;/code&gt; to &lt;code&gt;truncation&lt;/code&gt; and vice versa works without any issues.&lt;br /&gt;
&lt;code&gt;integration_helper.rb&lt;/code&gt;&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
  config.&lt;span class=&quot;Entity&quot;&gt;before&lt;/span&gt;(&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;each&lt;/span&gt;) &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;if&lt;/span&gt; example.&lt;span class=&quot;Entity&quot;&gt;metadata&lt;/span&gt;[&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;js&lt;/span&gt;]
      &lt;span class=&quot;Support&quot;&gt;DatabaseCleaner&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;clean&lt;/span&gt;
      &lt;span class=&quot;Support&quot;&gt;DatabaseCleaner&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;strategy&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;truncation&lt;/span&gt;
      &lt;span class=&quot;Support&quot;&gt;Capybara&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;current_driver&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;selenium&lt;/span&gt; &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; this can be removed with new Capybara release&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

  config.&lt;span class=&quot;Entity&quot;&gt;after&lt;/span&gt;(&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;each&lt;/span&gt;) &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;if&lt;/span&gt; example.&lt;span class=&quot;Entity&quot;&gt;metadata&lt;/span&gt;[&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;js&lt;/span&gt;]
      &lt;span class=&quot;Support&quot;&gt;DatabaseCleaner&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;clean&lt;/span&gt;
      load &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;Support&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;Entity&quot;&gt;root&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;}&lt;/span&gt;&lt;/span&gt;/db/seeds.rb&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;Support&quot;&gt;DatabaseCleaner&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;strategy&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;transaction&lt;/span&gt;
      &lt;span class=&quot;Support&quot;&gt;DatabaseCleaner&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;start&lt;/span&gt;

      &lt;span class=&quot;Support&quot;&gt;Capybara&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;use_default_driver&lt;/span&gt; &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; this can be removed with new Capybara release&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;You only need this bit if you&amp;#8217;re using &lt;span class=&quot;caps&quot;&gt;YAML&lt;/span&gt; fixtures/seed data and somewhere in your code you say something like &lt;code&gt;Fixtures.create_fixtures(seed_dir, table)&lt;/code&gt;.&lt;br /&gt;
&lt;code&gt;db/seeds.rb&lt;/code&gt;&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
&lt;span class=&quot;Support&quot;&gt;Fixtures&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;reset_cache&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Rspec integration test&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
  it &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;works with Selenium&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;js&lt;/span&gt; =&amp;gt; &lt;span class=&quot;Constant&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt;
    visit root_path
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;</description>
      <pubDate>Mon, 14 Mar 2011 21:22:40 GMT</pubDate>
      <guid>http://thinksimple.pl/entries/93-Capybara-Selenium-and-SSL</guid>
    </item>
    <item>
      <title>Authlogic gotchas</title>
      <link>http://thinksimple.pl/entries/92-Authlogic-gotchas</link>
      <description>&lt;p&gt;There are two. First one: Authlogic assumes that you want to log your users in with http basic authentication. If you have a staging server protected by basic auth you will get random &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt; queries with &amp;#8220;&lt;code&gt;WHERE email LIKE LOWER(your_http_auth_login)&lt;/code&gt;&amp;#8221;.&lt;/p&gt;
&lt;p&gt;Solution:&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
&lt;span class=&quot;Keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;UserSession&lt;span class=&quot;Superclass&quot;&gt; &lt;span class=&quot;Superclass&quot;&gt;&amp;lt;&lt;/span&gt; Authlogic::Session::Base&lt;/span&gt;&lt;/span&gt;
  allow_http_basic_auth &lt;span class=&quot;Constant&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;  &lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; ...&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Second one: Authlogic provides its own email validation. If you&amp;#8217;re using &lt;a href=&quot;https://github.com/goncalossilva/rails3_acts_as_paranoid&quot;&gt;rails3_acts_as_paranoid&lt;/a&gt; the &lt;code&gt;deleted_at&lt;/code&gt; field will not be taken into account. Resulting in validation errors for emails that exist, but the account has been deleted.&lt;/p&gt;
&lt;p&gt;Solution:&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
&lt;span class=&quot;Keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;User&lt;span class=&quot;Superclass&quot;&gt; &lt;span class=&quot;Superclass&quot;&gt;&amp;lt;&lt;/span&gt; ActiveRecord::Base&lt;/span&gt;&lt;/span&gt;
  acts_as_authentic &lt;span class=&quot;Keyword&quot;&gt;do &lt;/span&gt;|&lt;span class=&quot;Variable&quot;&gt;c&lt;/span&gt;|
    c.&lt;span class=&quot;Entity&quot;&gt;validate_email_field&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

  validates_uniqueness_of &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;email&lt;/span&gt;, &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;scope&lt;/span&gt; =&amp;gt; &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;deleted_at&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Fixed.&lt;/p&gt;</description>
      <pubDate>Tue, 22 Feb 2011 19:28:26 GMT</pubDate>
      <guid>http://thinksimple.pl/entries/92-Authlogic-gotchas</guid>
    </item>
    <item>
      <title>Git Extras</title>
      <link>http://thinksimple.pl/entries/91-Git-Extras</link>
      <description>&lt;p&gt;There&amp;#8217;s a fantastic tool on &lt;a href=&quot;http://github.com&quot;&gt;Github&lt;/a&gt; &amp;#8211; &lt;a href=&quot;http://github.com/visionmedia/git-extras&quot;&gt;Git Extras&lt;/a&gt;. Its &lt;code&gt;readme&lt;/code&gt; tells you everything you need to know, but just to give you a taste, here are my favourites:&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
$ git release &lt;span class=&quot;Constant&quot;&gt;0.1&lt;/span&gt;.&lt;span class=&quot;Constant&quot;&gt;0&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Create a commit and tags it.&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
$ git delete&lt;span class=&quot;Keyword&quot;&gt;-&lt;/span&gt;branch branch_name
&lt;/pre&gt;&lt;p&gt;Delete local &lt;span class=&quot;caps&quot;&gt;AND&lt;/span&gt; remote branch&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
$ git undo [number]
&lt;/pre&gt;&lt;p&gt;Undo one or more commits. Internally does &lt;code&gt;git reset --HARD&lt;/code&gt;&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
$ git commits&lt;span class=&quot;Keyword&quot;&gt;-&lt;/span&gt;since [date]
&lt;/pre&gt;&lt;p&gt;Lists commits since a specified date, or last week&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
$ git summary
&lt;/pre&gt;&lt;p&gt;See who created the most commits in your project&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;</description>
      <pubDate>Wed, 15 Sep 2010 18:42:54 GMT</pubDate>
      <guid>http://thinksimple.pl/entries/91-Git-Extras</guid>
    </item>
    <item>
      <title>Vim commands for developers, Part 2</title>
      <link>http://thinksimple.pl/entries/90-Vim-commands-for-developers-Part-2</link>
      <description>&lt;p&gt;The longer I work with Vim, the more great stuff I discover. Here&amp;#8217;s another chunk.&lt;/p&gt;
&lt;p&gt;Did you know there are so many ways to go to &lt;code&gt;insert&lt;/code&gt; mode?&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;i, a&lt;/code&gt; &amp;#8211; insert before/after current character&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;I, A&lt;/code&gt; &amp;#8211; insert at the beginning/end of the line&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;O, o&lt;/code&gt; &amp;#8211; insert a line before/after current line&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;gi&lt;/code&gt; &amp;#8211; go to Insert mode where you last stopped editing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Behold &amp;#8211; Folding!&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;code style=&quot;Visual;&quot;&gt;zf&lt;/code&gt; &amp;#8211; fold selected block&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;:{range}fo[ld]&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;zo&lt;/code&gt; &amp;#8211; open fold&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;:{range}foldo[pen]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ever changed your &lt;code&gt;.vimrc&lt;/code&gt; and had to close Vim to load it? Well no need for that any more!&lt;/p&gt;
&lt;p&gt;&lt;code&gt;:source $MYVIMRC&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And our plugin of the day is&amp;#8230; &lt;a href=&quot;http://github.com/scrooloose/nerdtree&quot;&gt;NERDTree&lt;/a&gt;! NERDTree is a project file browser, very useful!&lt;/p&gt;
&lt;p&gt;Commands:&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;NERDTree&lt;/span&gt; [start&lt;span class=&quot;Keyword&quot;&gt;-&lt;/span&gt;dir&lt;span class=&quot;Keyword&quot;&gt;|&lt;/span&gt;bookmark]  &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; opens NERDTree&lt;/span&gt;
&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;NERDTreeToggle&lt;/span&gt; [start&lt;span class=&quot;Keyword&quot;&gt;-&lt;/span&gt;dir&lt;span class=&quot;Keyword&quot;&gt;|&lt;/span&gt;bookmark]
&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;NERDTreeClose&lt;/span&gt;
&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;NERDTreeFind&lt;/span&gt;  &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; find current file in tree&lt;/span&gt;
&lt;/pre&gt;&lt;pre class=&quot;lazy&quot;&gt;
o, go &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; open / open and leave cursor in NERDTree&lt;/span&gt;
t, &lt;span class=&quot;Variable&quot;&gt;T&lt;/span&gt;  &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; open in new tab / open in tab and keep focus on current tab&lt;/span&gt;
i, gi &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; split window&lt;/span&gt;
s, gs &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; vsplit window&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Also &amp;#8211; you do know about &lt;a href=&quot;http://www.vim.org/scripts/script.php?script_id=2332&quot;&gt;Pathogen&lt;/a&gt;, right?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you missed out on &lt;a href=&quot;http://thinksimple.pl/entries/89-Useful-Vim-commands-for-developers&quot;&gt;Vim commands for developers, Part 1&lt;/a&gt;, here it is.&lt;/em&gt;&lt;/p&gt;</description>
      <pubDate>Sat, 18 Sep 2010 07:08:33 GMT</pubDate>
      <guid>http://thinksimple.pl/entries/90-Vim-commands-for-developers-Part-2</guid>
    </item>
    <item>
      <title>Useful Vim commands for developers</title>
      <link>http://thinksimple.pl/entries/89-Useful-Vim-commands-for-developers</link>
      <description>&lt;div style=&quot;font-size: 110%; font-weight: bold; padding: 0.5em; border: 1px solid gray&quot;&gt;
&lt;p&gt;&lt;span class=&quot;caps&quot;&gt;UPDATE&lt;/span&gt;: There&amp;#8217;s now &lt;a href=&quot;http://thinksimple.pl/entries/90-Vim-commands-for-developers-Part-2&quot;&gt;Vim commands for developers, Part 2&lt;/a&gt; available!&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I&amp;#8217;m always on the look for new Vim tips and tricks, so here&amp;#8217;s a new lot. Most of them are from &lt;a href=&quot;http://zmievski.org/c/dl.php?file=talks/php-quebec-2009/vim-for-php-programmers.pdf&quot;&gt;this presentation&lt;/a&gt; but these are the ones I want to start using.&lt;/p&gt;
&lt;h4&gt;Marks&lt;/h4&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;m&amp;lt;letter&amp;gt;&lt;/code&gt; &amp;#8211; bookmark named letter&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;`&amp;lt;letter&amp;gt;&lt;/code&gt; &amp;#8211; jumps to that bookmark&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;'&amp;lt;letter&amp;gt;&lt;/code&gt; &amp;#8211; jumps to line with the bookmark&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;:marks&lt;/code&gt; &amp;#8211; show current marks&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Handy example:&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
ma &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;=&amp;gt; set a mark&lt;/span&gt;
c&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;`&lt;/span&gt;a #=&amp;gt; change text from cursor to mark a&lt;/span&gt;
&lt;span class=&quot;String&quot;&gt;d&lt;span class=&quot;String&quot;&gt;`&lt;/span&gt;&lt;/span&gt;a &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;=&amp;gt; delete text from cursor to mark a&lt;/span&gt;
y&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;`&lt;/span&gt;a #=&amp;gt; yank text from cursor to mark a&lt;/span&gt;
&lt;span class=&quot;String&quot;&gt;=&lt;span class=&quot;String&quot;&gt;`&lt;/span&gt;&lt;/span&gt;a &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;=&amp;gt; reformat lines from current to the one with mark a&lt;/span&gt;
&lt;/pre&gt;&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;``&lt;/code&gt; &amp;#8211; moves you between the last two locations&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Text objects&lt;/h4&gt;
&lt;p&gt;They are complicated things which I probably thought I will never need, so here&amp;#8217;s a Vim help link: &lt;code&gt;:help text-objects&lt;/code&gt;. One useful tip:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;ci{&lt;/code&gt; &amp;#8211; change text inside {} block&lt;br /&gt;
Or, obviously, &lt;code&gt;di{&lt;/code&gt;, &lt;code&gt;yi{&lt;/code&gt;, &lt;code&gt;ci(&lt;/code&gt; &amp;#8211; you get the idea.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Undo &amp;#8211; simple version&lt;/h4&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;u&lt;/code&gt; &amp;#8211; undo&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;CTRL + R&lt;/code&gt; &amp;#8211; redo&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Complex version: If you undo something and make a change, a new branch is created, so then you can do this:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;g-, g+&lt;/code&gt; &amp;#8211; go to newer/older text state (through branches)&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;:earlier Ns,m,h&lt;/code&gt; &amp;#8211; go to text state as it was N seconds/minutes/hours ago&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;:later Ns,m,h&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;:undolist &amp;#8211; lists changes&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Tabs&lt;/h4&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;gt, gT&lt;/code&gt; &amp;#8211; move around tabs&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Completion&lt;/h4&gt;
&lt;p&gt;There are many types of completion and you can read about them under &lt;code&gt;:help completion&lt;/code&gt;, but this is probably most useful:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;CTRL + N&lt;/code&gt; &amp;#8211; complete with keywords in the current file&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can also use omnicompletion, triggered by &lt;code&gt;CTRL + X CTRL + O&lt;/code&gt;, but it doesn&amp;#8217;t seem to be working for me.&lt;/p&gt;
&lt;h4&gt;Open file under cursor&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;gf&lt;/code&gt;, that&amp;#8217;s easy. However, you can also do this: &lt;code&gt;CTRL + W, CTRL + F&lt;/code&gt; and bang! split window open. This alone is the best tip in this post.&lt;/p&gt;</description>
      <pubDate>Thu, 17 Jun 2010 14:41:00 GMT</pubDate>
      <guid>http://thinksimple.pl/entries/89-Useful-Vim-commands-for-developers</guid>
    </item>
    <item>
      <title>Ruby static code analysis</title>
      <link>http://thinksimple.pl/entries/88-Ruby-static-code-analysis</link>
      <description>&lt;p&gt;Today I&amp;#8217;d like to show you four tools for Ruby code analysis. I&amp;#8217;ll look at my Rails app written over two years ago, when I was just starting to learn Ruby and Rails &amp;#8211; there is &lt;strong&gt;a lot&lt;/strong&gt; to fix there.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;http://ruby.sadi.st/Flog.html&quot;&gt;Flog&lt;/a&gt;&lt;/h3&gt;&lt;pre class=&quot;lazy&quot;&gt;
sudo gem install flog
&lt;/pre&gt;&lt;p&gt;Shows the most complicated code you have written. The more complex the code, the higher the score, and the harder the code is to test. Here&amp;#8217;s my result:&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
$ flog app&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;controllers&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;*&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;rb&lt;/span&gt;
  &lt;span class=&quot;Constant&quot;&gt;1045.2&lt;/span&gt;: flog total
    &lt;span class=&quot;Constant&quot;&gt;12.6&lt;/span&gt;: flog&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;method average

    &lt;span class=&quot;Constant&quot;&gt;68.5&lt;/span&gt;: &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;search         app/controllers/entries_controller.rb:80&lt;/span&gt;
    &lt;span class=&quot;Constant&quot;&gt;39.6&lt;/span&gt;: &lt;span class=&quot;Variable&quot;&gt;CommentsController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;destroy       app/controllers/comments_controller.rb:91&lt;/span&gt;
    &lt;span class=&quot;Constant&quot;&gt;38.6&lt;/span&gt;: &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;search2        app/controllers/entries_controller.rb:64&lt;/span&gt;
    &lt;span class=&quot;Constant&quot;&gt;37.0&lt;/span&gt;: &lt;span class=&quot;Variable&quot;&gt;CommentsController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;create        app/controllers/comments_controller.rb:49&lt;/span&gt;
    &lt;span class=&quot;Constant&quot;&gt;35.1&lt;/span&gt;: &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;json           app/controllers/entries_controller.rb:176&lt;/span&gt;
    &lt;span class=&quot;Constant&quot;&gt;34.3&lt;/span&gt;: &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;update         app/controllers/entries_controller.rb:47&lt;/span&gt;
    &lt;span class=&quot;Constant&quot;&gt;33.2&lt;/span&gt;: &lt;span class=&quot;Variable&quot;&gt;SessionsController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;create        app/controllers/sessions_controller.rb:8&lt;/span&gt;
    &lt;span class=&quot;Constant&quot;&gt;33.2&lt;/span&gt;: &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;advanced_search app/controllers/entries_controller.rb:115&lt;/span&gt;
    &lt;span class=&quot;Constant&quot;&gt;31.4&lt;/span&gt;: &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;create         app/controllers/entries_controller.rb:13&lt;/span&gt;
    &lt;span class=&quot;Constant&quot;&gt;29.0&lt;/span&gt;: &lt;span class=&quot;Variable&quot;&gt;ProjectsController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;update        app/controllers/projects_controller.rb:60&lt;/span&gt;
    &lt;span class=&quot;Constant&quot;&gt;27.5&lt;/span&gt;: &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;archive        app/controllers/entries_controller.rb:137&lt;/span&gt;
    &lt;span class=&quot;Constant&quot;&gt;27.3&lt;/span&gt;: &lt;span class=&quot;Variable&quot;&gt;TagsController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;update            app/controllers/tags_controller.rb:48&lt;/span&gt;
    &lt;span class=&quot;Constant&quot;&gt;26.0&lt;/span&gt;: &lt;span class=&quot;Variable&quot;&gt;ProjectsController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;create        app/controllers/projects_controller.rb:43&lt;/span&gt;
    &lt;span class=&quot;Constant&quot;&gt;21.9&lt;/span&gt;: &lt;span class=&quot;Variable&quot;&gt;TagsController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;show              app/controllers/tags_controller.rb:21&lt;/span&gt;
    &lt;span class=&quot;Constant&quot;&gt;21.6&lt;/span&gt;: &lt;span class=&quot;Variable&quot;&gt;TagsController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;index             app/controllers/tags_controller.rb:9&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;&lt;code&gt;EntriesController#search&lt;/code&gt; method is 27 lines long and includes looping over all entries and doing a regex comparison on every single one. Definitely a candidate for refactoring.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;http://ruby.sadi.st/Flay.html&quot;&gt;Flay&lt;/a&gt;&lt;/h3&gt;&lt;pre class=&quot;lazy&quot;&gt;
sudo gem install flay
&lt;/pre&gt;&lt;p&gt;Flay looks for structural similarities in the code, ignoring whitespace, variable names and some other changes. A sample result looks like this:&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
$ flay app&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;controllers&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;*&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;rb&lt;/span&gt;
&lt;span class=&quot;Variable&quot;&gt;Total&lt;/span&gt; score (lower is better) &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;907&lt;/span&gt;                    


&lt;span class=&quot;Constant&quot;&gt;1&lt;/span&gt;) &lt;span class=&quot;Variable&quot;&gt;Similar&lt;/span&gt; code found &lt;span class=&quot;Keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;defn&lt;/span&gt; (mass &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;108&lt;/span&gt;)
  app&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;controllers&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;projects_controller.&lt;span class=&quot;Entity&quot;&gt;rb&lt;/span&gt;:&lt;span class=&quot;Constant&quot;&gt;77&lt;/span&gt;
  app&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;controllers&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;tags_controller.&lt;span class=&quot;Entity&quot;&gt;rb&lt;/span&gt;:&lt;span class=&quot;Constant&quot;&gt;66&lt;/span&gt;

&lt;span class=&quot;Constant&quot;&gt;2&lt;/span&gt;) &lt;span class=&quot;Variable&quot;&gt;IDENTICAL&lt;/span&gt; code found &lt;span class=&quot;Keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;iter&lt;/span&gt; (mass&lt;span class=&quot;Keyword&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;96&lt;/span&gt;)
  app&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;controllers&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;entries_controller.&lt;span class=&quot;Entity&quot;&gt;rb&lt;/span&gt;:&lt;span class=&quot;Constant&quot;&gt;16&lt;/span&gt;
  app&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;controllers&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;entries_controller.&lt;span class=&quot;Entity&quot;&gt;rb&lt;/span&gt;:&lt;span class=&quot;Constant&quot;&gt;51&lt;/span&gt;

&lt;span class=&quot;Constant&quot;&gt;3&lt;/span&gt;) &lt;span class=&quot;Variable&quot;&gt;Similar&lt;/span&gt; code found &lt;span class=&quot;Keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;defn&lt;/span&gt; (mass &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;90&lt;/span&gt;)
  app&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;controllers&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;comments_controller.&lt;span class=&quot;Entity&quot;&gt;rb&lt;/span&gt;:&lt;span class=&quot;Constant&quot;&gt;22&lt;/span&gt;
  app&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;controllers&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;projects_controller.&lt;span class=&quot;Entity&quot;&gt;rb&lt;/span&gt;:&lt;span class=&quot;Constant&quot;&gt;16&lt;/span&gt;

&lt;span class=&quot;Constant&quot;&gt;4&lt;/span&gt;) &lt;span class=&quot;Variable&quot;&gt;Similar&lt;/span&gt; code found &lt;span class=&quot;Keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;iasgn&lt;/span&gt; (mass &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;81&lt;/span&gt;)
  app&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;controllers&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;comments_controller.&lt;span class=&quot;Entity&quot;&gt;rb&lt;/span&gt;:&lt;span class=&quot;Constant&quot;&gt;9&lt;/span&gt;
  app&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;controllers&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;tags_controller.&lt;span class=&quot;Entity&quot;&gt;rb&lt;/span&gt;:&lt;span class=&quot;Constant&quot;&gt;10&lt;/span&gt;
  app&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;controllers&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;users_controller.&lt;span class=&quot;Entity&quot;&gt;rb&lt;/span&gt;:&lt;span class=&quot;Constant&quot;&gt;25&lt;/span&gt;

&lt;span class=&quot;Constant&quot;&gt;5&lt;/span&gt;) &lt;span class=&quot;Variable&quot;&gt;Similar&lt;/span&gt; code found &lt;span class=&quot;Keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;if&lt;/span&gt; (mass &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;56&lt;/span&gt;)
  app&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;controllers&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;entries_controller.&lt;span class=&quot;Entity&quot;&gt;rb&lt;/span&gt;:&lt;span class=&quot;Constant&quot;&gt;88&lt;/span&gt;
  app&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;controllers&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;entries_controller.&lt;span class=&quot;Entity&quot;&gt;rb&lt;/span&gt;:&lt;span class=&quot;Constant&quot;&gt;92&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Flay marked a similarity in &lt;code&gt;ProjectsController&lt;/code&gt; and &lt;code&gt;EntriesController&lt;/code&gt;, and the similarity is the automatically generated &lt;code&gt;destroy&lt;/code&gt; method. Not very helpful.&lt;/p&gt;
&lt;p&gt;However, the identical code listed is assigning tags to an entry in &lt;code&gt;create&lt;/code&gt; and &lt;code&gt;update&lt;/code&gt; methods, and it is indeed identical. Well spotted.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;http://ruby.sadi.st/Heckle.html&quot;&gt;Heckle&lt;/a&gt;&lt;/h3&gt;&lt;pre class=&quot;lazy&quot;&gt;
sudo gem install heckle
&lt;/pre&gt;&lt;p&gt;Heckle is a piece of really mean software. It takes your code, takes your tests, and then changes your code to see if the tests really fail. It works with Test::Unit or &lt;a href=&quot;http://rspec.info/documentation/tools/heckle.html&quot;&gt;RSpec&lt;/a&gt; tests.&lt;/p&gt;
&lt;p&gt;Unfortunately, I wasn&amp;#8217;t able to run heckle on my current codebase, for one thing, because it doesn&amp;#8217;t have any sensible tests (I was learning, OK?), and also because I broke my gems and now it doesn&amp;#8217;t recognize &lt;code&gt;ActiveRecord&lt;/code&gt; class.&lt;/p&gt;
&lt;h3&gt;
&lt;p&gt;&lt;a href=&quot;http://wiki.github.com/kevinrutherford/reek/&quot;&gt;Reek&lt;/a&gt;&lt;/p&gt;
&lt;/h3&gt;&lt;pre class=&quot;lazy&quot;&gt;
sudo gem install reek
&lt;/pre&gt;&lt;p&gt;Finally, a tool for detecting &lt;a href=&quot;http://wiki.github.com/kevinrutherford/reek/code-smells&quot;&gt;code smells&lt;/a&gt;. Reek tells you exactly what is wrong with your code, and you better fix it. This is a sample output:&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
$ reek app&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;controllers&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;entries_controller.&lt;span class=&quot;Entity&quot;&gt;rb&lt;/span&gt;
app&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;controllers&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;entries_controller.&lt;span class=&quot;Entity&quot;&gt;rb&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;33&lt;/span&gt; warnings:
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt; has no descriptive comment (&lt;span class=&quot;Variable&quot;&gt;IrresponsibleModule&lt;/span&gt;)
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;advanced_search calls entry[:content] twice (Duplication)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;advanced_search calls entry[:tags] twice (Duplication)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;advanced_search calls entry[:title] twice (Duplication)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;advanced_search has approx 10 statements (LongMethod)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;advanced_search refers to entry more than self (LowCohesion)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;archive calls month.nil? twice (Duplication)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;archive calls params 3 times (Duplication)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;archive has approx 11 statements (LongMethod)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;create calls params 4 times (Duplication)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;create calls params[:entry] 4 times (Duplication)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;create has approx 9 statements (LongMethod)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;create has the variable name 't' (UncommunicativeName)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;json calls params 6 times (Duplication)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;json calls params[:count] twice (Duplication)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;json calls params[:tag] twice (Duplication)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;search calls params 5 times (Duplication)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;search calls params[:search] 5 times (Duplication)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;search calls params[:search].downcase 3 times (Duplication)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;search contains iterators nested 2 deep (NestedIterators)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;search has approx 13 statements (LongMethod)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;search2 calls Entry.published 3 times (Duplication)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;search2 calls params 8 times (Duplication)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;search2 calls params[:search] 4 times (Duplication)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;search2 calls params[:tags] twice (Duplication)&lt;/span&gt;
  &lt;span class=&quot;Variable&quot;&gt;EntriesController&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;search2 calls params[:title] twice (Duplication)&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;I get it, I get it, tons of duplication and horribly long methods. Let me do some refactoring now&amp;#8230;&lt;/p&gt;
&lt;p&gt;(Thanks to &lt;a href=&quot;http://github.com/tomash&quot;&gt;Tomash&lt;/a&gt; for his &lt;a href=&quot;http://github.com/tomash/showoff-wrug-rubystatic&quot;&gt;presentation&lt;/a&gt;)&lt;/p&gt;</description>
      <pubDate>Sat, 08 May 2010 09:04:00 GMT</pubDate>
      <guid>http://thinksimple.pl/entries/88-Ruby-static-code-analysis</guid>
    </item>
    <item>
      <title>Multiline step arguments with Cucumber</title>
      <link>http://thinksimple.pl/entries/85-Multiline-step-arguments-with-Cucumber</link>
      <description>&lt;p&gt;I&amp;#8217;ve been doing lots of Cucumber testing lately and I must say, it&amp;#8217;s a great tool. I have stumbled upon one problem though, which are multiline step arguments. The &lt;a href=&quot;http://wiki.github.com/aslakhellesoy/cucumber/multiline-step-arguments&quot;&gt;Cucumber wiki&lt;/a&gt; covers most cases, but what happens when the &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; list or table you want to check is not a proper table, but just some &lt;code&gt;divs&lt;/code&gt;, mixed with &lt;code&gt;tables&lt;/code&gt; and/or &lt;code&gt;uls&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;There is a pretty easy way to do this. Cucumber &lt;a href=&quot;http://github.com/aslakhellesoy/cucumber/blob/master/History.txt&quot;&gt;History.txt&lt;/a&gt; file says that &lt;code&gt;table_at&lt;/code&gt; method is deprecated, and we should use &lt;code&gt;element_at&lt;/code&gt; instead. Also, &lt;code&gt;element_at&lt;/code&gt; takes a &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; selector as an argument. So we can just choose any container element from the &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;, pass it to Nokogiri, and get an array of text.&lt;/p&gt;
&lt;p&gt;Example: if we had this &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; code&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;search_results&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &amp;lt;% &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;people&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;do &lt;/span&gt;|&lt;span class=&quot;Variable&quot;&gt;person&lt;/span&gt;| %&amp;gt;
    &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;MetaTag&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;result&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;MetaTag&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;image&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;MetaTag&quot;&gt;src&lt;/span&gt;=&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;/img/default.png&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; /&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;MetaTag&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;information&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;ul&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;li&lt;/span&gt; &lt;span class=&quot;MetaTag&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;name&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&amp;lt;%=h person.&lt;span class=&quot;Entity&quot;&gt;name&lt;/span&gt; %&amp;gt;&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;li&lt;/span&gt; &lt;span class=&quot;MetaTag&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;email&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&amp;lt;%=link_to h(person.&lt;span class=&quot;Entity&quot;&gt;email&lt;/span&gt;), &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;mailto:&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;#{&lt;/span&gt;person&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;Entity&quot;&gt;email&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; %&amp;gt;&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;li&lt;/span&gt; &lt;span class=&quot;MetaTag&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;&lt;/span&gt;/&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;ul&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &amp;lt;% &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt; %&amp;gt;
&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;and we wanted to check if the search results are what we expect, we could write a Cucumber step that looks like this:&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
&lt;span class=&quot;Variable&quot;&gt;Then&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;Variable&quot;&gt;I&lt;/span&gt; should see the following search results&lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;$&lt;/span&gt;/&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;do &lt;/span&gt;|&lt;span class=&quot;Variable&quot;&gt;searches&lt;/span&gt;|
  search_results &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;element_at&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;div#search_results&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)
  node &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;Nokogiri&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;HTML&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&amp;lt;html&amp;gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;#{&lt;/span&gt;search_results&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;Entity&quot;&gt;element&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&amp;lt;/html&amp;gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).&lt;span class=&quot;Entity&quot;&gt;css&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;.information ul li.name&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)
  actual_table &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; node.&lt;span class=&quot;Entity&quot;&gt;map&lt;/span&gt; { |&lt;span class=&quot;Variable&quot;&gt;name&lt;/span&gt;| name.&lt;span class=&quot;Entity&quot;&gt;inner_html&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;strip&lt;/span&gt; }
  searches.&lt;span class=&quot;Entity&quot;&gt;diff!&lt;/span&gt;(actual_table)
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;and call it like this:&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
&lt;span class=&quot;Variable&quot;&gt;Then&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;I&lt;/span&gt; should see the following search results
  &lt;span class=&quot;Keyword&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;John&lt;/span&gt;  &lt;span class=&quot;Keyword&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;Mike&lt;/span&gt;  &lt;span class=&quot;Keyword&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;Susan&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;|&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Done!&lt;/p&gt;</description>
      <pubDate>Fri, 25 Sep 2009 07:37:55 GMT</pubDate>
      <guid>http://thinksimple.pl/entries/85-Multiline-step-arguments-with-Cucumber</guid>
    </item>
    <item>
      <title>AJAX pagination with Javascript</title>
      <link>http://thinksimple.pl/entries/83-AJAX-pagination-with-Javascript</link>
      <description>&lt;p&gt;Ryan Bates did an excellent &lt;a href=&quot;http://railscasts.com/episodes/174-pagination-with-ajax&quot;&gt;Railscast about pagination with &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt;&lt;/a&gt;. I&amp;#8217;d like to take it one step further and explain what to do when you want some Javascript functionality in the pagination partial.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s just go with something easy: say you want to highlight clicked products instead of continuing to the show product page. We&amp;#8217;ll create a file called &lt;code&gt;highlights.js&lt;/code&gt;:&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;//&lt;/span&gt; highlight.js&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;Keyword&quot;&gt;function&lt;/span&gt;() {
  &lt;span class=&quot;Keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;on&lt;/span&gt;() { 
    &lt;span class=&quot;Keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;this&lt;/span&gt;).css(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;background-color&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;yellow&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;); 
    &lt;span class=&quot;Keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;false&lt;/span&gt;;
  }

  &lt;span class=&quot;Keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;off&lt;/span&gt;() { 
    &lt;span class=&quot;Keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;this&lt;/span&gt;).css(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;background-color&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;transparent&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;); 
    &lt;span class=&quot;Keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;false&lt;/span&gt;;
  }

  &lt;span class=&quot;Keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;.product h3 a&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).live(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;click&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Keyword&quot;&gt;function&lt;/span&gt;() {
    &lt;span class=&quot;Keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;this&lt;/span&gt;).toggle(on, off);
    &lt;span class=&quot;Keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;false&lt;/span&gt;;
  });
});
&lt;/pre&gt;&lt;p&gt;Remember to include the file, we can do this in &lt;code&gt;index.html.erb&lt;/code&gt;, right below including &lt;code&gt;pagination.js&lt;/code&gt;&lt;br /&gt;
&lt;a name=&quot;index&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
&lt;span class=&quot;Keyword&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;%&lt;/span&gt; # index.html.erb &lt;span class=&quot;Keyword&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;%&lt;/span&gt; title &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;Products&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;%&lt;/span&gt; javascript &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;pagination&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;%&lt;/span&gt; javascript &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;highlights&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;&amp;gt;&lt;/span&gt;

&lt;span class=&quot;Keyword&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;%&lt;/span&gt; # more code here... &lt;span class=&quot;Keyword&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Okay, let&amp;#8217;s try it out. First click&amp;#8230; Oops, nothing happens. Second click &amp;#8211; background turns yellow. Third click &amp;#8211; background turns back white. Maybe second page will be better. First click &amp;#8211; nothing happens. Second click &amp;#8211; there it is, yellow. Third click &amp;#8211; white again.&lt;/p&gt;
&lt;p&gt;Everything works except for that nasty first click, where did this come from?&lt;/p&gt;
&lt;p&gt;Remember when we did this:&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
&lt;span class=&quot;Keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;.product h3 a&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).live(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;click&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Keyword&quot;&gt;function&lt;/span&gt;() {
  &lt;span class=&quot;Keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;this&lt;/span&gt;).toggle(on, off);
  &lt;span class=&quot;Keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;false&lt;/span&gt;;
});
&lt;/pre&gt;&lt;p&gt;What this &lt;code&gt;live&lt;/code&gt; thing does is bind a click event to all selected elements. The problem is that &lt;code&gt;toggle&lt;/code&gt; does exactly the same thing. So when we click for the first time, the &lt;code&gt;toggle&lt;/code&gt; method is run for the first time, and therefore it doesn&amp;#8217;t toggle anything, it just binds another click event. From then on everything works like it should. The simplest solution would be to call &lt;code&gt;toggle&lt;/code&gt; right after &lt;code&gt;live&lt;/code&gt;:&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
&lt;span class=&quot;Keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;.product h3 a&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).live(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;click&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Keyword&quot;&gt;function&lt;/span&gt;() {
  &lt;span class=&quot;Keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;this&lt;/span&gt;).toggle(on, off);
  &lt;span class=&quot;Keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;false&lt;/span&gt;;
});

&lt;span class=&quot;Keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;.product h3 a&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).toggle(on, off);
&lt;/pre&gt;&lt;p&gt;First page &amp;#8211; great, works! Second page &amp;#8211; oh crap! Apparently everything that&amp;#8217;s in the &lt;code&gt;highlight.js&lt;/code&gt; file has been done just once on the initial page load, and that includes the &lt;code&gt;toggle&lt;/code&gt; line we have just added. It should be done every time you change the page, because there are new links that need to have the click bound. If so, how about adding the &lt;code&gt;toggle&lt;/code&gt; line into &lt;code&gt;index.js.erb&lt;/code&gt;?&lt;br /&gt;
&lt;a name=&quot;toggle&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
&lt;span class=&quot;Keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;#products&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).html(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&amp;lt;%= escape_javascript(render(&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;products&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;)) %&amp;gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
&lt;span class=&quot;Keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;.product h3 a&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).toggle(on, off);
&lt;/pre&gt;&lt;p&gt;Trying the second page &amp;#8211; my Firebug says &amp;#8220;on&amp;#8221; is not defined. That gives me an idea. Let&amp;#8217;s change our &lt;code&gt;highlights.js&lt;/code&gt; file to this:&lt;br /&gt;
&lt;a name=&quot;highlights&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
&lt;span class=&quot;Keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;on&lt;/span&gt;() { 
  &lt;span class=&quot;Keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;this&lt;/span&gt;).css(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;background-color&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;yellow&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;); 
  &lt;span class=&quot;Keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;false&lt;/span&gt;;
}

&lt;span class=&quot;Keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;off&lt;/span&gt;() { 
  &lt;span class=&quot;Keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;this&lt;/span&gt;).css(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;background-color&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;transparent&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;); 
  &lt;span class=&quot;Keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;false&lt;/span&gt;;
}
  
&lt;span class=&quot;Keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;Keyword&quot;&gt;function&lt;/span&gt;() 
{
  &lt;span class=&quot;Keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;.product h3 a&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).live(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;click&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Keyword&quot;&gt;function&lt;/span&gt;() {
    &lt;span class=&quot;Keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;this&lt;/span&gt;).toggle(on, off);
    &lt;span class=&quot;Keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;false&lt;/span&gt;;
  });

  &lt;span class=&quot;Keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;.product h3 a&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).toggle(on, off);
});
&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;on&lt;/code&gt; and &lt;code&gt;off&lt;/code&gt; functions are now defined regardless of whether the page is ready or not. Check it again &amp;#8211; tadaa!&lt;/p&gt;
&lt;p&gt;Ok so just to sum up what we need to do from Ryan&amp;#8217;s final code:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;create &lt;code&gt;highlights.js&lt;/code&gt; with &lt;a href=&quot;#highlights&quot;&gt;this content&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;link to &lt;code&gt;highlights.js&lt;/code&gt; in &lt;a href=&quot;#index&quot;&gt;&lt;code&gt;index.html.erb&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;call &lt;code&gt;toggle&lt;/code&gt; in &lt;a href=&quot;#toggle&quot;&gt;&lt;code&gt;index.js.erb&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And actually, while we&amp;#8217;re at it, we might remove the &lt;code&gt;live&lt;/code&gt; call altogether. We need to bind the click event on our own each time anyway, so this is not needed anymore. So the final &lt;code&gt;highlights.js&lt;/code&gt; looks like this:&lt;/p&gt;&lt;pre class=&quot;lazy&quot;&gt;
&lt;span class=&quot;Keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;on&lt;/span&gt;() { 
  &lt;span class=&quot;Keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;this&lt;/span&gt;).css(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;background-color&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;yellow&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;); 
  &lt;span class=&quot;Keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;false&lt;/span&gt;;
}

&lt;span class=&quot;Keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;off&lt;/span&gt;() { 
  &lt;span class=&quot;Keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;this&lt;/span&gt;).css(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;background-color&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;transparent&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;); 
  &lt;span class=&quot;Keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;false&lt;/span&gt;;
}
  
&lt;span class=&quot;Keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;Keyword&quot;&gt;function&lt;/span&gt;() 
{
  &lt;span class=&quot;Keyword&quot;&gt;$&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;.product h3 a&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).toggle(on, off);
});
&lt;/pre&gt;&lt;p&gt;And you know what, I&amp;#8217;m just going to say it. &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; pagination sucks.&lt;/p&gt;</description>
      <pubDate>Fri, 14 Aug 2009 07:48:56 GMT</pubDate>
      <guid>http://thinksimple.pl/entries/83-AJAX-pagination-with-Javascript</guid>
    </item>
    <item>
      <title>Bye bye Prototype!</title>
      <link>http://thinksimple.pl/entries/81-Bye-bye-Prototype-</link>
      <description>&lt;p&gt;I&amp;#8217;ve been struggling for a couple of days to make a javascript carousel. Or, to find a library that does that. There are a ton of scripts out there, just grab one of &amp;#8216;em and let&amp;#8217;s get started!&lt;/p&gt;
&lt;p&gt;Ughhh. Little or no documentation. Incomplete examples. Lots of &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; and &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; just to have the same thing as in the example and it still doesn&amp;#8217;t work. Seriously, is it really that big? In the meantime I saw this page, &lt;a href=&quot;http://www.catswhocode.com/blog/top-10-javascript-slideshows-carousels-and-sliders&quot;&gt;Top 10 JS Carousels and Sliders&lt;/a&gt;. Out of those 10, 5 (namely: five!) were written in jQuery and only two in Prototype.&lt;/p&gt;
&lt;p&gt;So today I gave up. I installed &lt;a href=&quot;http://ennerchi.com/projects/jrails&quot;&gt;jrails&lt;/a&gt;. And tried out &lt;a href=&quot;http://www.gmarwaha.com/jquery/jcarousellite/&quot;&gt;jCarouselLite&lt;/a&gt; as &lt;a href=&quot;http://sorgalla.com/projects/jcarousel/&quot;&gt;jCarousel&lt;/a&gt; seemed too big for my needs. And guess what? I got it up and running in about 10 minutes, including downloading, skimming documentation and updating my &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; (actually, removing all unnecessary markup needed by previous libraries). Worked like a charm. Also, now I&amp;#8217;m really really angry that Rails makes you use Prototype by default.&lt;/p&gt;
&lt;p&gt;You can see the result on my &lt;a href=&quot;http://thinksimple.pl/projects&quot;&gt;projects page&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Mon, 27 Jul 2009 07:03:46 GMT</pubDate>
      <guid>http://thinksimple.pl/entries/81-Bye-bye-Prototype-</guid>
    </item>
  </channel>
</rss>

