<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-23214170</id><updated>2024-09-08T21:32:10.773+10:00</updated><category term="ruby"/><category term="c#"/><category term="codeigniter"/><category term="doctrine"/><category term="rails"/><category term="PHP"/><category term="ajax"/><category term="development"/><category term="dtmf"/><category term="git"/><category term="pcm"/><category term="sinatra"/><category term="wave"/><category term="Cloud computing"/><category term="EC2"/><category term="IE"/><category term="ISO_3166-1"/><category term="S3"/><category term="asp.net"/><category term="backbone.js"/><category term="bdd"/><category term="bisect"/><category term="broken tests"/><category term="client side MVC"/><category term="code"/><category term="coffeescript"/><category term="compilation"/><category term="countries"/><category term="execution"/><category term="ext"/><category term="extjs"/><category term="filters"/><category term="formatters"/><category term="gems"/><category term="google"/><category term="google ajax crawling scheme"/><category term="google api"/><category term="google places"/><category term="javascript"/><category term="layouts"/><category term="linux"/><category term="mvc"/><category term="nested properties"/><category term="orm"/><category term="pinvoke"/><category term="popen"/><category term="proc_open"/><category term="profile"/><category term="redux"/><category term="sampling"/><category term="sass"/><category term="script"/><category term="search engines"/><category term="shell"/><category term="tdd"/><category term="transactions"/><category term="ubuntu"/><category term="unit testing"/><category term="web"/><category term="windows"/><title type='text'>The Code Abode</title><subtitle type='html'>All things code from Ruby to PHP, C#, Backbone.JS and Coffeescript</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>30</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-23214170.post-997480790909917521</id><published>2014-02-25T07:32:00.001+10:00</published><updated>2014-02-25T07:43:57.200+10:00</updated><title type='text'>Why you shouldn&#39;t choose Spine.JS</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
This is really for my own benefit... something to remind me of the reasons why I shouldn&#39;t ever choose Spine.JS over other client side MVC frameworks. Shoot me a comment if you&#39;d like to add to this list.... In order of importance:&lt;br /&gt;
&lt;br /&gt;
&lt;ol style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;Its Backbone&#39;s red headed stepchild. Just chose Backbone&lt;/li&gt;
&lt;li&gt;Their AJAX mixin to models sucks. It relies on events thrown from globally accessible objects, rather than callbacks and / or promises to complete async actions. This introduces a layer of indirection, and potentially messy code. In small apps, this could be acceptable, but not for larger apps.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Configuring URLs to retrieve model information is strongly opinionated, and difficult to override. REST principles are enforced, an any deviation from these are problematic. Should a model be loadable from multiple urls (i.e. Person model list loaded from http://my-app/friends, and http://my-app/friends/1/friends), there is no easy way to implement this contextual switching without implementing your own ajax module.&lt;/li&gt;
&lt;li&gt;Its collection helpers (i.e. find, all, fetch, select etc.) clone models before returning, which can be very cumbersome as the model you have retrieved is not the same as the one you set. Adding models to the cache is also annoying, as a call to save() is required. However, in calling this, a bunch of logic gets executed that you might not want to be executed, such as the assigning of an id, or throwing of &#39;create&#39;, &#39;save&#39; events etc. Quite often you just want your models to be stored in an accessible collection in the state that they are in. Its probably better to do this in your own managed collection, rather than via Spine&#39;s cache. So really - whats the point of them?&lt;/li&gt;
&lt;li&gt;Due to this cloning, the models are cumbersome. Every property added to a model must be declared as an attribute or configured.&lt;/li&gt;
&lt;li&gt;It uses global collection helpers, and caches (i.e. MyModel.all). This sounds wonderful, and on small apps its handy. But for a sizeable app, this can get nasty as if the developer is not careful it implicitly introduces an unwanted level of state into your application.&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/997480790909917521/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/997480790909917521?isPopup=true' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/997480790909917521'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/997480790909917521'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2014/02/why-you-shouldnt-choose-spinejs.html' title='Why you shouldn&#39;t choose Spine.JS'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-3968902415343802228</id><published>2013-05-25T14:20:00.002+10:00</published><updated>2013-06-24T17:21:40.598+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="bdd"/><category scheme="http://www.blogger.com/atom/ns#" term="bisect"/><category scheme="http://www.blogger.com/atom/ns#" term="broken tests"/><category scheme="http://www.blogger.com/atom/ns#" term="git"/><category scheme="http://www.blogger.com/atom/ns#" term="tdd"/><title type='text'>Git Bisect: Find the commit that broke my tests</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;br /&gt;
So master is broken and you don&#39;t know which commit contains the offending code....&lt;br /&gt;
&lt;br /&gt;
Git bisect is an amazing tool. It allows you to flag which commit was the last green state, and automatically iterate over each subsequent commit, running a script (i.e. your tests) until it finds the breaking commit....&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
i.e.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;

&lt;pre class=&#39;code&#39;&gt;
git bisect start [some-breaking-commit-sha] [last-good-commit-sha]
git bisect run [test-command]
&lt;/pre&gt;

&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
a working example using rspec:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&#39;code&#39;&gt;
git bisect start 120cba5 c2d0a5e
git bisect run rspec spec/mytest_spec:123
&lt;/pre&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/3968902415343802228/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/3968902415343802228?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/3968902415343802228'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/3968902415343802228'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2013/05/git-bisect-find-commit-that-broke-my.html' title='Git Bisect: Find the commit that broke my tests'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-3156342986362916379</id><published>2013-04-21T15:31:00.002+10:00</published><updated>2013-06-24T17:22:26.800+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="git"/><title type='text'>Git: patching diffs between branches</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;br /&gt;
Recently I accidentally committed changes to master that I want to commit in a feature branch..... I made the mistake of&lt;br /&gt;
&lt;br /&gt;
&lt;ol style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;branching master (to a feature branch) from my erroneous commit - then&lt;/li&gt;
&lt;li&gt;resetting (HARD) master to the previous commit&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
This axed all my history in my feature branch as the commit which I branched from in master no longer existed....&lt;br /&gt;
&lt;br /&gt;
To fix I had to create a new feature branch from master, then create a patch of the differences between my original feature branch and master doing the following:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&#39;code&#39;&gt;
git checkout master
git checkout -b [new_feature_branch]
git diff --no-prefix origin/[busted_feature_branch] &gt; my.patch
&lt;/pre&gt;
&lt;br /&gt;
then apply the patch:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&#39;code&#39;&gt;patch -p0 &lt; my.patch
&lt;/pre&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/3156342986362916379/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/3156342986362916379?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/3156342986362916379'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/3156342986362916379'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2013/04/git-patching-diffs-between-branches.html' title='Git: patching diffs between branches'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-5266238344275382720</id><published>2013-04-13T00:32:00.001+10:00</published><updated>2013-06-24T17:22:47.171+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="formatters"/><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><category scheme="http://www.blogger.com/atom/ns#" term="nested properties"/><title type='text'>Javascript: Safely reading a nested property</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;br /&gt;
In some templating frameworks it can be really annoying reading a nested property of a JS object as it can of mean chaining a heap of null checks together....&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
for instance if I need to access a nested property &#39;to&#39; in &#39;email.addresses.to&#39; safely it means having to do something like:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&#39;code&#39;&gt;if(email &amp;amp;&amp;amp; (adresses = email.addresses)) {
  //print addresses.to
}
&lt;/pre&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
This is verbose and annoying. I needed a function that would return the nested value, or simply return an empty string if any property in the chain was null or undefined&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
i.e.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&#39;code&#39;&gt;safeRead(email, &#39;addresses&#39;, &#39;to&#39;);&lt;/pre&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I also wanted property chains can be as long or short as I&#39;d like.... ie.:&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&#39;code&#39;&gt;safeRead(my, &#39;very&#39;, &#39;deeply&#39;, &#39;nested&#39;, &#39;property&#39;);&lt;/pre&gt;
&lt;div&gt;
&lt;br /&gt;
The finished product:&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;script src=&quot;https://gist.github.com/benkitzelman/5372419.js&quot;&gt;&lt;/script&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/5266238344275382720/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/5266238344275382720?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/5266238344275382720'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/5266238344275382720'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2013/04/javascript-safely-reading-nested.html' title='Javascript: Safely reading a nested property'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-2068172778023632126</id><published>2013-04-11T21:14:00.000+10:00</published><updated>2013-04-11T21:28:16.116+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ajax"/><category scheme="http://www.blogger.com/atom/ns#" term="IE"/><category scheme="http://www.blogger.com/atom/ns#" term="rails"/><category scheme="http://www.blogger.com/atom/ns#" term="ruby"/><category scheme="http://www.blogger.com/atom/ns#" term="sinatra"/><title type='text'>IE Ajax requests returning 401 Unauthorized in Rails / Sinatra</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Here&#39;s a quick little nugget of info for any devs experiencing ajax issues in IE....&lt;br /&gt;
&lt;br /&gt;
Firstly, earlier ( &amp;lt;= IE 8) versions of IE cache everything ajax, and it can be a pain to resolve without compromising (breaking through) server side cache.... I wrote an article &lt;a href=&quot;http://thecodeabode.blogspot.com.au/2010/10/cache-busting-ajax-requests-in-ie.html&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt; about that...&lt;br /&gt;
&lt;br /&gt;
To add another drop to the ocean of pain that is IE, I found that on Windows 7 (and windows 7 only), IE7, IE8 and IE9, all AJAX requests were consistently returning 401 Unauthorized statuses. After much mining through code and system settings etc., a workmate and I discovered that in Windows 7, all ajax requests send an uppercase ACCEPT_LANGUAGE header, whereas regular synchronous requests send a lowercase one.....&lt;br /&gt;
&lt;br /&gt;
This may seem inconsequential, but for those developing a rack based app using rack-protection, this is enough to trip the session-hijacking check, which compares this header with previous requests (&lt;a href=&quot;https://github.com/rkh/rack-protection/blob/master/lib/rack/protection/session_hijacking.rb#L23&quot; target=&quot;_blank&quot;&gt;https://github.com/rkh/rack-protection/blob/master/lib/rack/protection/session_hijacking.rb#L23&lt;/a&gt;) ...&lt;br /&gt;
&lt;br /&gt;
As the case is different the equality check fails, resulting in rack-protection blocking the call and returning 401 Unauthorized.&lt;br /&gt;
&lt;br /&gt;
Not a fun bug.&lt;br /&gt;
&lt;br /&gt;
The solution is to either downcase the header client side for all ajax requests (i.e. $.ajaxSetup), or introduce some custom middleware before rack-protection that downcases the offending header before rack-protection checks it.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/2068172778023632126/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/2068172778023632126?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/2068172778023632126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/2068172778023632126'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2013/04/ie-ajax-requests-returning-401.html' title='IE Ajax requests returning 401 Unauthorized in Rails / Sinatra'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-7701757034140620449</id><published>2013-03-26T21:20:00.003+10:00</published><updated>2013-06-29T12:44:31.700+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ajax"/><category scheme="http://www.blogger.com/atom/ns#" term="backbone.js"/><category scheme="http://www.blogger.com/atom/ns#" term="client side MVC"/><category scheme="http://www.blogger.com/atom/ns#" term="google ajax crawling scheme"/><category scheme="http://www.blogger.com/atom/ns#" term="search engines"/><title type='text'>Backbone.JS and SEO: Google Ajax Crawling Scheme</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;br /&gt;
&lt;div class=&quot;p1&quot;&gt;
Most search engines hate client side MVC, but luckily there&#39;s a few tools around to get your client side routes indexed.&lt;/div&gt;
&lt;div class=&quot;p1&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p1&quot;&gt;
As most web bots (i.e. Google and others) don&#39;t interpret javascript on the fly, they fail to parse &amp;nbsp; javascript rendered content for indexing. To overcome this, Google (and now Bing) support the &#39;Google Ajax Crawling Scheme&#39; (&lt;a href=&quot;https://developers.google.com/webmasters/ajax-crawling/docs/getting-started&quot;&gt;&lt;span class=&quot;s1&quot;&gt;https://developers.google.com/webmasters/ajax-crawling/docs/getting-started&lt;/span&gt;&lt;/a&gt;) - which basically states that IF you want js rendered DOM content to be indexed (i.e. rendering ajax call results), you must be able to:&lt;/div&gt;
&lt;ol class=&quot;ol1&quot;&gt;
&lt;li class=&quot;li2&quot;&gt;Trigger a page state (javascript rendering) via the url using hashbangs &lt;span class=&quot;s2&quot;&gt;#!&lt;/span&gt; (i.e.&lt;span class=&quot;s2&quot;&gt;http://www.mysite.com/#!my-state&lt;/span&gt;), and&lt;/li&gt;
&lt;li class=&quot;li2&quot;&gt;Be able to serve a rendered dom snapshot of your site AFTER javascript modification on request.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;p1&quot;&gt;
If using a client side MVC framework like Backbone.js, or simply have a javascript heavy page, and wish to get its various states indexed - you will need to provide this dom snapshotting service server side if you want your web app indexed. Typically this is done using a headless browser (i.e. QT, PhantomJS, Zombie.JS, HtmlUnit).&lt;/div&gt;
&lt;div class=&quot;p1&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p1&quot;&gt;
For those using ruby server side, there&#39;s a gem which already handles this called google_ajax_crawler available on rubygems.&lt;/div&gt;
&lt;div class=&quot;p1&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p1&quot;&gt;
&lt;pre class=&quot;code&quot;&gt;gem install google_ajax_crawler&lt;/pre&gt;
&lt;/div&gt;

&lt;br /&gt;

&lt;div class=&quot;p4&quot;&gt;
&lt;span class=&quot;s3&quot;&gt;source available on my github (&lt;a href=&quot;https://github.com/benkitzelman/google-ajax-crawler&quot;&gt;https://github.com/benkitzelman/google-ajax-crawler&lt;/a&gt;&lt;/span&gt;)&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p1&quot;&gt;
Its used as rack middleware and essentially intercepts a request made by a web bot adhering to the scheme, and scrapes your site server side then delivers the rendered dom back to the requesting bot as a snapshot.&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;p1&quot;&gt;
&lt;br /&gt;
A simple rack app example demonstrating how to configure and use the gem:&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;

&lt;script src=&quot;https://gist.github.com/benkitzelman/5309967.js&quot;&gt;&lt;/script&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/7701757034140620449/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/7701757034140620449?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/7701757034140620449'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/7701757034140620449'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2013/03/backbonejs-and-seo-google-ajax-crawling.html' title='Backbone.JS and SEO: Google Ajax Crawling Scheme'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-2624119698630280322</id><published>2012-12-12T15:47:00.000+10:00</published><updated>2013-06-26T22:21:01.117+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="coffeescript"/><category scheme="http://www.blogger.com/atom/ns#" term="compilation"/><category scheme="http://www.blogger.com/atom/ns#" term="gems"/><category scheme="http://www.blogger.com/atom/ns#" term="sass"/><category scheme="http://www.blogger.com/atom/ns#" term="sinatra"/><title type='text'>Sinatra Asset Snack: Coffeescript and SASS compilation for Sinatra</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Up until recently most of my RIAs have been built using Backbone.JS and Sinatra, using the Sinatra Assetpack gem to handle asset compilation and pipelining. Unfortunately recently I found some performance issues with Sinatra Assetpack.&lt;br /&gt;
&lt;br /&gt;
Generally speaking its great at managing coffeescript and SASS compilation and minification on the fly, however I was finding that as my codebase grew, each time I fired up a server in development, it was taking way to long to clear its cache, recompile and load a page. This was a real drag when working on UX, as this recompilation time made development slow and clunky. I was also finding that even after warming its asset cache, the serving of these assets via assetpack on development and test environments was really preventing quick page loads and was starting to become annoying.&lt;br /&gt;
&lt;br /&gt;
In response, I wrote a simple gem to slim down the asset serving codebase, and handle runtime compilation of coffeescript and SASS in a faster fashion. Its released on RubyGems:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;code&quot;&gt;gem install sinatra-asset-snack
&lt;/pre&gt;
&lt;br /&gt;
At the moment it handles only SASS and Coffeescript compilation, and allows you to designate script bundling into common files (i.e. application.js). For example:&lt;br /&gt;
&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/benkitzelman/5309877.js&quot;&gt;&lt;/script&gt;
Minification isn&#39;t handled yet, mainly as most sites (should) use g-zip compression anyway which means minification is largely a secondary / unnecessary concern anyway.&lt;br /&gt;
&lt;br /&gt;
Should anyone want to write any additional compilers for other syntaxes feel free! The code can be found at&lt;a href=&quot;https://github.com/benkitzelman/sinatra-asset-snack&quot; target=&quot;_blank&quot;&gt;&amp;nbsp;https://github.com/benkitzelman/sinatra-asset-snack&lt;/a&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/2624119698630280322/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/2624119698630280322?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/2624119698630280322'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/2624119698630280322'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2013/03/sinatra-asset-snack-coffeescript-and.html' title='Sinatra Asset Snack: Coffeescript and SASS compilation for Sinatra'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-5504539206777031101</id><published>2012-11-05T15:32:00.001+10:00</published><updated>2013-06-24T17:24:07.157+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Cloud computing"/><category scheme="http://www.blogger.com/atom/ns#" term="EC2"/><category scheme="http://www.blogger.com/atom/ns#" term="S3"/><category scheme="http://www.blogger.com/atom/ns#" term="ubuntu"/><title type='text'>S3FS: Mounting an S3 Bucket in Ubuntu</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;br /&gt;
Recently I had an app on EC2 that needed to manage files in an S3 bucket. Normally I would use a gem to handle the uploading etc., but I figured I would give s3fs a crack.&lt;br /&gt;
&lt;br /&gt;
Essentially s3fs allows you to mount an S3 bucket as an external file system, allowing you to manage files transparently as part of the OS.&lt;br /&gt;
&lt;br /&gt;
It was relatively simple to get it working on an EC2 instance running Ubuntu 10.04.3 LTS&lt;br /&gt;
&lt;br /&gt;
&lt;h4 style=&quot;text-align: left;&quot;&gt;
OVERVIEW:&lt;/h4&gt;
&amp;nbsp;- install the dependencies&lt;br /&gt;
&amp;nbsp;- install s3fs&lt;br /&gt;
&amp;nbsp;- create the password file&lt;br /&gt;
&amp;nbsp;- add the s3 bucket to fstab&lt;br /&gt;
&amp;nbsp;- mount and symlink to deployment dir&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Installing Dependencies:&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&#39;code&#39;&gt;$ sudo apt-get install build-essential libfuse-dev fuse-utils libcurl4-openssl-dev libxml2-dev mime-support
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Install Fuse 2.8.4:&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&#39;code&#39;&gt;$ wget http://sourceforge.net/projects/fuse/files/fuse-2.X/2.8.4/fuse-2.8.4.tar.gz/download -O fuse-2.8.4.tar.gz
$ tar xvzf fuse-2.8.4.tar.gz
$ cd fuse-2.8.4
$ ./configure --prefix=/usr
$ make
$ sudo make install
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Install S3FS:&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&#39;code&#39;&gt;$ wget http://s3fs.googlecode.com/files/s3fs-1.61.tar.gz
$ tar xvzf s3fs-1.61.tar.gz
$ cd s3fs-1.61/
$ ./configure --prefix=/usr
$ make
$ sudo make install
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Create /etc/passwd-s3fs:&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&#39;code&#39;&gt;$ sudo vim /etc/passwd-s3fs
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;Populate it with&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&#39;code&#39;&gt;[your_aws_access_id]:[your_aws_secret]
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;Change permissions:&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&#39;code&#39;&gt;$ sudo chmod 640 /etc/passwd-s3fs
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;Add Mount Point:&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&#39;code&#39;&gt;$ sudo mkdir /mnt/bucket
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;Add to FSTAB:&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&#39;code&#39;&gt;s3fs#[bucket-name] /mnt/bucket fuse netdev,default_acl=public-read,use_cache=/tmp,use_rrs=1,allow_other 0 0
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;Symlink to Mount Point:&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&#39;code&#39;&gt;$ ln -s /mnt/bucket /[deployed_app_path]/public
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;FYI ONCE OFF MOUNT COMMAND CMD:&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&#39;code&#39;&gt;$ AWSACCESSKEYID=[your_aws_access_id] AWSSECRETACCESSKEY=[your_aws_secret] sudo /usr/bin/s3fs [bucket-name] /mnt/bucket -odefault_acl=public-read&lt;/pre&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/5504539206777031101/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/5504539206777031101?isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/5504539206777031101'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/5504539206777031101'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2012/11/s3fs-mounting-s3-on-ec2-instance.html' title='S3FS: Mounting an S3 Bucket in Ubuntu'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-3595053726942996211</id><published>2012-07-20T12:43:00.000+10:00</published><updated>2013-02-24T22:39:06.714+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="countries"/><category scheme="http://www.blogger.com/atom/ns#" term="ISO_3166-1"/><category scheme="http://www.blogger.com/atom/ns#" term="ruby"/><title type='text'>3 Character to 2 Character Country Codes</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
For anyone else who needs to map 3 character to 2 character country codes in ruby, I have provided the following class based on the ISO_3166-1 country code list found at&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/ISO_3166-1#Current_codes&quot;&gt;http://en.wikipedia.org/wiki/ISO_3166-1#Current_codes&lt;/a&gt;&lt;br /&gt;

&lt;script src=&quot;https://gist.github.com/benkitzelman/5023666.js&quot;&gt;&lt;/script&gt;

&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/3595053726942996211/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/3595053726942996211?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/3595053726942996211'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/3595053726942996211'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2012/07/3-character-to-2-character-country-codes.html' title='3 Character to 2 Character Country Codes'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-4844256483306124317</id><published>2012-07-14T14:00:00.000+10:00</published><updated>2013-06-26T22:22:01.681+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="code"/><category scheme="http://www.blogger.com/atom/ns#" term="development"/><category scheme="http://www.blogger.com/atom/ns#" term="google"/><category scheme="http://www.blogger.com/atom/ns#" term="google api"/><category scheme="http://www.blogger.com/atom/ns#" term="google places"/><category scheme="http://www.blogger.com/atom/ns#" term="ruby"/><category scheme="http://www.blogger.com/atom/ns#" term="web"/><title type='text'>Google-api-client Authorizing with an API Key in Ruby</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div class=&quot;p1&quot;&gt;
The documentation for the Google RESTful APIs is generally pretty good, however when playing with the google-api-client ruby gem, developed by Google to trawl their APIs, I ran into a few issues, particularly when authenticating using an api key (rather than OAuth).&lt;br /&gt;
&lt;br /&gt;
After installing the google-api-client gem, getting a Google API Key (&lt;a href=&quot;https://code.google.com/apis/console/&quot;&gt;https://code.google.com/apis/console/&lt;/a&gt;), and setting up a custom search account (with its prefs widened to all web pages - &lt;a href=&quot;http://www.google.com/cse/&quot;&gt;http://www.google.com/cse/&lt;/a&gt;)....&lt;br /&gt;
&lt;br /&gt;
The following allowed me to trawl google search results (copy paste into irb, then inspect response when finished):
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&quot;code&quot;&gt;  require &#39;openssl&#39;
  OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE

  require &#39;google/api_client&#39;
  client = Google::APIClient.new(:key =&amp;gt; &#39;your-api-key&#39;, :authorization =&amp;gt; nil)
  search = client.discovered_api(&#39;customsearch&#39;)

  response = client.execute(
    :api_method =&amp;gt; search.cse.list,
    :parameters =&amp;gt; {
      &#39;q&#39; =&amp;gt; &#39;the hoff&#39;,
      &#39;key&#39; =&amp;gt; &#39;your-api-key&#39;,
      &#39;cx&#39; =&amp;gt; &#39;your-custom-search-id&#39;
    }
  )
&lt;/pre&gt;
&lt;div class=&quot;p1&quot;&gt;
&lt;br /&gt;
&lt;b&gt;THE MOST IMPORTANT BIT&lt;/b&gt; was the :authorization param when constructing he client.... this ensures the api key is used when calling, in preference to oauth. Without it you will get 401 Unauthorized response status everytime.&lt;/div&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/4844256483306124317/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/4844256483306124317?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/4844256483306124317'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/4844256483306124317'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2012/07/google-api-ruby-client-authorizing-with.html' title='Google-api-client Authorizing with an API Key in Ruby'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-9046616270906175046</id><published>2012-07-12T17:47:00.002+10:00</published><updated>2013-06-26T22:22:41.142+10:00</updated><title type='text'>ERROR 1045 (28000): Access denied for user &#39;root&#39;@&#39;localhost&#39; (using password: YES)</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Somehow my root account lost its &#39;ALL PRIVILEGES&#39; option, and instead was listing all individual privileges when running&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;code&quot;&gt;
show grants;
&lt;/pre&gt;
&lt;br /&gt;
As root instead of:&lt;br /&gt;
&lt;pre class=&quot;code&quot;&gt;+----------------------------------------------------------------------------------------------------------------------------------------+
| Grants for root@localhost                                                                                                              |
+----------------------------------------------------------------------------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO &#39;root&#39;@&#39;localhost&#39; IDENTIFIED BY PASSWORD &#39;*76854B38A7923CC05E7857229F508E66E89D69AD&#39; WITH GRANT OPTION |
+----------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
&lt;/pre&gt;
&lt;br /&gt;
This was preventing me from assigning all privileges to *.* to other users....&lt;br /&gt;
The solution for me (in OSX 10.6.8) was to run in terminal:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;code&quot;&gt;mysql_upgrade
&lt;/pre&gt;
&lt;br /&gt;
which rebuilt my grants table, then after logging into mysql as root, retrying the grant cmd:&lt;br /&gt;
&lt;pre class=&quot;code&quot;&gt;GRANT ALL PRIVILEGES ON *.* TO &#39;myuser&#39;@&#39;localhost&#39;
&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/9046616270906175046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/9046616270906175046?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/9046616270906175046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/9046616270906175046'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2012/07/error-1045-28000-access-denied-for-user.html' title='ERROR 1045 (28000): Access denied for user &#39;root&#39;@&#39;localhost&#39; (using password: YES)'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-5286834571529478229</id><published>2012-06-11T13:12:00.000+10:00</published><updated>2012-07-01T21:19:29.152+10:00</updated><title type='text'>Sinatra, BackboneJS and CoffeeScript Bootstrap</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Just a quick post.... For those who want a quick way to kickstart a ruby / backbonejs app, and maybe do it &amp;nbsp;in Coffeescript, I added a real basic Bootstrap / project starter to my github account (&lt;a href=&quot;https://github.com/benkitzelman/sinatra-backbone-bootstrap&quot;&gt;https://github.com/benkitzelman/sinatra-backbone-bootstrap&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
It also integrates Jasmine allowing JS tests to also be written in Coffeescript, which is nice :)&lt;br /&gt;
&lt;br /&gt;
It uses the following tech stack:&lt;br /&gt;
&lt;h3&gt;
GEMS&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Sinatra&lt;/li&gt;
&lt;li&gt;Sinatra-assetpack&lt;/li&gt;
&lt;li&gt;Coffee-Script&lt;/li&gt;
&lt;li&gt;SASS&lt;/li&gt;
&lt;li&gt;Jasmine&lt;/li&gt;
&lt;li&gt;Thin&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
JS LIBS&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Modernizr 2.5.3&lt;/li&gt;
&lt;li&gt;BackboneJS 0.9.2&lt;/li&gt;
&lt;li&gt;UnderscoreJS 1.3.3&lt;/li&gt;
&lt;li&gt;JQuery 1.7.2&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
CSS FRAMEWORK&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Skeleton 1.1&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/5286834571529478229/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/5286834571529478229?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/5286834571529478229'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/5286834571529478229'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2012/06/sinatra-backbonejs-and-coffeescript.html' title='Sinatra, BackboneJS and CoffeeScript Bootstrap'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-3212095664368907577</id><published>2011-01-18T08:45:00.003+10:00</published><updated>2013-06-24T17:24:48.766+10:00</updated><title type='text'>Detect the Adobe Reader Plugin</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Recently I had to be able to detect the Adobe Reader Plugin in Javascript. I have included the code I used to flag if the Adobe Reader Plugin is installed, as well as get the version of the current adobe reader plugin. This code will detect:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Adobe Reader Plugin for Firefox&lt;/li&gt;
&lt;li&gt;Adobe Reader Plugin for IE ( &amp;lt;5 and 5+)&lt;/li&gt;
&lt;li&gt;Adobe Reader Plugin for Chrome and&lt;/li&gt;
&lt;li&gt;WebKit PDF Reader for Safari&lt;/li&gt;
&lt;li&gt;The PDF Reader for Chrome (Chrome&#39;s default alternative to the&amp;nbsp;Adobe Reader Plugin)&lt;/li&gt;
&lt;li&gt;Adobe Reader Plugin for most other browsers&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;b&gt;To call it in javascript:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&#39;code&#39;&gt;
var info = getAcrobatInfo();
alert(info.browser+ &quot; &quot; + info.acrobat + &quot; &quot; + info.acrobatVersion);
&lt;/pre&gt;
&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/benkitzelman/6d4ead05b3d4b80518f3.js&quot;&gt;&lt;/script&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/3212095664368907577/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/3212095664368907577?isPopup=true' title='21 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/3212095664368907577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/3212095664368907577'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2011/01/detect-adobe-reader-plugin.html' title='Detect the Adobe Reader Plugin'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>21</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-6307836527963592513</id><published>2010-12-01T11:36:00.003+10:00</published><updated>2013-06-26T22:23:25.544+10:00</updated><title type='text'>SQLite and Doctrine: in memory databases</title><content type='html'>Recently for a client&#39;s project, I incorporated a SQLite in memory database into my persistence tests as its a good (and fast) alternative to managing separate unit test and system databases. Typically in my test setup / tear down methods, I drop and recreate the unit test database to ensure clean testing conditions.... however I found that Doctrine doesn&#39;t support SQLite in memory database drops. &lt;br /&gt;
&lt;br /&gt;
To drop an in memory db - I don&#39;t believe the standard sql drop statement works. As this is the case, when calling Doctrine::dropDatabases(), Doctrine&#39;s SQLite Driver produces in a &#39;Database could not be found&#39; Exception in its dropDatabases method.&lt;br /&gt;
&lt;br /&gt;
As the SQLite in memory databases exist for the life of the connection only, a good solution is to simply reset the connection.&lt;br /&gt;
&lt;br /&gt;
Burrowing through the Doctrine framework, within the SQLite Driver (Doctrine/Connection/SQLite.php) I made the following modification:&lt;br /&gt;
&lt;br /&gt;
&lt;pre  class=&quot;code&quot;&gt;&lt;code&gt;
 public function dropDatabase()
    {
        if ( ! $dsn = $this-&amp;gt;getOption(&#39;dsn&#39;)) {
            throw new Doctrine_Connection_Exception(&#39;You must create your Doctrine_Connection by using a valid Doctrine style dsn in order to use the create/drop database functionality&#39;);
        }
        
        $info = $this-&amp;gt;getManager()-&amp;gt;parseDsn($dsn);
        
        //
        // BENS EDIT: If the db is in memory only - simply recreate a new connection
        //
        if(strcasecmp($info[&quot;dsn&quot;], &quot;sqlite::memory:&quot;) == 0)
        {         
         $c = $this-&amp;gt;getManager()-&amp;gt;getCurrentConnection();

  $this-&amp;gt;getManager()-&amp;gt;closeConnection($c);
  $this-&amp;gt;getManager()-&amp;gt;connection(&quot;sqlite::memory:&quot;,&quot;unit_test&quot;);
     
         return;
        }
        //
        // END BENS EDIT
        //

        $this-&amp;gt;export-&amp;gt;dropDatabase($info[&#39;database&#39;]);
    }
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
There are probably better ways to do this - so feel free to leave comments - however the above worked for me...</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/6307836527963592513/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/6307836527963592513?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/6307836527963592513'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/6307836527963592513'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2010/12/dropping-sqlite-in-memory-databases-in.html' title='SQLite and Doctrine: in memory databases'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-7492060794765548514</id><published>2010-11-25T21:06:00.004+10:00</published><updated>2013-06-26T22:24:15.063+10:00</updated><title type='text'>CodeIgniter and PHP Howto - Embedding images in Email</title><content type='html'>&lt;a href=&quot;http://utils.beninzambia.com/linker.php?direct=downloads.beninzambia.com/blog/MyPages_Email.php.txt&amp;amp;track=TCA&quot;&gt;DOWNLOAD THE CODEIGNITER EMAIL EXTENSION HERE&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
I recently had an issue in a client&#39;s development which required images to be embedded in html email code (&amp;lt;img src=&#39;cid:embeddedImage&#39; /&amp;gt;), rather than referenced via a public url (i.e. &amp;lt;img src=&#39;http://www.mysite.com/myImage.png&#39; /&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
&lt;!--
google_ad_client = &quot;pub-8226778256743425&quot;;
/* In article ads */
google_ad_slot = &quot;7464771992&quot;;
google_ad_width = 250;
google_ad_height = 250;
//--&gt;
&lt;/script&gt;&lt;br /&gt;
&lt;script src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot; type=&quot;text/javascript&quot;&gt;
&lt;/script&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;QUICK OVERVIEW - THE PUNCH LINE&lt;/h3&gt;I have written a CodeIgniter Library Extension to the basic Email class that facilitates the embedding of images in emails. You can download the code &lt;a href=&quot;http://utils.beninzambia.com/linker.php?direct=downloads.beninzambia.com/blog/MyPages_Email.php.txt&amp;amp;track=TCA&quot;&gt;HERE&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
To implement it, follow the instructions for Extending Native Libraries on the CodeIgniter website &lt;a href=&quot;http://codeigniter.com/user_guide/general/creating_libraries.html&quot;&gt;http://codeigniter.com/user_guide/general/creating_libraries.html &lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Finally, in the body of your email, use the following macro - making sure the class_id attribute matches the one used in the img src attribute (i.e. &amp;lt;img src=&#39;cid:my_image&#39; /&amp;gt;). An exmaple message body would be as follows&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;code&gt;
&amp;lt;html&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;img src=&quot;cid:my_image&quot; /&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;

// Macro in Windows
{embedded_image file=C:\\my_image.png class_id=my_image}{/embedded_image}

//Alternative Linux Macro
{embedded_image file=/var/my_image.png class_id=my_image}{/embedded_image}

&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
And thats it - the library encodes the image file as a base64 string and embeds it in your email.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;PROS AND CONS OF EMBEDDING IMAGES IN EMAIL:&lt;/h3&gt;&lt;h4&gt;PROS&lt;/h4&gt;- Images are immediately displayed when opening a message, rather than the client prompting the user to allow remote content... great for newsletters&lt;br /&gt;
- Emails are independent, once downloaded, they don&#39;t require a live connection to view in all their glory&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;CONS&lt;/h4&gt;- A little bit more coding and knowledge of email message format is required to get them to work if your framework does not support embedding images in email&lt;br /&gt;
- Some conjecture about spam filtering for bulk messages with embedded images. Some believe spam filtering is more pessimistic for emails with embedded images than not when sending to more than 100 addresses&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;HOW TO EMBED AN IMAGE&lt;/h3&gt;I&#39;m not going to go too far into the coding of native php code to email with embedded images (unless I get requests) - so Ill give a brief overview and some references.&lt;br /&gt;
&lt;br /&gt;
Like most things on the web, email message content can be defined in a series of envelopes. These envelopes are defined by content type. You can read about all of them here &lt;a href=&quot;http://www.freesoft.org/CIE/RFC/1521/15.htm&quot;&gt;http://www.freesoft.org/CIE/RFC/1521/15.htm&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
One of the most useful images to exemplify the content structure of a html email can be found at &lt;a href=&quot;http://www.phpeveryday.com/articles/PHP-Email-Using-Embedded-Images-in-HTML-Email-P113.html&quot;&gt;http://www.phpeveryday.com/articles/PHP-Email-Using-Embedded-Images-in-HTML-Email-P113.html&lt;/a&gt;&lt;br /&gt;
Bit of a warning though - the article itself has buggy code and examples.&lt;br /&gt;
&lt;br /&gt;
Grossly speaking - your email message if it supports html with embedded images, and a plain text alternative (for non html email clients) should render the following content in the email body&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;code&gt;
Content-Type: multipart/alternative; boundary=&quot;UNIQUE_ID_1&quot;

--UNIQUE_ID_1
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit

.... plain text alternative content for your html email....

--UNIQUE_ID_1
Content-Type: multipart/related;
 boundary=&quot;UNIQUE_ID_2&quot;

--UNIQUE_ID_2
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

--UNIQUE_ID_2
Content-Type: image/jpeg
 name=&#39;embedded_image.jpg&#39;
Content-Transfer-Encoding: base64
Content-ID: &amp;lt;class_id_referenced_in_img_src&amp;gt;
Content-Disposition: inline;
 filename=&#39;embedded_image.jpg&#39;

(Base64 encoded binary for the image)

--UNIQUE_ID_2-- 

--UNIQUE_ID_1--

&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h3&gt;NOTE on the above.&lt;/h3&gt;-- means open content type. Trailing -- means closing content type. When content type is &#39;multipart&#39;, you can define more than one content type under the same section identifier as you are either specifying alternative content, or related content. multipart/alternative content means one of the specified content sections is used. multipart/related content means that one content section references the other. We use the multipart/alternative content type to specify html, and plain text message alternatives. We use the multipart/related for relating html content with embedded image content.</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/7492060794765548514/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/7492060794765548514?isPopup=true' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/7492060794765548514'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/7492060794765548514'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2010/11/codeigniter-and-php-howto-embedding.html' title='CodeIgniter and PHP Howto - Embedding images in Email'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-4354167329149660528</id><published>2010-11-22T10:34:00.002+10:00</published><updated>2010-11-24T09:38:01.833+10:00</updated><title type='text'>noscript tag and google index</title><content type='html'>The noscript tag is indexed by google! I recently released work for a client which used the noscript tag to display the typical &#39;this site needs javascript&#39; warning if javascript was disabled on the client&#39;s browser.... unfortunately I did this in the head of my page AND used a h3 element to title the warning segment....&lt;br /&gt;
&lt;br /&gt;
As a result, most pages on the site were indexed as &#39;Javascript not enabled&#39; as the title, and the site&#39;s metatagged description as the content. Not happy.&lt;br /&gt;
&lt;br /&gt;
Best practice - if you are going to use the noscript tag for simple javascript warnings, use it at the bottom of the rendered page.... many sites do this (including StackOverflow). Might also help not to use any heading elements (i.e. h1,h2,h3) but rely on styling another element as a heading.</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/4354167329149660528/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/4354167329149660528?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/4354167329149660528'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/4354167329149660528'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2010/11/noscript-and-google-index.html' title='noscript tag and google index'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-7123436432804949578</id><published>2010-11-07T21:58:00.005+10:00</published><updated>2010-11-17T18:57:08.158+10:00</updated><title type='text'>Free DNS Servers: Free DNS Online</title><content type='html'>For the last few years of web development, I have had to find a couple of reliable free DNS online services to manage my, and client Domains. I thought I&#39;d post up a few and rate my experience with them. &lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Free DNS Online - My Experiences&lt;/h2&gt;&lt;br /&gt;
&lt;a href=&quot;http://utils.beninzambia.com/linker.php?direct=www.zoneedit.com&amp;amp;track=TCA&quot;&gt;Zone Edit&lt;/a&gt; : A great free DNS online service, 100% private and 100% free. Accounts used to be able to serve up to 5 domains, however recently this has been restricted to 2. The User Interface / Administration feels a bit clunky and old school web - but pretty straight forward and easy to use. &lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://utils.beninzambia.com/linker.php?direct=freedns.afraid.org&amp;amp;track=TCA&quot;&gt;FreeDNS&lt;/a&gt; : Another good free DNS online service, however you entries can be reviewed by other users. Other users can configure subdomains off your domain, however you can pipe this through an authorisation process (where you the administrator are emailed and confirm any config changes). Payment is required if you want to make your listing private.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://utils.beninzambia.com/linker.php?direct=www.dnsexit.com&amp;amp;track=TCA&quot;&gt;DNSExit&lt;/a&gt; : An uncapped free DNS online service. You can have as many accounts as you require... you can even set up dynamic DNS which is nice. Very slow though - and I have some questions regarding reliability. Recently the service was brought down by a DDOS attack for a couple of days.... have a backup - secondary dns on an alternate name server if possible.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://utils.beninzambia.com/linker.php?direct=www.dyndns.com&amp;amp;track=TCA&quot;&gt;DynDns &lt;/a&gt;: Free Dynamic DNS online service. Been around for years - can&#39;t recommend it enough for publicly serving from your dev box. Great for limited serving (i.e. demoing sites during development). Have a range of other paid services - however, a bit of googling for these will uncover alternative free services.&lt;br /&gt;
&lt;br /&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
&lt;!--
google_ad_client = &quot;pub-8226778256743425&quot;;
/* In article ads */
google_ad_slot = &quot;7464771992&quot;;
google_ad_width = 250;
google_ad_height = 250;
//--&gt;
&lt;/script&gt;&lt;br /&gt;
&lt;script src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot; type=&quot;text/javascript&quot;&gt;
&lt;/script&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/7123436432804949578/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/7123436432804949578?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/7123436432804949578'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/7123436432804949578'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2010/11/free-dns-servers-free-dns-online.html' title='Free DNS Servers: Free DNS Online'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-8602669158428547150</id><published>2010-11-02T11:03:00.008+10:00</published><updated>2013-04-12T23:39:57.683+10:00</updated><title type='text'>Detect Popup Blocker: Popup Blocker  Detection for Chrome + all browsers</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Popup blocker detection for all major browsers including Chrome....&lt;br /&gt;
&lt;br /&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
&lt;!--
google_ad_client = &quot;pub-8226778256743425&quot;;
/* In article ads */
google_ad_slot = &quot;7464771992&quot;;
google_ad_width = 250;
google_ad_height = 250;
//&lt;/script&gt;
&lt;br /&gt;
&lt;script src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot; type=&quot;text/javascript&quot;&gt;
&lt;/script&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/benkitzelman/5372051.js&quot;&gt;&lt;/script&gt;

&lt;br /&gt;
Chrome popup blocker detection is a little different to others in that Chrome returns a valid window object after calling window.open, even with popups being disabled. There are a heap of posts around all basically stating that to determine whether this window object has been blocked by Chrome, we need to test whether the innerHeight of the popup has been set to 0.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/8602669158428547150/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/8602669158428547150?isPopup=true' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/8602669158428547150'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/8602669158428547150'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2010/11/window-open-popup-blocker-detect-for.html' title='Detect Popup Blocker: Popup Blocker  Detection for Chrome + all browsers'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-8955563210890621149</id><published>2010-10-15T19:26:00.002+10:00</published><updated>2010-10-20T08:37:47.947+10:00</updated><title type='text'>Google Analytics - multi domain named site tracking</title><content type='html'>&lt;script type=&quot;text/javascript&quot;&gt;
&lt;!--
google_ad_client = &quot;pub-8226778256743425&quot;;
/* In article ads */
google_ad_slot = &quot;7464771992&quot;;
google_ad_width = 250;
google_ad_height = 250;
//--&gt;
&lt;/script&gt;&lt;br /&gt;
&lt;script src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot; type=&quot;text/javascript&quot;&gt;
&lt;/script&gt;&lt;br /&gt;
Another quick blog... Recently I added analytics to a couple of sites with more than one domain name. Its easy to see how much of your traffic is from each hostname (Vistors-&amp;gt;Network Properties-&amp;gt;Hostnames), but&lt;br /&gt;
I wanted to be able to overlay how much traffic was arriving to the site from each domain (to see which one was most effectively being advertised).....&lt;br /&gt;
&lt;br /&gt;
I was able to achieve this by creating a &lt;b&gt;Custom Segment.&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
When first logging into the &lt;b&gt;Google Analytics Dashboard&lt;/b&gt; for the desired site / account, just above the Date Range, there is the &lt;b&gt;Advanced Segments&lt;/b&gt; drop down list. Clicking on that drop down I was able to create a new &lt;b&gt;Advanced Segment.&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
In the Advanced Segment editor, I could expand the &lt;b&gt;Content submenu&lt;/b&gt; from the Dimensions menu on the left, and drag the&lt;b&gt; &#39;HOSTNAME&#39;&lt;/b&gt; field into my segment.&lt;br /&gt;
&lt;br /&gt;
I then set the &lt;b&gt;Condition&lt;/b&gt; field to &lt;b&gt;&#39;CONTAINS&#39;&lt;/b&gt;, then enter the base hostname of the additional domain I want to analyse separately (i.e. myseconddomain.com).&lt;br /&gt;
&lt;br /&gt;
After naming and saving the segment, I can apply it via the &lt;b&gt;Advanced Segments &lt;/b&gt;drop down in the &lt;b&gt;dashboard &lt;/b&gt;and viola....</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/8955563210890621149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/8955563210890621149?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/8955563210890621149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/8955563210890621149'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2010/10/google-analytics-multi-domain-named.html' title='Google Analytics - multi domain named site tracking'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-5025641096962877729</id><published>2010-10-08T15:23:00.001+10:00</published><updated>2013-06-26T22:25:08.850+10:00</updated><title type='text'>CodeIgniter - Supporting Multiple Domains in config[&quot;base_url&quot;]</title><content type='html'>A very quick blog.....&lt;br /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Within the site config file (application_folder/config/config.php file), a base_url property is set. This is read by the base_url() method to generate server side redirections......&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;If you are creating a site which has more than domain name (ie. www.domain_one.com and www.domain_two.com), its probably a good idea to dynamically create this value in the config file. This way, the domain name is preserved when redirecting between pages.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class=&quot;code&quot;&gt;&lt;br /&gt;
//...config ...//&lt;br /&gt;
$config[&#39;base_url&#39;] = &#39;http&#39;;&lt;br /&gt;
if (isset($_SERVER[&quot;HTTPS&quot;]) &amp;amp;&amp;amp; $_SERVER[&quot;HTTPS&quot;] == &quot;on&quot;) $config[&#39;base_url&#39;] .= &quot;s&quot;;&lt;br /&gt;
&lt;br /&gt;
$config[&#39;base_url&#39;] .= &quot;://&quot;;&lt;br /&gt;
&lt;br /&gt;
if ($_SERVER[&quot;SERVER_PORT&quot;] != &quot;80&quot;) $config[&#39;base_url&#39;] .= $_SERVER[&quot;SERVER_NAME&quot;].&quot;:&quot;.$_SERVER[&quot;SERVER_PORT&quot;];&lt;br /&gt;
else $config[&#39;base_url&#39;] .= $_SERVER[&quot;SERVER_NAME&quot;];&lt;br /&gt;
&lt;br /&gt;
$config[&quot;base_url&quot;].&quot;/&quot;;&lt;br /&gt;
//... config ...//&lt;/div&gt;&lt;div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/5025641096962877729/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/5025641096962877729?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/5025641096962877729'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/5025641096962877729'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2010/10/codeigniter-supporting-multiple-domains.html' title='CodeIgniter - Supporting Multiple Domains in config[&quot;base_url&quot;]'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-1560218569421241441</id><published>2010-10-06T16:04:00.011+10:00</published><updated>2013-06-26T22:26:09.290+10:00</updated><title type='text'>IE Cache and AJAX: Cache Busting Ajax requests</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Yet another &#39;special case&#39; caveat for Internet Explorer, the red headed step child of the browser family..... (sorry to any red headed step children who might be reading this - chalk it up to the savage injustices of life). I discovered that IE cache and Ajax requests are not the best of friends compared to how other browsers handle Ajax requests.   &lt;br /&gt;
&lt;br /&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
&lt;!--
google_ad_client = &quot;pub-8226778256743425&quot;;
/* In article ads */
google_ad_slot = &quot;7464771992&quot;;
google_ad_width = 250;
google_ad_height = 250;
//&lt;/script&gt;

&lt;script src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot; type=&quot;text/javascript&quot;&gt;
&lt;/script&gt;&lt;br /&gt;
&lt;br /&gt;
Recently I found that IE cached ajax requests in a CodeIgniter + ExtJS site. I was using url rewriting, so all GET params were encoded as URI segments...&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;
eg. (http://host/controller/action/param1/param2)&lt;/div&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;The Problem:&lt;/span&gt;&lt;br /&gt;
Usually, I would use ExtJS inherent cache busting tools (Ext.Ajax.disableCaching - which normally defaults to true).... but due to the url rewriting, the ExtJS method caused issues. Query string values (?blah=value) are disallowed in my app due to the url rewriting, therefore EXTs native cache disabling does not work as it simply appends a uid to the querystring (?_dc=123453443343). This caused &#39;disallowed character&#39; exceptions.&lt;br /&gt;
&lt;br /&gt;
Furthermore - I couldn&#39;t simply add a random variable to the end of a request, as this could be misinterpreted as an actual parameter for actions with parameters with default values&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;
eg. http://host/controller/action/param1/param2/no_cache01223213312&lt;/div&gt;
&lt;br /&gt;
no_cache01223213312 could be misinterpreted as param3 in the following action:&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;
public function action($param1, $param2, $param3 = &quot;default value&quot;)&lt;br /&gt;
{&lt;br /&gt;
//..//&lt;br /&gt;
}&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;The Solution:&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;The Big Stick:&lt;/span&gt;&lt;br /&gt;
Whether you use an MVC framework, URL rewriting, the first thing you should consider is that on all Ajax actions, make sure the header &#39;pragma&#39; is set to no-cache..... so in php - write the header somewhere before content is returned to the browser&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;
header(&quot;Pragma: no-cache&quot;);&lt;/div&gt;
&lt;br /&gt;
This can really suck as it blows away all your lovely server side cache introducing a potential performance bottleneck to your app, all because Dwayne Dibley is still browsing your site using IE.&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;The ExtJS (Javascript) way:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
The Ext solution was at the page level to intercept all AJAX requests, and add a random POSTED variable to the parameter listing.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;br /&gt;
Ext.Ajax.disableCaching = false;&lt;br /&gt;
Ext.Ajax.addListener(&quot;beforerequest&quot;, function (conn, options ){&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;if(!options.params) options.params = {};&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;options.params.cacheBuster = Ext.id();  &lt;br /&gt;
}, this);&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
This forces a server side request as the request is unique (thanks to the random post variable). It also allows me to free specify GET params in the rewritten url, as I am adding a POST variable to uniquify the request.&lt;br /&gt;
&lt;br /&gt;
For generic javascript.... when calling the target url, simply append a generated dummy query string parameter (like a timestamp)&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;
&quot;http://myhost.com/myAjaxPage.php?_nocache=321313213445462&quot;&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
Again, the same caveat applies to the pragma header - you would probably want to make this cache busting parameter conditional on browser type
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/1560218569421241441/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/1560218569421241441?isPopup=true' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/1560218569421241441'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/1560218569421241441'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2010/10/cache-busting-ajax-requests-in-ie.html' title='IE Cache and AJAX: Cache Busting Ajax requests'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-7055085493556659460</id><published>2010-10-02T11:38:00.002+10:00</published><updated>2010-10-02T17:09:04.801+10:00</updated><title type='text'>Extra Bucks Online</title><content type='html'>So in the past I have blogged a bit about finding an &lt;a href=&quot;http://thecodeabode.blogspot.com/2010/09/e-business-ideas.html&quot;&gt;eBusiness which is quick to setup and get running&lt;/a&gt;. I&#39;m pleased to announce that my latest attempt at this is entering its final proofing.....&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://utils.beninzambia.com/linker.php?direct=www.extrabucks.com.au&amp;track=TCA&quot;&gt;ExtraBucks&lt;/a&gt; is now online and is in its final proofing stages. The official launch date will come soon.... Essentially it is an odd jobs and piece work bulletin board. Its designed for those who want to make a bit of extra work outside of business hours to link up with people who need the odd job done. All 100% free to use. Check it out - have a play and feel free to leave some comments!</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/7055085493556659460/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/7055085493556659460?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/7055085493556659460'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/7055085493556659460'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2010/10/extra-bucks-online.html' title='Extra Bucks Online'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-6150499578541559126</id><published>2010-08-09T22:42:00.003+10:00</published><updated>2013-06-26T22:29:04.815+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="development"/><category scheme="http://www.blogger.com/atom/ns#" term="execution"/><category scheme="http://www.blogger.com/atom/ns#" term="linux"/><category scheme="http://www.blogger.com/atom/ns#" term="PHP"/><category scheme="http://www.blogger.com/atom/ns#" term="popen"/><category scheme="http://www.blogger.com/atom/ns#" term="proc_open"/><category scheme="http://www.blogger.com/atom/ns#" term="script"/><category scheme="http://www.blogger.com/atom/ns#" term="shell"/><category scheme="http://www.blogger.com/atom/ns#" term="windows"/><title type='text'>Calling the php interpreter within web script</title><content type='html'>Recently, part of a development required me to execute shell script as part of a web request. The design was to kick start a long running php process (via shell script), which would run beyond the length of a standard web request.&amp;nbsp;To do this, I used forking shell script and popen... (if using shared hosting, shell execution methods are generally disabled - check php.ini&#39;s disable_functions config value to verify).&lt;br /&gt;
&lt;br /&gt;
Within my dev environment (Windows) I was able to execute the following with no issues:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;popen(&quot;start /b php my_script.php my_args&quot;, &quot;w&quot;);&lt;/div&gt;&lt;b&gt;Note: &#39;start /b&#39; forks a windows process - making it run in the background&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
When executing its equivalent in a Linux environment&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;popen(&quot;php my_script.php my_args &amp;amp;&quot;, &quot;w&quot;);&lt;/div&gt;&lt;br /&gt;
In Linux, the server was thrown into a state of confusion, perpetually executing, then aborting the requested shell script command (infinitely starting and exiting the requested php script in the popen command). Obviously explicitly calling the php interpreter from within an executing php process is a particularly nasty thing to do. &lt;br /&gt;
&lt;br /&gt;
I&#39;m assuming this sort of thing doesn&#39;t happen in windows as shell script executes in its own command window (which when using proc_open with get_proc_status makes getting a correct PID value problematic). Anyone with futher insight - feel free to leave comments.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;To get around this issue&lt;/b&gt;, I ensured that in the linux environment, the shebang path to the interpreter appeared on the first line of the executing script, and it was chmod&#39;ed to allow direct cli execution... ie&lt;br /&gt;
&lt;br /&gt;
my_script.php:&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;#!/usr/local/bin/php&lt;br /&gt;
&lt;br /&gt;
//&lt;br /&gt;
// my code&lt;br /&gt;
//&lt;br /&gt;
?&amp;gt;&lt;/div&gt;&lt;br /&gt;
CHMOD command used:&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;chmod 755 my_script.php&lt;/div&gt;&lt;br /&gt;
Then finally the linux popen command:&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;popen(&quot;./my_script.php my_args &amp;amp;&quot;, &quot;w&quot;);&lt;/div&gt;&lt;br /&gt;
The default working directory of popen, and all other shell script execution methods is always web root (so my_script.php sat in the web root dir).&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;The same issue occurs with all other shell script execution methods:&lt;/b&gt;&lt;br /&gt;
system, exec, proc_open, passthru, back ticks (`) etc.</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/6150499578541559126/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/6150499578541559126?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/6150499578541559126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/6150499578541559126'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2010/08/calling-php-interpreter-within-web.html' title='Calling the php interpreter within web script'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-1643870170773988151</id><published>2010-06-27T21:45:00.003+10:00</published><updated>2010-09-18T11:14:47.704+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="codeigniter"/><category scheme="http://www.blogger.com/atom/ns#" term="doctrine"/><category scheme="http://www.blogger.com/atom/ns#" term="filters"/><category scheme="http://www.blogger.com/atom/ns#" term="layouts"/><category scheme="http://www.blogger.com/atom/ns#" term="rails"/><category scheme="http://www.blogger.com/atom/ns#" term="ruby"/><category scheme="http://www.blogger.com/atom/ns#" term="transactions"/><title type='text'>CodeIgniter - Ruby on Rails (RoR) Layouts and filters</title><content type='html'>&lt;a href=&quot;http://utils.beninzambia.com/linker.php?direct=175.107.156.152/blog/CodeIgniter-Doctrine-ExtJS_Base_Project.zip&amp;amp;track=TCA&quot;&gt;DOWNLOAD THE CODEIGNITER DOCTRINE STARTER (~8Mb)&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Continuing to list starter features, I have also integrated Ruby on Rails (RoR) style layouts and before / after filters.&lt;br /&gt;
&lt;br /&gt;
Both were implemented as CI hooks - both the layout and filter code was obtained from the CodeIgniter forums and wiki posts&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Layouts:&amp;nbsp;&lt;a href=&quot;http://utils.beninzambia.com/linker.php?direct=codeigniter.com/forums/viewthread/57902/&amp;amp;track=TCA&quot;&gt;CodeIgniter Forums Post&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Filters:&amp;nbsp;&lt;a href=&quot;http://utils.beninzambia.com/linker.php?direct=codeigniter.com/wiki/Filters_system/&amp;amp;track=TCA&quot;&gt;CodeIgniter Forums Post - Filters&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;Using the Filters hook, each action is wrapped in a Doctrine Transaction, which ensures all db updates etc. are ATOMIC.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;One hassle I found with the above Filters system was that I couldn&#39;t implement a before / after filter directly in the controller class. Within the Doctrine_Transaction filter I ensure that if a controller has a before_action, or after_action function within its class definition, it is called before, or after the action is executed. This obviously could / should be abstracted out eventually into its own Filter class.... but it works just the same as is.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;http://utils.beninzambia.com/linker.php?direct=175.107.156.152/blog/CodeIgniter-Doctrine-ExtJS_Base_Project.zip&amp;amp;track=TCA&quot;&gt;DOWNLOAD THE CODEIGNITER DOCTRINE STARTER (~8Mb)&lt;/a&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/1643870170773988151/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/1643870170773988151?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/1643870170773988151'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/1643870170773988151'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2010/06/codeigniter-ruby-on-rails-ror-layouts.html' title='CodeIgniter - Ruby on Rails (RoR) Layouts and filters'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-23214170.post-3941891294278005183</id><published>2010-06-08T18:06:00.011+10:00</published><updated>2013-06-26T22:30:50.184+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="codeigniter"/><category scheme="http://www.blogger.com/atom/ns#" term="doctrine"/><category scheme="http://www.blogger.com/atom/ns#" term="unit testing"/><title type='text'>CodeIgniter - Doctrine unit testing - starter features</title><content type='html'>&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-8226778256743425&quot;;
/* In article ads */
google_ad_slot = &quot;7464771992&quot;;
google_ad_width = 250;
google_ad_height = 250;
//--&gt;
&lt;/script&gt;&lt;br /&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;&lt;br /&gt;
&lt;br /&gt;
So to expand on the previous post... specifically to describe a few of the extra bells and whistles in the project starter....&lt;br /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;http://utils.beninzambia.com/linker.php?direct=175.107.156.152/blog/CodeIgniter-Doctrine-ExtJS_Base_Project.zip&amp;amp;track=TCA&quot;&gt;DOWNLOAD THE CODEIGNITER-DOCTRINE STARTER (~8Mb)&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;b&gt;Unit Testing&lt;/b&gt;&lt;/div&gt;&lt;div&gt;I have created a (very) simple extension to the codeigniter unit testing as I wanted to have a simple, web based interface to unit tests. I found the whole CodeIgniter terminology used in unit testing a little confusing (coming from a NUnit / JUnit testing background). Unless I missed something in the doc (which is very possible), CodeIgniter supports test assertions ($controller-&amp;gt;unit-&amp;gt;run when the test helper is loaded), there was no way to group a number of assertions together into a logical unit of testing.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;I&#39;m going to use a little NUnit / JUnit terminology to describe unit testing via the web page interface in the starter. In the ApplicationCode/libraries folder I have a &lt;b&gt;base_test_controller&lt;/b&gt; which when extended replicates basic &lt;b&gt;TestFixture &lt;/b&gt;functionality. To create a &lt;b&gt;Unit Test&lt;/b&gt; within the fixture, simply create a function prefixed with the name test_. The following demonstrates using a controller as a &lt;b&gt;test fixture&lt;/b&gt;:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;&lt;br /&gt;
&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;//&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;// My Test Fixture&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;//&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;class MyTest extends base_test_controller {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;   &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;//&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;// This method is executed before any test methods are run&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;//&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;function fixture_setup(){}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;//&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;// This method is executed after all test methods are run&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;//&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;function fixture_tear_down(){}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;//&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;// This method is executed before each test method is run&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;//&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;function unit_setup(){}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;//&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;// This method is executed after each test method is run&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;//&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;function unit_tear_down(){}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;//&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;// Your Unit Test&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;white-space: pre;&quot;&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;//&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;function test_My_unit_test()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;    $this-&amp;gt;test_description = &quot;This is a description of my unit test&quot;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;    $this-&amp;gt;unit-&amp;gt;run(true, true, &quot;Assertion one has passed&quot;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;    $this-&amp;gt;unit-&amp;gt;run(true, true, &quot;Assertion two has passed&quot;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: Georgia, serif;&quot;&gt;&lt;a href=&quot;http://utils.beninzambia.com/linker.php?direct=175.107.156.152/blog/CodeIgniter-Doctrine-ExtJS_Base_Project.zip&amp;amp;track=TCA&quot;&gt;DOWNLOAD THE CODEIGNITER-DOCTRINE STARTER (~8Mb)&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://thecodeabode.blogspot.com/feeds/3941891294278005183/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/23214170/3941891294278005183?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/3941891294278005183'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/23214170/posts/default/3941891294278005183'/><link rel='alternate' type='text/html' href='http://thecodeabode.blogspot.com/2010/06/codeigniter-doctrine-starter-features.html' title='CodeIgniter - Doctrine unit testing - starter features'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/11465248091245614781</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>