<?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" xml:lang="en-US">
  <title>Drogomir's blog - Home</title>
  <id>tag:drogomir.com,2009:mephisto/</id>
  <generator uri="http://mephistoblog.com" version="0.8.0">Mephisto Drax</generator>
  
  <link href="http://drogomir.com/blog/" rel="alternate" type="text/html" />
  <updated>2009-09-24T15:52:13Z</updated>
  <link rel="self" href="http://feeds.feedburner.com/blog-drogomir" type="application/atom+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry xml:base="http://drogomir.com/blog/">
    <author>
      <name>drogus</name>
    </author>
    <id>tag:drogomir.com,2009-09-24:3254</id>
    <published>2009-09-24T15:46:00Z</published>
    <updated>2009-09-24T15:52:13Z</updated>
    <category term="survey" />
    <category term="testing" />
    <category term="web developmenr" />
    <link href="http://feedproxy.google.com/~r/blog-drogomir/~3/tzIPSCe4qjo/web-development-testing-survey" rel="alternate" type="text/html" />
    <title>Web development testing survey</title>
<content type="html">
            &lt;p&gt;I would like to know what are testing habits of web developers and I’ve created a survey to find it out. It’s focused on testing, especially browser testing, but if do not test, your voice is still
valueable, don’t give up and fill it anyway :)&lt;/p&gt;


	&lt;p&gt;Survey is on google docs: 
&lt;a href="http://spreadsheets.google.com/viewform?formkey=dGxzNHQzT1hsUmtlVTRTVTcwMHR3aFE6MA"&gt;http://spreadsheets.google.com/viewform?formkey=dGxzNHQzT1hsUmtlVTRTVTcwMHR3aFE6MA&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;I will publish the results as soon as I will got sufficient number of
votes or in 2-3 weeks.&lt;/p&gt;
          </content>  <feedburner:origLink>http://drogomir.com/blog/2009/9/24/web-development-testing-survey</feedburner:origLink></entry>
  <entry xml:base="http://drogomir.com/blog/">
    <author>
      <name>drogus</name>
    </author>
    <id>tag:drogomir.com,2009-06-16:1911</id>
    <published>2009-06-16T11:25:00Z</published>
    <updated>2009-07-24T10:46:27Z</updated>
    <category term="acceptanace testing" />
    <category term="ajax" />
    <category term="celerity" />
    <category term="cucumber" />
    <category term="culerity" />
    <category term="javascript" />
    <category term="testing" />
    <link href="http://feedproxy.google.com/~r/blog-drogomir/~3/S70e91YqM7A/cucumber-and-celerity-testing-unobtrusive-javascript" rel="alternate" type="text/html" />
    <title>Cucumber and Celerity - testing unobtrusive javascript</title>
<content type="html">
            &lt;p&gt;In the world of javascript and ajax web apps I often find that writing applications supporting both javascript enabled and disabled is hard. For the sake of simplicity and due to deadlines I often write only javascript version of some of the features. But there are many situations where both scenarios should be supported.&lt;/p&gt;


	&lt;p&gt;The most important parts of app, especially the ones that must be crawled by google, should be written with unobtrusive style. And here comes the problem… I rarely see javascript testing and till today I haven’t done it myself. Celerity and cucumber (with help of culerity) can solve this problem. Here is short guide introducing this technique.&lt;/p&gt;


	&lt;p&gt;I will use &lt;a href="http://cukes.info/"&gt;Cucumber&lt;/a&gt;, &lt;a href="http://celerity.rubyforge.org/"&gt;celerity&lt;/a&gt; (which is &lt;a href="http://htmlunit.sourceforge.net/"&gt;HtmlUnit&lt;/a&gt; wrapper with &lt;span class="caps"&gt;API&lt;/span&gt; compatible with watir) and &lt;a href="http://github.com/langalex/culerity/tree/master"&gt;culerity&lt;/a&gt;. Culerity is a proxy between celerity and your app. Celerity requires JRuby and probably your app need &lt;span class="caps"&gt;MRI&lt;/span&gt; or &lt;span class="caps"&gt;REE&lt;/span&gt; – culerity resolves this problem.&lt;/p&gt;


	&lt;p&gt;Let’s get started.&lt;/p&gt;


	&lt;p&gt;You need to &lt;a href="http://kenai.com/projects/jruby/pages/GettingStarted#Installing_a_JRuby_Binary_Fille"&gt;install JRuby&lt;/a&gt; in order to run celerity. After installing and adding jruby to your &lt;span class="caps"&gt;PATH&lt;/span&gt; install celerity gem (probably as a root):&lt;/p&gt;


&lt;pre&gt;&lt;code class="console"&gt;
jruby -S gem install celerity
&lt;/code&gt;&lt;/pre&gt;

Now you can create rails app and configure the environment:
&lt;pre&gt;&lt;code class="console"&gt;
rails culerity-example
sudo gem install cucumber rspec rspec-rails haml
# add config.gem "haml" to environment.rb
gem install langalex-culerity --source http://gems.github.com
cd culerity-example
./script/generate cucumber
./script/generate rspec
# now edit database.yml and set database options
rake db:migrate
rake features
rm features/step_definitions/webrat_steps.rb # cause we will be using celerity
&lt;/code&gt;&lt;/pre&gt;

At this point you should have cucumber configured and you should be able to run “rake features” with output similar to:
&lt;pre&gt;&lt;code class="console"&gt;
0 scenarios
0 steps
0m0.000s
&lt;/code&gt;&lt;/pre&gt;

Let’s add some tests! You will need step definitions and hooks. Culerity provides some basic step definitions and hooks which you can generate with ”./script/generate culerity” but I’ve changed them a bit for my needs, so you can find them on &lt;a href="http://github.com/drogus/culerity-javascript-example"&gt;this example repository&lt;/a&gt;.
	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://github.com/drogus/culerity-javascript-example/blob/master/features/step_definitions/common_celerity.rb"&gt;features/step_definitions/common_celerity.rb&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://github.com/drogus/culerity-javascript-example/blob/master/features/support/hooks.rb"&gt;features/support/hooks.rb&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Copy those files to your app.&lt;/p&gt;


	&lt;p&gt;The first file is just rewrite of webrat steps and the second file adds hooks for firing celerity server and browser. Let me explain the hooks.rb file:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;
require 'culerity'
`mongrel_rails start -e cucumber -p 3001 -d`

Before do
  $server ||= Culerity::run_server
  $browser = Culerity::RemoteBrowserProxy.new $server, {:browser =&amp;gt; :firefox}
  $browser.webclient.setJavaScriptEnabled(false) 
  @host = 'http://localhost:3001'
end

Before("@js") do |scenario|
  $browser.webclient.setJavaScriptEnabled(true)
end

at_exit do
  $browser.exit
  $server.close
  `mongrel_rails stop`
end
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;‘Before’ hooks are run before each scenerio. In first ‘before’ hook server and browser are set up and host is set to “http://localhost:3001” (change it if you want to run app on other address or port). Notice the line: $browser.webclient.setJavaScriptEnabled(false) – it disables javascript by default.&lt;/p&gt;


	&lt;p&gt;Second Before hook is fired only for scenarios tagged with @js tag. It will be useful for explicitly saying which scenarios should be tested with  javascript.&lt;/p&gt;


	&lt;p&gt;&lt;ins&gt;I’ve also added lines to start mongrel before the tests and stop it at exit. It’s handy if you don’t want to run and restart mongrel manually&lt;/ins&gt;&lt;/p&gt;


Now it is time to write some scenarios. File &lt;a href="http://github.com/drogus/culerity-javascript-example/blob/master/features/javascript.feature"&gt;features/javascript.feature&lt;/a&gt;
&lt;pre&gt;&lt;code&gt;
Feature: Javascript
  In order to test javascript
  As a developer
  I need a way to run test scenarios with javascript enabled or disabled

  @js
  Scenario: With javascript
    Given I am on the homepage
    And I follow "Click me!" 
    Then I should see "Javascript rocks!" 

  Scenario: Without javascript
    Given I am on the homepage
    And I follow "Click me!" 
    Then I should see "I am also working without javascript!" 
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Both scenerios rely on “Click me!” link but have different expectations. &lt;del&gt;To run those tests start mongrel (or any other web server):&lt;/del&gt;
&lt;del&gt;&lt;pre&gt;&lt;code&gt;
mongrel_rails start -e cucumber -p 3001 -d
&lt;/code&gt;&lt;/pre&gt;&lt;/del&gt;&lt;/p&gt;


	&lt;p&gt;&lt;del&gt;This will fire mongrel in background on port 3001.&lt;/del&gt;
&lt;ins&gt;It is not necessary as mongrel control commands are in hooks.rb file&lt;/ins&gt;&lt;/p&gt;


	&lt;p&gt;It’s best to operate on 2 console tabs while using celerity. One of the big drawbacks of using it, is lack of displaying rails exceptions. Because of that I run cucumber on one tab and “tail -f log/cucumber.log” on the other – I can see errors in the log without opening the browser.&lt;/p&gt;


	&lt;p&gt;Let’s run tests: &lt;pre&gt;rake features&lt;/pre&gt;&lt;/p&gt;


	&lt;p&gt;Of course both tests should fail with &lt;pre&gt;Unable to locate Link, using :text and /Click me!/&lt;/pre&gt; and rails error in log file: &lt;pre&gt;ActionController::RoutingError (No route matches "/" with {:method=&amp;gt;:get}):&lt;/pre&gt;&lt;/p&gt;


Now we can fix it. We need some controller to show the link: 
&lt;pre&gt;script/generate rspec_controller home&lt;/pre&gt;

	&lt;p&gt;Add &lt;pre&gt;map.root :action =&amp;gt; "show", :controller =&amp;gt; "home"&lt;/pre&gt; to routes file.
Next copy &lt;a href="http://github.com/drogus/culerity-javascript-example/raw/master/app/views/layouts/main.html.haml"&gt;app/views/layouts/main.html.haml&lt;/a&gt; (it just yields action and includes jquery.js and application.js) and &lt;a href="http://github.com/drogus/culerity-javascript-example/raw/master/public/javascripts/jquery.js"&gt;jquery.js&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;You need to also set layout for home controller: &lt;pre&gt;layout 'main'&lt;/pre&gt;&lt;/p&gt;


And here comes html and javascript.
app/views/home/show.html.haml
&lt;pre&gt;&lt;code class="haml"&gt;
= link_to "Click me!", "?clicked=1", :id =&amp;gt; "click_me" 

#text
  - if params[:clicked]
    I am also working without javascript!
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;It displays a link and a text if params[:clicked] is present. So after clicking on that link page will be reloaded with parameter clicked=1 and the text will be displayed.&lt;/p&gt;


Let’s check if it’s passing:
&lt;pre&gt;mongrel_rails restart; rake features&lt;/pre&gt;
We need to restart mongrel before “rake features” in order to load changes because of “cache_classes = true”. It’s one of the drawbacks of using this method, but I’m sure that someone will find out better way to do that.

	&lt;p&gt;If you did everything properly the second scenario should pass now. We’re green! :D&lt;/p&gt;


Add javascript code to your application in order to make the second scenario pass:
&lt;pre&gt;&lt;code class="javascript"&gt;
jQuery(function() {
  $("#click_me").click(function() {
    $("#text").html("Javascript rocks!");
    return false;
  });
})
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now both scenarios should pass.&lt;/p&gt;


To sum up, now you should be able to:
	&lt;ul&gt;
	&lt;li&gt;configure rails app with cucumber and celerity&lt;/li&gt;
		&lt;li&gt;specify how your tests should be run by placing @js tag on top of javascript scenarios&lt;/li&gt;
		&lt;li&gt;test unobtrusive javascript with ease&lt;/li&gt;
	&lt;/ul&gt;


TODOs:
	&lt;ul&gt;
	&lt;li&gt;&lt;del&gt;figure out better way to reload rails app while testing&lt;/del&gt;&lt;/li&gt;
		&lt;li&gt;provide better error explanations in cucumber with celurity to test without tailing logs&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Cheers!&lt;/p&gt;


	&lt;h3&gt;Additional resources
	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://github.com/alvinschur/celerity-examples"&gt;Celerity ajax examples by Alvin Schur&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;&lt;/h3&gt;
          </content>  <feedburner:origLink>http://drogomir.com/blog/2009/6/16/cucumber-and-celerity-testing-unobtrusive-javascript</feedburner:origLink></entry>
  <entry xml:base="http://drogomir.com/blog/">
    <author>
      <name>drogus</name>
    </author>
    <id>tag:drogomir.com,2009-05-12:1784</id>
    <published>2009-05-12T13:42:00Z</published>
    <updated>2009-05-12T13:48:08Z</updated>
    <category term="alias_method_chain" />
    <category term="memcached" />
    <category term="rails" />
    <category term="ruby" />
    <category term="safe_erb" />
    <link href="http://feedproxy.google.com/~r/blog-drogomir/~3/S-wASf185gY/fixing-safe_erb-with-memcached-improved" rel="alternate" type="text/html" />
    <title>Fixing safe_erb with memcached improved</title>
<content type="html">
            &lt;p&gt;Ruby has many structures that are weird and dangerous to some programmers that works with Java or other more “traditional” OO languages. For me it’s great and metaprogramming capabilities makes ruby killer in case of DSLs, nice looking APIs and avoiding repeating yourself.&lt;/p&gt;


	&lt;p&gt;But many problems that are solved with alias_method_chain or method_missing can be solved easier without the code smell. I sometimes find myself designing some weird complex solutions and then, after looking at it saying: “Hey! Why not just use OO features!”. I encourage everybody to look critically at every piece of your code that seems to be overkill and can be replaced with standard OO design.&lt;/p&gt;


	&lt;p&gt;One of examples is &lt;a href="http://www.nfjsone.com/blog/david_bock/2009/03/fixing_safe_erb_with_memcached_fragments.html"&gt;fixing memcached and safe_erb duet with alias_method_chain&lt;/a&gt; I don’t know if this solution worked in older versions of rails, but in 2.3 I got stack level too deep error. After some thinking I’ve just created subclass of MemCacheStore:&lt;/p&gt;


&lt;p&gt;And then you can simply set it as cache store: config.cache_store = :my_mem_cache_store&lt;/p&gt;


	&lt;p&gt;And that’s it, no alias method chain :)&lt;/p&gt;
          </content>  <feedburner:origLink>http://drogomir.com/blog/2009/5/12/fixing-safe_erb-with-memcached-improved</feedburner:origLink></entry>
  <entry xml:base="http://drogomir.com/blog/">
    <author>
      <name>drogus</name>
    </author>
    <id>tag:drogomir.com,2009-05-03:1748</id>
    <published>2009-05-03T19:02:00Z</published>
    <updated>2009-05-03T19:07:30Z</updated>
    <category term="git" />
    <category term="tips" />
    <link href="http://feedproxy.google.com/~r/blog-drogomir/~3/s8ZXPgfwctQ/managing-many-app-variants-with-git" rel="alternate" type="text/html" />
    <title>Managing many app variants with git</title>
<content type="html">
            &lt;p&gt;One of my friends works on application that have basically two variants with slight modifications between each of them. It can be horror to work with two similar applications without good &lt;span class="caps"&gt;SCM&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;Happily we have git :)&lt;/p&gt;


	&lt;p&gt;How to deal with this problem? It’s based on &lt;a href="http://drogomir.com/blog/2009/4/26/my-git-workflow"&gt;git approach from one of my previous posts&lt;/a&gt; so read it first.&lt;/p&gt;


	&lt;p&gt;Main task is to find last commit with which applications were identical. Let’s say that it’s:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
commit b576de0csadcscs846ef933edf75e449d12db39d
Author: FooBar
Date:   Thu Apr 16 13:07:01 2009 -0700

    Last touches before creating appliaction variant.
&lt;/code&gt;&lt;/pre&gt;

We must create a branch that will be ancestor for both variants:
&lt;pre&gt;&lt;code&gt;
git checkout -b both b576de0c
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now branch both keeps only things that are identical in every variant of application. If you want to make some changes and merge them with both applications just:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
git checkout both
git checkout -b bugfix23
# fix this nasty bug
git checkout both
git merge bugfix23 # merge it back to both
git checkout variant1 
git merge both # merge the changes to variant 1
git checkout variant2
git merge both # merge the changes to variant 2
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Why can’t I just do it without both?&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
# don't do it!
git checkout variant1
git checkout -b bugfix23 # now we are on bugfix23 which has variant's 1 commits in history
# fix this nasty bug
git checkout variant1 
git merge bugfix23 # everything is fine, mergeing changes from bugfix
git checkout variant2
git merge bugfix23 # now your repo is a mess - you've just merged all of the variant's 1 commits
&lt;/code&gt;&lt;/pre&gt;

So what to do if you accidentally commited changes to branch inheriting from one of the variants? You can just cherry-pick one of the commits:
&lt;pre&gt;&lt;code&gt;
git cherry-pick cs6dc876
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;It’s like a merge, but merging only one commit.&lt;/p&gt;
          </content>  <feedburner:origLink>http://drogomir.com/blog/2009/5/3/managing-many-app-variants-with-git</feedburner:origLink></entry>
  <entry xml:base="http://drogomir.com/blog/">
    <author>
      <name>drogus</name>
    </author>
    <id>tag:drogomir.com,2009-04-28:1724</id>
    <published>2009-04-28T13:03:00Z</published>
    <updated>2009-04-28T13:19:59Z</updated>
    <category term="docx" />
    <category term="microsoft" />
    <category term="ruby" />
    <link href="http://feedproxy.google.com/~r/blog-drogomir/~3/JxxAaYa-Hm4/reading-docx-files-with-ruby" rel="alternate" type="text/html" />
    <title>Reading docx files with ruby</title>
<content type="html">
            &lt;p&gt;Just a quick post about handling docx (and other &lt;strong&gt;*&lt;/strong&gt;x formats) with ruby.&lt;/p&gt;


	&lt;p&gt;These files are basically &lt;span class="caps"&gt;XML&lt;/span&gt; packed with zip, so reading them is as just extracting the zip and parsing xml files. Here is a snippet with getting pages count from docx file:&lt;/p&gt;


&lt;p&gt;Reading the text is also easy – it’s located in word/document.xml.&lt;/p&gt;


	&lt;p&gt;I must say that this is a step at the right direction. Reading older microsoft formats without windows &lt;span class="caps"&gt;API&lt;/span&gt; is hard and painful… Although there is a possibility to run MS Office with wine and access it using Win32::Ole and Perl (I’ve tried it once, don’t ask…), there are license problems as far as I know.&lt;/p&gt;
          </content>  <feedburner:origLink>http://drogomir.com/blog/2009/4/28/reading-docx-files-with-ruby</feedburner:origLink></entry>
  <entry xml:base="http://drogomir.com/blog/">
    <author>
      <name>drogus</name>
    </author>
    <id>tag:drogomir.com,2009-04-26:1717</id>
    <published>2009-04-26T19:56:00Z</published>
    <updated>2009-04-26T20:06:38Z</updated>
    <category term="git" />
    <category term="tips" />
    <category term="workflow" />
    <link href="http://feedproxy.google.com/~r/blog-drogomir/~3/-SlY3cMKe0E/my-git-workflow" rel="alternate" type="text/html" />
    <title>My git workflow</title>
<content type="html">
            &lt;p&gt;I know that this post may be obvious for experienced git users, but it may be useful for some of you.&lt;/p&gt;


	&lt;p&gt;Github has &lt;a href="http://github.com/blog/421-pick-your-default-branch"&gt;added default branch picking&lt;/a&gt; recently. It’s great, as you don’t have to use master branch as your main branch. I usually have three “main” branches in my repo – production, staging and development.&lt;/p&gt;


	&lt;p&gt;The main point of it is to have separate branch for each environment (sometimes I skip staging, but it’s often wise to have some point between development and production). My main problem with git (or maybe rather with my lack of knowledge about git) in the very beginning of using git was to learn how to use branches efficiently. After some time with git I’ve noticed that it’s best to keep each fix or idea in separate branch.&lt;/p&gt;


	&lt;p&gt;One crucial thing is to inherit from production when it’s possible. Let’s say you have those main branches I mentioned before. There is a bug #345 in bug tracker and you want to fix it and merge into production after showing results to the client. The best way is to begin with production:&lt;/p&gt;


&lt;pre&gt;&lt;code class="console"&gt;
git checkout -b bug345 production
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;It will create new branch bug345 with production as a parent branch. Now:&lt;/p&gt;


&lt;pre&gt;&lt;code class="console"&gt;
# fix the bug
git commit -m "Fixed the nasty bug #345" 
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Sometimes client doesn’t need reviewing the changes but when he does you should have ability to show it and merge it to the production branch later.&lt;/p&gt;


&lt;pre&gt;&lt;code class="console"&gt;
git checkout staging
git merge bug345
# deploy staging
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;After the client approval of your solution you can merge the bugfix to the production branch:&lt;/p&gt;


&lt;pre&gt;&lt;code class="console"&gt;
git checkout production
git merge bug345
# deploy production
# you can remove bug345 branch now
git branch -d bug345
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The most important thing in this process is to always inherit from production branch, unless you need changes from other branches. Otherwise you could merge some needless junk from other branches or have to cherry-pick individual commits. With above solution everything is clean and you are sure that that you will merge only what you need.&lt;/p&gt;


	&lt;p&gt;Hope it will help :)&lt;/p&gt;
          </content>  <feedburner:origLink>http://drogomir.com/blog/2009/4/26/my-git-workflow</feedburner:origLink></entry>
  <entry xml:base="http://drogomir.com/blog/">
    <author>
      <name>drogus</name>
    </author>
    <id>tag:drogomir.com,2009-02-10:1342</id>
    <published>2009-02-10T09:08:00Z</published>
    <updated>2009-02-10T09:18:03Z</updated>
    <category term="apache" />
    <category term="jsonp" />
    <category term="progress" />
    <category term="upload" />
    <link href="http://feedproxy.google.com/~r/blog-drogomir/~3/imwiwuPWBMs/json-p-support-for-apache-upload-progress" rel="alternate" type="text/html" />
    <title>JSON-P support for Apache upload progress</title>
<content type="html">
            &lt;p&gt;Just a quick note about new feature added to apache upload progress and jquery upload progress libs.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://deadprogrammersociety.blogspot.com/"&gt;Ron Evans aka deadprogrammer&lt;/a&gt; has added support for &lt;span class="caps"&gt;JSON&lt;/span&gt;-P in &lt;a href="http://github.com/drogus/apache-upload-progress-module/commit/20fed47119d3ea70b91ccb6a91a9338c8f127304"&gt;this commit&lt;/a&gt;. What does it mean? Cross domain requests are now possible, so if you need such a functionality pull the newest changes.&lt;/p&gt;


Here is Ron’s description from &lt;span class="caps"&gt;README&lt;/span&gt;:
&lt;blockquote&gt;
- &lt;span class="caps"&gt;JSON&lt;/span&gt;-P Support

	&lt;p&gt;You can also request progress updates by using &lt;span class="caps"&gt;JSON&lt;/span&gt;-P, if you are uploading the file from a different domain or  subdomain than the web server that is handling your original request. Adding a “callback=yourCallbackFunction” parameter  to your request to the progress server will activate this functionality.&lt;/p&gt;


	&lt;p&gt;For example, a request like:
  http://uploads.yourdomain.com/progress?callback=jsonp123&amp;X-Progress-ID=1234&lt;/p&gt;


	&lt;p&gt;Would return the &lt;span class="caps"&gt;JSON&lt;/span&gt;-P function: 
  jsonp123(new Object({ ‘state’ : ‘uploading’, ‘received’ : 35587, ‘size’ : 716595, ‘speed’ : 35587 }));&lt;/p&gt;


	&lt;p&gt;The normal &lt;span class="caps"&gt;JSON&lt;/span&gt; request:
  http://www.yourdomain.com/progress?X-Progress-ID=1234&lt;/p&gt;


Would return the &lt;span class="caps"&gt;JSON&lt;/span&gt; data: 
  new Object({ ‘state’ : ‘uploading’, ‘received’ : 35587, ‘size’ : 716595, ‘speed’ : 35587 })
&lt;/blockquote&gt;

	&lt;p&gt;Remember to update &lt;a href="http://github.com/drogus/jquery-upload-progress/tree/master"&gt;jquery upload progress&lt;/a&gt; also, to use jsonp.&lt;/p&gt;


	&lt;p&gt;Enjoy :)&lt;/p&gt;
          </content>  <feedburner:origLink>http://drogomir.com/blog/2009/2/10/json-p-support-for-apache-upload-progress</feedburner:origLink></entry>
  <entry xml:base="http://drogomir.com/blog/">
    <author>
      <name>drogus</name>
    </author>
    <id>tag:drogomir.com,2008-07-03:19</id>
    <published>2008-07-03T16:40:00Z</published>
    <updated>2008-07-03T20:59:29Z</updated>
    <link href="http://feedproxy.google.com/~r/blog-drogomir/~3/05zvVa2bpiw/tweaking-rails-app-with-jquery-part-i" rel="alternate" type="text/html" />
    <title>Tweaking Rails app with jQuery, part I</title>
<content type="html">
            &lt;div class="quick-links"&gt;

	&lt;p&gt;Quick links:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt; &lt;a href="http://mugshots.drogomir.com/js/step2/mugshots"&gt;completed demo&lt;/a&gt; (demo is reseted every few hours)&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://github.com/drogus/mugshots/tree/master"&gt;sources of application on github&lt;/a&gt; (&lt;a href="http://github.com/drogus/mugshots/tarball/master"&gt;or download tarball&lt;/a&gt;)&lt;/li&gt;
	&lt;/ul&gt;


&lt;/div&gt;

	&lt;p&gt;I’m in the train from &lt;a href="http://maps.google.com/maps?f=d&amp;amp;#38;hl=en&amp;amp;#38;geocode=&amp;amp;#38;saddr=Zgorzelec,+Poland&amp;amp;#38;daddr=warsaw,+poland&amp;amp;#38;sll=37.0625,-95.677068&amp;amp;#38;sspn=58.470251,108.984375&amp;amp;#38;ie=UTF8&amp;amp;#38;ll=51.604372,17.578125&amp;amp;#38;spn=5.815072,13.623047&amp;amp;#38;z=6"&gt;Zgorzelec to Warsaw&lt;/a&gt; returning from my girlfriend’s place. Polish trains are like turtles, so I will have pretty much time for writing ;-)&lt;/p&gt;


	&lt;p&gt;I’ve wrote (or maybe it’s better to say copy&amp;paste) little rails app like in &lt;a href="http://clarkware.com/cgi/blosxom/2007/02/24"&gt;Mike Clark’s tutorial for attachment_fu&lt;/a&gt;. A few months ago there was &lt;a href="http://www.yoursgallery.pl/exhibitions.php?action=details&amp;amp;#38;exh_id=44&amp;amp;#38;setlang=en"&gt;Mugshots exhibition in Yours Gallery&lt;/a&gt; in Warsaw based on &lt;a href="http://www.amazon.com/City-Shadows-Sydney-Photographs-1912-1948/dp/1876991208/ref=pd_bbs_sr_2?ie=UTF8&amp;amp;#38;s=books&amp;amp;#38;qid=1215106900&amp;amp;#38;sr=8-2"&gt;work of Peter Doyle&lt;/a&gt;. I saw it with Kathleene, she took some pictures. Great! I have material to fill my new app, what else could I possibly dream of?! (yeah… macbook, but it’s obvious ;-).&lt;/p&gt;


	&lt;p&gt;Now you can admire my hard work: &lt;a href="http://mugshots.drogomir.com/js/no-javascript/mugshots/"&gt;mugshots.drogomir.com/js/no-javascript/mugshots/&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;But wait… It’s not so cool… where are all those shiny javascript effects? Don’t worry. I will show you how to spice this dish.&lt;/p&gt;


We will need:
	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.malsup.com/jquery/form/"&gt;jQuery form plugin&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://brandonaaron.net/docs/livequery/"&gt;jQuery livequery plugin&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://github.com/drogus/jquery-upload-progress/"&gt;jQuery upload progress&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://malsup.com/jquery/block/" title="used by multifile"&gt;jquery blockUI&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.fyneworks.com/jquery/multiple-file-upload/"&gt;jquery mutli file&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://github.com/drogus/lightbox-fu/tree/master"&gt;jquery lightBoxFu&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://leandrovieira.com/projects/jquery/lightbox/"&gt;lightbox&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;I’ve pushed application to github, so you can see entire code. Clone it or &lt;a href="http://cdsc"&gt;grab the tarball&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;There is one thing that is not straight forward. @main_js variable in app/views/layouts/main.rhtml:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;
&amp;lt;%= javascript_include_tag @main_js %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;It’s there for changing javascript file loaded. When url is app.com/js/some_javascript_file/mugshots, @main_js should be “some_javascript_file.js”. I’ve done this to have possibility to show you app with different javascript files without changing the code. See routes and mugshots_controller.rb to find out how it was done (or run “rake routes” in app dir to see routes).&lt;/p&gt;


	&lt;p&gt;Lets begin.&lt;/p&gt;


	&lt;p&gt;What to do first? It’s all about uploading files, so I would add upload progress bar to form in &lt;a href="http://mugshots.drogomir.com/mugshots/new"&gt;mugshots.drogomir.com/mugshots/new&lt;/a&gt;. To implement it you will need some kind of server module:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://drogomir.com/blog/2008/6/18/upload-progress-bar-with-mod_passenger-and-apache"&gt;Apache upload progress module&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://wiki.codemongers.com/NginxHttpUploadProgressModule"&gt;Nginx upload progress module&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://upload.lighttpd.net/"&gt;Lighttpd upload progress&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;You have to install and enable one of the above modules to make progress bar work.&lt;/p&gt;


	&lt;p&gt;Then add some javascript to applications.js. This example is using “LightBoxFu”: – little script that I wrote to show progress bar as an overlay. It’s based on &lt;a href="http://riddle.pl/"&gt;Riddle’s work&lt;/a&gt; – all positioning is in &lt;span class="caps"&gt;CSS&lt;/span&gt; (except expressions for IE) so it’s really light and fast. Ideal for such a task. If you don’t like lightBoxFu you can use any other form of displaying message (you can use some other lightbox with displaying code function or even blockUI plugin).&lt;/p&gt;


&lt;pre&gt;&lt;code class="javascript"&gt;
// handy trick, if we can't use $ beaceuse jQuery.noConflict
// was used, jQuery is passed as argument in document ready
// so we can name it $
jQuery(function($) {
  // add upload progress to our form
  $('form.progress').uploadProgress({
    start:function(){
      // after starting upload open lightBoxFu with our bar as html
      $.lightBoxFu.open({
        html: '&amp;lt;div id="uploading"&amp;gt;&amp;lt;span id="received"&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span id="size"&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;div id="progress" class="bar"&amp;gt;&amp;lt;div id="progressbar"&amp;gt;&amp;amp;nbsp;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;span id="percent"&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;',
        width: "250px",
        closeOnClick: false
      });
      jQuery('#received').html("Upload starting.");
      jQuery('#percent').html("0%");
    },
    uploading: function(upload) {
      // update upload info on each /progress response
      jQuery('#received').html("Uploading: "+parseInt(upload.received/1024)+"/");
      jQuery('#size').html(parseInt(upload.size/1024)+" kB");
      jQuery('#percent').html(upload.percents+"%");
    },
    interval: 2000,
    /* if we are using images it's good to preload them, safari has problems with
       downloading anything after hitting submit button. these are images for lightBoxFu
       and progress bar */
    preloadImages: ["/images/overlay.png", "/images/ajax-loader.gif"]
  });
});
&lt;/code&gt;&lt;/pre&gt;

And some styling for progress bar:
&lt;pre&gt;&lt;code class="css"&gt;
  #progress {
  margin: 8px;
  width: 220px;
  height: 19px;
}

#progressbar {
  background: url('/images/ajax-loader.gif') no-repeat;
  width: 0px;
  height: 19px;
}
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;That’s it, just add “progress” class to your form and progress bar is working:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;
&amp;lt;% form_for(:mugshot, :url =&amp;gt; mugshots_path, 
                      :html =&amp;gt; { :multipart =&amp;gt; true, :class =&amp;gt; "progress" }) do |f| -%&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Uploading files looks much better right now, check it here: &lt;a href="http://mugshots/drogomir.com/js/progress/mugshots/new"&gt;http://mugshots.drogomir.com/js/progress/mugshots/new&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;So what now? I find the “add photo, click New mugshot, add photo” scenerio annoying. We could add more than one file on each submit. For that we will use jquery.MultiFile.js. This one is a bit tricky, cause we will need to tweak code handling uploads also.&lt;/p&gt;


	&lt;p&gt;Javascript enabling mutlifile:&lt;/p&gt;


&lt;pre&gt;&lt;code class="javascript"&gt;
jQuery(function($) {
  $('.multi-file').each(function() {
    // change name of element before applying MultiFile
    // so array of files can be send to server with mugshot[uploaded_data][]
    $(this).attr('name', $(this).attr('name') + '[]');
  }).MultiFile();
});
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;We must also add “multi-file” class to file field:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;
&amp;lt;%= f.file_field :uploaded_data, :class =&amp;gt; 'multi-file' %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;From javascript point of view that’s all. Let’s see how uploaded photos are handled by rails app:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;
@mugshot = Mugshot.new(params[:mugshot])
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;So mugshot.uploaded_data is filled with data from &lt;code&gt;params[:mugshot][:uploaded_data]&lt;/code&gt;. Good for one file. But with array of files we should create Mugshot for each file. I would add a method in model:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;
  def self.handle_upload(mugshot_params)
    # array for not saved mugshots
    mugshots = []
    if mugshot_params[:uploaded_data].kind_of?(Array)
      mugshot_params[:uploaded_data].each do |p| 
        unless p.blank?
          mugshot = Mugshot.new(:uploaded_data =&amp;gt; p)
          mugshots &amp;lt;&amp;lt; mugshot unless mugshot.save
        end
      end
    else
      mugshot = Mugshot.new(mugshot_params)
      mugshots &amp;lt;&amp;lt; mugshot unless mugshot.save
    end
    mugshots
  end
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;and slightly change controller code:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;
  def create
    @mugshots = Mugshot.handle_upload(params[:mugshot])

    # if @mugshots is empty there are no errors
    if @mugshots.blank?
      flash[:notice] = 'Mugshot was successfully created.'
      redirect_to mugshots_url
    else
      render :action =&amp;gt; :new
    end
  end
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Only one problem left. Validation.&lt;/p&gt;


	&lt;p&gt;Easiest way is to change error_messages_for:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;
&amp;lt;%= error_messages_for :object =&amp;gt; @mugshots %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;It works. But suppose you are uploading 3 files and 2 of them are too big. You will end with:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Size is not included in the list&lt;/li&gt;
		&lt;li&gt;Size is not included in the list&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Which one was added? Some lottery here…&lt;/p&gt;


	&lt;p&gt;I would tweak attachment_fu error messages a bit. By default it uses validates_as_attachment method which simply adds:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;
  validates_presence_of :size, :content_type, :filename
  validate  :attachment_attributes_valid?
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Instead validates_as_attachment we can isert our new code:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;
  validates_presence_of :size, :content_type, :filename, :message =&amp;gt; Proc.new { |mugshot| "can't be blank (#{mugshot.filename})" }
  validate  :attachment_attributes_valid?

  def attachment_attributes_valid?
    [:size, :content_type].each do |attr_name|
      enum = attachment_options[attr_name]
      errors.add attr_name, "#{ActiveRecord::Errors.default_error_messages[:inclusion]} (#{self.filename})" unless enum.nil? || enum.include?(send(attr_name))
    end
  end
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now it’s a lot more readable:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Size is not included in the list (filename.jpg)&lt;/li&gt;
		&lt;li&gt;Size is not included in the list (filename1.jpg)&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Submit form looks better now, but viewing files is still ugly. Maybe we could add some lightbox? No problem:&lt;/p&gt;


&lt;pre&gt;&lt;code class="javascript"&gt;
$('#mugshots li a').lightBox(); 
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;I used &lt;a href="http://leandrovieira.com/projects/jquery/lightbox/"&gt;that lightbox&lt;/a&gt; cause I had it configured for my previous rails apps, but pick your favourite one, as there are gazilions of them.&lt;/p&gt;


	&lt;p&gt;This is first step of tweaking our app. Javascript is in step1.js file: &lt;a href="http://mugshots.drogomir.com/js/step1/mugshots/new"&gt;mugshots.drogomir.com/js/step1/mugshots/new&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;What now? User can upload many files at one submit and see progress bar. What else do we need? Ajax! My preciousssss…&lt;/p&gt;


	&lt;p&gt;As all children know, XMLHttpRequest can’t upload files. What a shame… our new tweaked mugshots app is all about uploading files. Although you can’t do it with &lt;span class="caps"&gt;XHR&lt;/span&gt;, there is a way to imitate it. It is obtained by creating an iframe and uploading files to it.&lt;/p&gt;


	&lt;p&gt;Luckily Mike Malsup has done hard work for us writing &lt;a href="http://www.malsup.com/jquery/form/"&gt;jQuery form plugin&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;First, we need our form. I would place it instead “New mugshot” link. Link has id=”new_mugshot_link”, so this piece of code will replace it with form:&lt;/p&gt;


&lt;pre&gt;&lt;code class="javascript"&gt;
  /* create upload form with multifile instead of new mugshot link */
  var form = $('&amp;lt;form method="post" enctype="multipart/form-data" class="progress ajax" action="/mugshots"&amp;gt;');
  var label = $('&amp;lt;p&amp;gt;&amp;lt;label for="mugshot_uploaded_data"&amp;gt;Upload mugshot: &amp;lt;/label&amp;gt;&amp;lt;/p&amp;gt;');
  var input = $('&amp;lt;input type="file" class="multi-file" id="mugshot_uploaded_data" size="30" name="mugshot[uploaded_data]"/&amp;gt;');
  label.append(input).appendTo(form);
  form.append('&amp;lt;p&amp;gt;&amp;lt;input type="submit" value="Create" name="commit"/&amp;gt;&amp;lt;/p&amp;gt;');
  if (typeof(AUTH_TOKEN) != "undefined") form.append('&amp;lt;input type="hidden" value="'+AUTH_TOKEN+'" name="authenticity_token"/&amp;gt;'); 
  $('#new_mugshot_link').replaceWith(form);
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Our form has to be send to an iframe, so we have to apply ajaxForm to it. After replacing link with form we can’t figure out when form is actually appended to &lt;span class="caps"&gt;DOM&lt;/span&gt;. To be sure that form is there, we can use livequery. It will fire callback function when ‘form.ajax’ will be available:&lt;/p&gt;


&lt;pre&gt;&lt;code class="javascript"&gt;
  $('form.ajax').livequery(function() {
    $(this).ajaxForm({iframe: true, success: function (responseText, statusText, form) {
      var url = $(form).attr('action');
      /* get new files */
      $.ajax({
          url: url,
          dataType: "script",
          beforeSend: function(xhr) {xhr.setRequestHeader("Accept", "text/javascript");},
      /* we need to update lightbox array to include new files */
          complete: function() { $('#mugshots li a').lightBox(); }
      });
    }});
  });
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;When new form tag with class “ajax” will be available callback function will be run. iframe option tells form plugin to add hidden iframe (it will handle file upload).&lt;/p&gt;


	&lt;p&gt;The above code has ajax call to ”/mugshots” url which will run index.js.erb (RJS), so we will need one:&lt;/p&gt;


app/views/mugshots/index.js.erb
&lt;pre&gt;&lt;code class="ruby"&gt;
  jQuery('#mugshots').html(&amp;lt;%= js render(:partial =&amp;gt; 'mugshot', :collection =&amp;gt; @mugshots) %&amp;gt;);
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;to handle it we need to use respond_to:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;
  respond_to do |format|
    format.html
    # layout =&amp;gt; false is here beaceuse without it rails are looking
    # for layouts/index.js.erb
    format.js { render :layout =&amp;gt; false }
  end
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Normally I try not to use &lt;span class="caps"&gt;RJS&lt;/span&gt; to keep all my javascript (and ajax) logic in javascript files, but in case of images it isn’t so esay. I will write about it and about javascript templating systems in one of the next posts.&lt;/p&gt;


	&lt;p&gt;Take a look at: &lt;a href="http://mugshots.drogomir.com/js/step2/mugshots"&gt;mugshots.drogomir.com/js/step2/mugshots&lt;/a&gt; Doesn’t it look nice?&lt;/p&gt;


	&lt;p&gt;There is only one problem :) No ajax validation. After submitting files, javascript can’t get any info about errors or uploaded files beaceuse it is treated like normal html request and response is loaded in an iframe. How to fix it? I’ll write about it in the next post. :)&lt;/p&gt;
          </content>  <feedburner:origLink>http://drogomir.com/blog/2008/7/3/tweaking-rails-app-with-jquery-part-i</feedburner:origLink></entry>
  <entry xml:base="http://drogomir.com/blog/">
    <author>
      <name>drogus</name>
    </author>
    <id>tag:drogomir.com,2008-07-02:18</id>
    <published>2008-07-02T22:05:00Z</published>
    <updated>2008-07-02T22:42:03Z</updated>
    <category term="autotest" />
    <category term="knotify" />
    <category term="rspec" />
    <link href="http://feedproxy.google.com/~r/blog-drogomir/~3/ieS8vvbiKlw/autotest-and-knotify" rel="alternate" type="text/html" />
    <title>Autotest and KNotify</title>
<content type="html">
            &lt;p&gt;I’ve configured KNotify to work with &lt;a href="http://www.zenspider.com/ZSS/Products/ZenTest/"&gt;ZenTest&lt;/a&gt;. To see knotify messages just drop below code to ~/.autotest&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;
module KDENotify
 def self.span str, color
   "&amp;lt;span style=\"color: #{color}\"&amp;gt;#{str}&amp;lt;/span&amp;gt;" 
 end

 def self.notify title, msg, color
   system "dcop knotify default notify " +
          "eventname '#{span(title, color)}' '#{span(msg, color)}' '' '' 16 2" 
   end

 Autotest.add_hook :ran_command do |at|
   if at.results.split("\n").last.first =~ /([0-9]+\sexamples,\s([0-9]+)\sfailures?(,\s([0-9]+) pending)?)/
     message, failures, pending = $1, $2.to_i, $4.to_i
     if failures &amp;gt; 0
       notify "Tests failed", message, "darkred" 
     elsif pending &amp;gt; 0
       notify "Tests passed with some tests pending", message, "goldenrod" 
     else
       notify "Tests passed", message, "darkgreen" 
     end
   end
 end
end
&lt;/code&gt;&lt;/pre&gt;
          </content>  <feedburner:origLink>http://drogomir.com/blog/2008/7/2/autotest-and-knotify</feedburner:origLink></entry>
  <entry xml:base="http://drogomir.com/blog/">
    <author>
      <name>drogus</name>
    </author>
    <id>tag:drogomir.com,2008-06-30:17</id>
    <published>2008-06-30T12:14:00Z</published>
    <updated>2008-07-01T23:17:38Z</updated>
    <category term="javascript" />
    <category term="jquery" />
    <category term="progress" />
    <category term="safari" />
    <category term="upload" />
    <link href="http://feedproxy.google.com/~r/blog-drogomir/~3/-7hkcO-qCkk/upload-progress-script-with-safari-support" rel="alternate" type="text/html" />
    <title>Upload progress script with safari support</title>
<content type="html">
            Quick links:
	&lt;ul&gt;
	&lt;li&gt;Source on github for jquery version: &lt;a href="http://github.com/drogus/jquery-upload-progress"&gt;http://github.com/drogus/jquery-upload-progress&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;Source on github for prototype version: &lt;a href="http://github.com/drogus/prototype-upload-progress"&gt;http://github.com/drogus/prototype-upload-progress&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;jQuery demo: &lt;a href="http://drogomir.com/files/blog/jquery-upload-progress/example"&gt;http://drogomir.com/files/blog/jquery-upload-progress/example&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;Prototype demo: &lt;a href="http://drogomir.com/files/blog/prototype-upload-progress/example"&gt;http://drogomir.com/files/blog/prototype-upload-progress/example&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://drogomir.com/blog/2008/6/18/upload-progress-bar-with-mod_passenger-and-apache"&gt;Installing apache upload progress&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Recently I’ve wrote about &lt;a href="http://drogomir.com/blog/2008/6/18/upload-progress-bar-with-mod_passenger-and-apache"&gt;apache upload progress module&lt;/a&gt;. I work mainly on linux and I haven’t check my scripts on safari. It was working even on IE, what possibly could be harder to obtain? ;-) Some people reported that demo is not working on safari and Michele &lt;a href="http://drogomir.com/blog/2008/6/18/upload-progress-bar-with-mod_passenger-and-apache#comment-13"&gt;resolved the problem&lt;/a&gt; (thanks Michele :).&lt;/p&gt;


	&lt;p&gt;Solved! The only thing to do was to open WinXP on &lt;a href="http://www.virtualbox.org/"&gt;VirtualBox&lt;/a&gt; and check it on Safari 3. Michele’s solution worked well, but to make it work there must be html page with given structure and javascript. I like “one file” easy to use scripts without any issues with static files :) So what? Create an iframe dynamically, load scripts dynamically, one file, the only thing that user will have to set is path to scripts.&lt;/p&gt;


	&lt;p&gt;With Safari? No, not really. I’ve wrote it in a few minuttes and checked in firefox. It worked, great, now safari. Nope….&lt;/p&gt;


	&lt;p&gt;Although Safari have great &lt;span class="caps"&gt;CSS&lt;/span&gt; support, it is really terrible with Javascript. &lt;span class="caps"&gt;WYSIWYG&lt;/span&gt;, javascript history, ajax issues, now the upload progress and iframes. In edge case libraries I often see hacks for IE and safari mainly.&lt;/p&gt;


	&lt;p&gt;Luckily Apple released Windows version of safari and I can check my scripts and pages on safari. Good… developer tools don’t work, though… I had to do some alert-like IE style debugging ;-) After many hours of trying new more and more insane ways to create iframe and load scripts into it, code with document.write() worked!&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://github.com/drogus/jquery-upload-progress/commit/cc8ebce8acbb54febb3d24c7a77118c1501a922f"&gt;Check the commit on github&lt;/a&gt;. Lines 18-22 especially. And 28-line issue with safari not waiting to load previous script.&lt;/p&gt;


	&lt;p&gt;It’s really sad that after working on firefox with firebug or opera with developer tools I have to fight with Safari which is supposed to be modern browser. I know that on Mac developing scripts for safari is easier, thanks to working debug tools, but hey! I work on Linux. Why do I have to run Safari on Wine or VirtualBox, lacking debug tools? It’s a pain. I feel like I’m working on explorer…&lt;/p&gt;


	&lt;p&gt;&lt;del&gt;I will add prototype version&lt;/del&gt; and possibly some usage page shortly (for know look at the &lt;a href="http://drogomir.com/files/blog/jquery-upload-progress/example"&gt;demo code&lt;/a&gt;).&lt;/p&gt;
          </content>  <feedburner:origLink>http://drogomir.com/blog/2008/6/30/upload-progress-script-with-safari-support</feedburner:origLink></entry>
  <entry xml:base="http://drogomir.com/blog/">
    <author>
      <name>drogus</name>
    </author>
    <id>tag:drogomir.com,2008-06-18:2</id>
    <published>2008-06-18T21:18:00Z</published>
    <updated>2008-07-02T17:01:42Z</updated>
    <category term="apache" />
    <category term="javascript" />
    <category term="jquery" />
    <category term="merb" />
    <category term="mod_passenger" />
    <category term="nginx" />
    <category term="progress" />
    <category term="progressbar" />
    <category term="prototype" />
    <category term="raiils" />
    <category term="ruby" />
    <category term="upload" />
    <link href="http://feedproxy.google.com/~r/blog-drogomir/~3/kFIdMaZemac/upload-progress-bar-with-mod_passenger-and-apache" rel="alternate" type="text/html" />
    <title>Upload progress bar with mod_passenger and apache</title>
<content type="html">
            &lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;&lt;/strong&gt;: I found 2 bugs in upload progress module. If you have already installed. update to at least 0.1 version: &lt;a href="http://github.com/drogus/apache-upload-progress-module/commits/0.1"&gt;http://github.com/drogus/apache-upload-progress-module/commits/0.1&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;I’ve installed &lt;a href="http://www.modrails.com/"&gt;mod passenger&lt;/a&gt; on my server recently. It’s really great software. Now I don’t have to worry about monitoring, nginx proxy, load balancing, big file uploads… and it’s fast! With &lt;a href="http://www.rubyenterpriseedition.com/"&gt;Ruby Enterprise Edition&lt;/a&gt; it’s even faster.&lt;/p&gt;


	&lt;p&gt;Personally I don’t care about people saying that phusion wants to &lt;a href="http://judofyr.net/posts/ruby-fishy-edition.html"&gt;promote themselves on &lt;span class="caps"&gt;REE&lt;/span&gt;&lt;/a&gt; as long as it gives faster ruby with lower memory use (but yes, I know, &lt;span class="caps"&gt;REE&lt;/span&gt; is not best choice for a name :).&lt;/p&gt;


	&lt;p&gt;After installing I’ve realised that my shiny upload progress bar (thanks to &lt;a href="http://wiki.codemongers.com/NginxHttpUploadProgressModule"&gt;Upload Progress Module for nginx&lt;/a&gt;) was not working. Oh gods! What a tragedy!&lt;/p&gt;


	&lt;p&gt;But fear not. I’ve written &lt;a href="http://github.com/drogus/apache-upload-progress-module/tree/master"&gt;apache upload progress module&lt;/a&gt; to have my lovely progress bar back again. As a lazy developer I’ve implemented reports in the same way as in nginx upload progress, so my applications are working without changing any signle line of code. If you were using nginx upload progress just drop the module, change your config and you’re good to go :)&lt;/p&gt;


	&lt;p&gt;I’m testing it in one of my production servers, but be carefull – it’s not well tested in other enviroments (i have gentoo with apache 2.2.8). Any feedback will be helpfull. Give me a note in comments if you encounter any problems.&lt;/p&gt;


	&lt;p&gt;So you want to be cool and have your own sexy progress bar in your app? Keep reading ;)&lt;/p&gt;


To install module you must download it using git:
&lt;pre&gt;&lt;code class="console"&gt;git clone git://github.com/drogus/apache-upload-progress-module.git&lt;/code&gt;&lt;/pre&gt;
or get the package: &lt;a href="http://github.com/drogus/apache-upload-progress-module/tarball/master"&gt;http://github.com/drogus/apache-upload-progress-module/tarball/master&lt;/a&gt;

To compile/install/activate you have to use apxs2:
&lt;pre&gt;&lt;code class="console"&gt;apxs2 -c -i -a mod_upload_progress.c&lt;/code&gt;&lt;/pre&gt;

	&lt;ul&gt;
	&lt;li&gt;-c is for compiling&lt;/li&gt;
		&lt;li&gt;-i is for installing (copy mod_upload_progress.so to apache library dir)&lt;/li&gt;
		&lt;li&gt;-a is for activating (add LoadModule option into your apache conf file)&lt;/li&gt;
	&lt;/ul&gt;


If you want to install and activate run this command as a root. Otherwise you can just compile and add LoadModule to apache conf:
&lt;pre&gt;&lt;code class="config"&gt;LoadModule upload_progress_module path/to/apache-upload-progress-module/.libs/mod_upload_progress.so&lt;/code&gt;&lt;/pre&gt;

Currently there is only one global option:
&lt;pre&gt;&lt;code class="config"&gt;UploadProgressSharedMemorySize 1024000&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This sets shared memory size to  1M. By default it’s 100kB.&lt;/p&gt;


To add tracking and reporting upload for a virtual host in apache you will need to add:
&lt;pre&gt;&lt;code class="config"&gt;
&amp;lt;Location /&amp;gt;
    # enable tracking uploads in /
    TrackUploads On
&amp;lt;/Location&amp;gt;

&amp;lt;Location /progress&amp;gt;
    # enable upload progress reports in /progress
    ReportUploads On
&amp;lt;/Location&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now all uploads will be tracked and reports are under /progress&lt;/p&gt;


	&lt;p&gt;Format of the report is &lt;span class="caps"&gt;JSON&lt;/span&gt;. From nginx wiki:&lt;/p&gt;


&lt;blockquote&gt;
The returned document is a &lt;span class="caps"&gt;JSON&lt;/span&gt; text with the possible 4 results:

	&lt;ul&gt;
	&lt;li&gt;the upload request hasn’t been registered yet or is unknown:&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;new Object({ ‘state’ : ‘starting’ })&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;the upload request has ended:&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;new Object({ ‘state’ : ‘done’ })&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;the upload request generated an &lt;span class="caps"&gt;HTTP&lt;/span&gt; error:&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;new Object({ ‘state’ : ‘error’, ‘status’ : &amp;lt;error&gt; })&lt;/p&gt;


	&lt;p&gt;One error code that is interesting to track for clients is &lt;span class="caps"&gt;HTTP&lt;/span&gt; error 413 (Request entity too large)&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;the upload request is in progress:&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;new Object({ ‘state’ : ‘uploading’, ‘received’ : &amp;lt;size_received&gt;, ‘size’ : &amp;lt;total_size&gt;})&lt;/p&gt;


	&lt;p&gt;The &lt;span class="caps"&gt;HTTP&lt;/span&gt; request to this location must have either an X-Progress-ID parameter or X-Progress-ID &lt;span class="caps"&gt;HTTP&lt;/span&gt; header containing the unique identifier as specified in your upload/POST request to the relevant tracked zone. If you are using the X-Progress-ID as a query-string parameter, ensure it is the &lt;span class="caps"&gt;LAST&lt;/span&gt; argument in the &lt;span class="caps"&gt;URL&lt;/span&gt;.&lt;/blockquote&gt;&lt;/p&gt;


	&lt;p&gt;Now the last thing to do is to implement progress bar. I don’t like repeating others and &lt;a href="http://blog.new-bamboo.co.uk/2007/11/23/upload-progress-with-nginx"&gt;there is great tutorial on setting up upload progress bar with nginx and merb&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;&lt;/strong&gt;: I released jquery upload progress library with Safari 3 support. More info &lt;a href="http://drogomir.com/blog/2008/6/30/upload-progress-script-with-safari-support"&gt;here&lt;/a&gt;.
&lt;strong&gt;&lt;span class="caps"&gt;UPDATE2&lt;/span&gt;&lt;/strong&gt;: I’ve upgraded prototype version to work in Safari.&lt;/p&gt;


	&lt;p&gt;It’s for merb and nginx but if you drop the scripts in your rails app and with apache-upload-progress-module it will work. :) Basically if you have your own code handling uploads (for example using attachment_fu) you can just add javascript and css – it’s unobtrusive.&lt;/p&gt;


	&lt;p&gt;If you’re using prototype I’ve rewritten script and made &lt;a href="http://drogomir.com/files/blog/prototype-upload-progress/example"&gt;a demo&lt;/a&gt;. &lt;a href="http://drogomir.com/files/blog/prototype-upload-progress/"&gt;You can also grab files&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;I hope you enjoy this article. Progress bar is in my opinion one of the most useful technics – there is nothing more annoying than large file uploading without any info on state of an upload.&lt;/p&gt;
          </content>  <feedburner:origLink>http://drogomir.com/blog/2008/6/18/upload-progress-bar-with-mod_passenger-and-apache</feedburner:origLink></entry>
</feed>
