<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>PerfectLine</title>
	<atom:link href="http://www.perfectline.ee/feed" rel="self" type="application/rss+xml" />
	<link>http://www.perfectline.ee</link>
	<description>PerfectLine</description>
	<lastBuildDate>Tue, 20 Dec 2011 15:34:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>What&#8217;s Up With Startup Burn Rates?</title>
		<link>http://www.perfectline.ee/blog/whats-up-with-startup-burn-rates</link>
		<comments>http://www.perfectline.ee/blog/whats-up-with-startup-burn-rates#comments</comments>
		<pubDate>Tue, 20 Dec 2011 15:32:27 +0000</pubDate>
		<dc:creator>Martin Kivi</dc:creator>
				<category><![CDATA[Startups]]></category>
		<category><![CDATA[Burn rate]]></category>
		<category><![CDATA[Minimum Viable Product]]></category>
		<category><![CDATA[VC]]></category>

		<guid isPermaLink="false">http://www.perfectline.ee/?p=152</guid>
		<description><![CDATA[I finally managed to catch up with my reading and found a rather intriguing post by Fred Wilson about startup burn rates. More specifically, how much should startup spend (follow up post here) to build different stages of its product. [...]]]></description>
			<content:encoded><![CDATA[<p>I finally managed to catch up with my reading and found a rather intriguing post by <a href="http://www.avc.com">Fred Wilson</a> about startup burn rates. More specifically, <a href="http://www.avc.com/a_vc/2011/12/burn-rates-how-much.html">how much should startup spend</a> (follow up post <a href="http://www.avc.com/a_vc/2011/12/how-much-to-burn-while-building-product.html">here</a>) to build different stages of its product. What kind of amused me was the $50K monthly burn rate when a startup is in a Building Product Stage. My experience has been way different and I believe that you will agree with me &#8211; you don&#8217;t need to spend that much.<span id="more-152"></span></p>
<p>There was one thing that I didn&#8217;t quite get. As a founder who has a vision about your product (is there any other way at all?), why on Earth would you need a product manager? The founder, from all the people in the world, should be the one who knows exactly how the product should work and who it is for. Not having previous experience with product management shouldn&#8217;t be an acceptable excuse to any founder.</p>
<p>Apparently it seems that it is acceptable to work on the <strong>first stage for around 6-9 months and spend approximately $375K</strong> while doing that. Don&#8217;t you think that it&#8217;s a bit too much? If a founder doesn&#8217;t take any seed funding to build a <a href="http://www.perfectline.ee/blog/what-does-minimum-viable-product-mean-for-us" title="What Does Minimum Viable Product Mean For Us?">minimum viable product</a> (strongly recommended in my opinion) then I bet that most of the founders out there don&#8217;t have that spare $375K to spend just to see if their idea will fly or not.</p>
<p>If I wouldn&#8217;t have any previous experience I probably wouldn&#8217;t be surprised by the mentioned time and cost to build a minimum viable product. However, I have some experience when it comes to helping founders to get their MVP out there. With that experience in mind, I&#8217;ve found that <strong>it takes usually less than 3 months</strong> (one designer + one engineer + some additional help will go a long way) to get the first version done. It will usually be good enough to test if their idea and business model works and go after seed funding on much better terms than without a MVP.</p>
<h2>You can do it for less</h2>
<p>Now, some more personal experience. You might or might not know that we&#8217;re working on two products of our own and we&#8217;ve taken somewhat different approach on execution for both of them.</p>
<p><a href="http://www.shoperb.com" title="Shoperb - easy eCommerce platform">Shoperb</a>, a rather complex eCommerce SaaS platform, has been in the works for over a year with <strong>total actual development time spent around 5 months</strong> or so. We want it to have all the necessary features to successfully run an online store when we launch some time next year. From technical point of view Shoperb has much more complex features (tax rules, shipping rules, etc) than an average product we work with (want to take a look at it, let me know). On top of that, at some point I realized that the design could be quite a bit better, so I  redesigned it even before we launched. That could be considered as a mistake but I&#8217;m still thinking that it was a right decision &#8211; we&#8217;re coming out with better product thanks to that.</p>
<p>Then we have <a href="http://www.photry.com" title="Photry - cloud backup for photos">Photry</a>, a cloud backup platform for photos, that was <strong>created within 48 hours</strong> at Rails Rumble 2010. With that time we built a MVP that works well and is actually getting some organic traffic and more signups than we would ever have hoped for. That was about a year ago. In the meanwhile a new design was created (a lot better, if I may add) and about a week ago one of our engineers started working on it. By the end of this year we will have a next version of Phtory ready and hopefully in early January we&#8217;ll have a nice re-launch.</p>
<p><strong>Both of these services are being built with very limited resources.</strong> Only more lately one of our engineers have worked on Shoperb almost full time and the progress this far has been awesome. Same experience with Photry &#8211; amazing progress with minimum amount of time. How much is it costing us? A lot less than was brought out by Mr. Wilson&#8217;s post.</p>
<h2>Conclusion</h2>
<p>So what am I saying with all this? It is possible to build something without costing founders arms and legs. Hiring five employees that early in the product&#8217;s life cycle clearly seems like spending too much. Founders can do and do it well with less money spent. If a founder has some savings (lets say $50K) then they most probably can do without seed funding. Even if they need funding, they can take way smaller amount of funding and save more equity for themselves. They can find themselves a decent engineering partner to build the MVP for their awesome idea. When looking for that partner, a proper due diligence on partners is strongly recommended, just like it would be done with any investors or employees. Getting in touch with their previous clients will go a long way in building that relationship.</p>
<p>I know that I&#8217;m biased but <strong>with $50K it is more reasonable to just outsource</strong> this work to experienced experts (may I recommend us?). With constant communication it will be a breeze to get your first version out. Just like we would be sitting in your office. Except you don&#8217;t need to spend on office or anything related to it.</p>
<p>On top of that, this will save founders (even if they&#8217;ve taken seed funding) a big slice of equity. Now isn&#8217;t that what we all want, get more for less? I know that I prefer it that way and most probably so do you.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.perfectline.ee/blog/whats-up-with-startup-burn-rates/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What Does Minimum Viable Product Mean For Us?</title>
		<link>http://www.perfectline.ee/blog/what-does-minimum-viable-product-mean-for-us</link>
		<comments>http://www.perfectline.ee/blog/what-does-minimum-viable-product-mean-for-us#comments</comments>
		<pubDate>Sun, 18 Dec 2011 20:22:11 +0000</pubDate>
		<dc:creator>Martin Kivi</dc:creator>
				<category><![CDATA[Startups]]></category>
		<category><![CDATA[Entrepreneurship]]></category>
		<category><![CDATA[Founders]]></category>
		<category><![CDATA[Minimum Viable Product]]></category>
		<category><![CDATA[Product Management]]></category>

		<guid isPermaLink="false">http://www.perfectline.ee/?p=153</guid>
		<description><![CDATA[In my time in the whole startup world I&#8217;ve come to notice that Minimum Viable Product (MVP) is understood somewhat differently to most founders. Lately I have been getting the question of &#8220;What is Minimum Viable Product&#8221; more often and [...]]]></description>
			<content:encoded><![CDATA[<p>In my time in the whole startup world I&#8217;ve come to notice that Minimum Viable Product (MVP) is understood somewhat differently to most founders. Lately I have been getting the question of &#8220;What is Minimum Viable Product&#8221; more often and that&#8217;s why I&#8217;ve taken some time to shed some light on how we see it.<span id="more-153"></span></p>
<p>To start off what <a href="http://en.wikipedia.org/wiki/Minimum_viable_product">Minimum Viable Product</a> means to us, I would like to quote an article from Wikipedia:</p>
<blockquote><p><span class="quote"></span>A Minimum Viable Product has just those features that allow the product to be deployed, and no more. The product is typically deployed to a subset of possible customers, such as early adopters that are thought to be more forgiving, more likely to give feedback, and able to grasp a product vision from an early prototype or marketing information. It is a strategy targeted at avoiding building products that customers do not want, that seeks to maximize the information learned about the customer per dollar spent.</p></blockquote>
<p>From my own experience when working with various startups is that you don&#8217;t need to necessarily have that simplified approach. For us, a MVP means simply a limited subset of features and a possibility of some manual labor by the founder. However, by no means should it be acceptable that MVP stands for a crappy product. The user interface, and the user experience in general, <strong>has to be absolutely brilliant</strong> from the day one. That&#8217;s how you will <strong>create fans</strong> who love your product. </p>
<p>On most cases it should be possible to <strong>create a Minimum Viable Product in about 3 months</strong> of development. Of course it takes more time and resources if you&#8217;re building a SaaS platform to maintain nuclear power plants. Not doing anything that high scale? Well, 3 months should be enough to put together a simple, yet beautiful, product that gives your future customers something to work with. Something that gets them thinking on what more could they use and what could be changed in the product. Now that&#8217;s a perfect position to be in and I bet that most founders would love to be there.</p>
<p>You can start <strong>building some traction</strong> with that product, get more ideas on which features to implement and just <strong>do what your customers will love</strong>. Instead of going somewhat blindly in guessing what they might want. If you&#8217;re lucky, you can even implement billing/subscription plans and already start charging customers for the awesome service you have built for them.</p>
<p>I believe that the following will conclude it perfectly. <strong>Minimum Viable Product will help to remove the guesswork in building your awesome product or service.</strong></p>
<p>Lets build it together. If you want to know more about how we work, just <a href="http://www.perfectline.ee/contact" title="Contact">get in touch</a> with us.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.perfectline.ee/blog/what-does-minimum-viable-product-mean-for-us/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adding flash message capability to your render calls in Rails</title>
		<link>http://www.perfectline.ee/blog/adding-flash-message-capability-to-your-render-calls-in-rails</link>
		<comments>http://www.perfectline.ee/blog/adding-flash-message-capability-to-your-render-calls-in-rails#comments</comments>
		<pubDate>Wed, 16 Nov 2011 08:12:07 +0000</pubDate>
		<dc:creator>Tanel Suurhans</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[ActionController]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://www.perfectline.ee/?p=148</guid>
		<description><![CDATA[Ruby on Rails 3.x has given us a lot of syntactical sugar. Most of it are pretty small things, things you might not even discover unless someone told you. One of these things is being able to define flash messages [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Ruby on Rails 3.x</strong> has given us a lot of syntactical sugar. Most of it are pretty small things, things you might not even discover unless someone told you.<br />
One of these things is being able to define <strong>flash messages with redirect calls</strong> in the controller. In this post I will do a really quick overview of that small feature and replicate it for render calls also &#8211; resulting in prettier code.
</p>
<p><span id="more-148"></span></p>
<p>
Let&#8217;s get started with code right away &#8211; this is how the feature works:</p>
<div class="codecolorer-container ruby dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">redirect_to login_path, <span style="color:#ff3333; font-weight:bold;">:flash</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span>:error <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;My error here&quot;</span><span style="color:#006600; font-weight:bold;">&#125;</span><br />
<br />
<span style="color:#008000; font-style:italic;"># or with convenience shortcuts :alert and :notice</span><br />
redirect_to login_path, <span style="color:#ff3333; font-weight:bold;">:notice</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;My notice&quot;</span><br />
redirect_to login_path, <span style="color:#ff3333; font-weight:bold;">:alert</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;My alert&quot;</span><br />
<br />
<span style="color:#008000; font-style:italic;"># notice that you can also use the shortcut readers for &nbsp;these</span><br />
= flash.<span style="color:#9900CC;">notice</span> <span style="color:#008000; font-style:italic;"># same as flash[:notice]</span><br />
= flash.<span style="color:#9900CC;">alert</span> <span style="color:#008000; font-style:italic;"># same as flash[:alert]</span><br />
<br />
<span style="color:#008000; font-style:italic;"># and you can also assign with these shortcuts</span><br />
flash.<span style="color:#9900CC;">notice</span> = <span style="color:#996600;">&quot;foo&quot;</span><br />
flash.<span style="color:#9900CC;">alert</span> = <span style="color:#996600;">&quot;bar&quot;</span></div></div>
<p><p>
Now the common pattern in controllers looks like this:</p>
<div class="codecolorer-container ruby dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@foo</span>.<span style="color:#9900CC;">save</span><br />
&nbsp; redirect_to foos_path, <span style="color:#ff3333; font-weight:bold;">:notice</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Foo saved&quot;</span><br />
<span style="color:#9966CC; font-weight:bold;">else</span><br />
&nbsp; flash<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:alert</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;Some errors occured&quot;</span><br />
&nbsp; render <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:new</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></div>
</p>
<p>
What I want to be able to do is this:</p>
<div class="codecolorer-container ruby dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@foo</span>.<span style="color:#9900CC;">save</span><br />
&nbsp; redirect_to foos_path, <span style="color:#ff3333; font-weight:bold;">:notice</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Foo saved&quot;</span><br />
<span style="color:#9966CC; font-weight:bold;">else</span><br />
&nbsp; render <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:new</span>, <span style="color:#ff3333; font-weight:bold;">:alert</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Some errors occured&quot;</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></div>
</p>
<p>
Adding this functionality is actually pretty simple &#8211; we just have to create some code extending the render function.<br />
This next piece of code actually extends the module containing the functionality for the redirect calls.</p>
<div class="codecolorer-container ruby dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">module</span> ActionController<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">module</span> Flash<br />
<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> render<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; options = args.<span style="color:#9900CC;">last</span>.<span style="color:#9900CC;">is_a</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">Hash</span><span style="color:#006600; font-weight:bold;">&#41;</span> ? args.<span style="color:#9900CC;">last</span> : <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> alert = options.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:alert</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; flash<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:alert</span><span style="color:#006600; font-weight:bold;">&#93;</span> = alert<br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> notice = options.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:notice</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; flash<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:notice</span><span style="color:#006600; font-weight:bold;">&#93;</span> = notice<br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> other = options.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:flash</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; flash.<span style="color:#9900CC;">update</span><span style="color:#006600; font-weight:bold;">&#40;</span>other<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">super</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></div>
</p>
<p>You can place this in an initialize or somewhere in your library directory and explicitly require it. Hope this is helpful for you as much as it is for me!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.perfectline.ee/blog/adding-flash-message-capability-to-your-render-calls-in-rails/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>We are hiring and other news</title>
		<link>http://www.perfectline.ee/blog/we-are-hiring-and-other-news</link>
		<comments>http://www.perfectline.ee/blog/we-are-hiring-and-other-news#comments</comments>
		<pubDate>Fri, 14 Oct 2011 21:55:15 +0000</pubDate>
		<dc:creator>Martin Kivi</dc:creator>
				<category><![CDATA[PerfectLine]]></category>

		<guid isPermaLink="false">http://www.perfectline.ee/?p=141</guid>
		<description><![CDATA[We have been rather busy this past few months (like always) so this is just a quick note about what we&#8217;ve been up to. Briefly &#8211; we&#8217;re hiring, Shoperb is coming closer to private beta and we&#8217;ve moved to a [...]]]></description>
			<content:encoded><![CDATA[<p>We have been rather busy this past few months (like always) so this is just a quick note about what we&#8217;ve been up to. Briefly &#8211; we&#8217;re hiring, Shoperb is coming closer to private beta and we&#8217;ve moved to a new office.<span id="more-141"></span></p>
<h2>We are hiring!</h2>
<p>More specifically we&#8217;re looking to fill two positions in our Tallinn office. You should be awesome and down to earth kind of guy (or girl), know your stuff and be easy to talk and work with. You should be really great with <strong>Ruby</strong> (Python, PHP and Java are good starting points as well) or with <strong>HAML, SCSS and Javascript</strong>. As always, we prefer people who are comfortable in wearing multiple hats &#8211; the more you can do, the better. You will be working on various projects for our awesome clients (mostly startups around the world), as well as on our internal projects &#8211; <a href="http://www.shoperb.com" title="Shoperb"><strong>Shoperb</strong></a> and <a href="http://www.photry.com" title="Photry"><strong>Photry</strong></a>. Besides that, we have a lot more ideas that we want to try out and will also support you with making your ideas form into something meaningful as well.</p>
<p>If you&#8217;re interested in joining us or have any questions then just get in touch with me and we&#8217;ll take it from there.</p>
<h2>Shoperb &#8211; it&#8217;s all coming together now</h2>
<p>Lately we&#8217;ve been able to get a lot of work done on Shoperb and it&#8217;s all coming together rather well. We&#8217;re currently preparing for the launch of a highly customized Shoperb store for an online music business, which will be followed by a private beta for the platform. If you&#8217;re interested in participating, please go to <a href="http://www.shoperb.com" title="Shoperb">www.shoperb.com</a> and sign up for beta program. We will get in touch with you as soon as we get going with the beta. In the meanwhile, if you have any questions or thoughts about Shoperb, feel free to drop me a line.</p>
<h2>We&#8217;ve moved to a new office</h2>
<p>Secondly, we have moved and are now located in Delta Plaza that is just a few kilometers away from our last office in downtown Tallinn. We have been looking for a new office for quite a while and when the opportunity came, we decided quickly. About a week or two later we were already in our new office. Anyway, enough of this chit-chat &#8211; lets look at the photos.</p>
<p><img src="http://assets0.perfectline.ee/wp-content/uploads/coders-at-work.jpg" alt="" title="Coders at Work" width="536" height="356" class="alignnone size-full wp-image-142" style="border: 2px solid #ffffff; -moz-box-shadow: 0 0 5px rgba(0, 100, 130, 0.15); -webkit-box-shadow: 0 0 5px rgba(0, 100, 130, 0.15); box-shadow: 0 0 5px rgba(0, 100, 130, 0.15); margin: 0 -10px;" /><br />
<img src="http://assets1.perfectline.ee/wp-content/uploads/meetings-or-daily-power-napping.jpg" alt="" title="Meetings or Daily Power Napping" width="536" height="356" class="alignnone size-full wp-image-145" style="border: 2px solid #ffffff; -moz-box-shadow: 0 0 5px rgba(0, 100, 130, 0.15); -webkit-box-shadow: 0 0 5px rgba(0, 100, 130, 0.15); box-shadow: 0 0 5px rgba(0, 100, 130, 0.15); margin: 0 -10px;" /><br />
<img src="http://assets0.perfectline.ee/wp-content/uploads/lets-take-a-moment-for-few-games.jpg" alt="" title="Lets Take a Moment for Few Games" width="536" height="356" class="alignnone size-full wp-image-144" style="border: 2px solid #ffffff; -moz-box-shadow: 0 0 5px rgba(0, 100, 130, 0.15); -webkit-box-shadow: 0 0 5px rgba(0, 100, 130, 0.15); box-shadow: 0 0 5px rgba(0, 100, 130, 0.15); margin: 0 -10px;" /><br />
<img src="http://assets0.perfectline.ee/wp-content/uploads/desks-and-two-open-positions.jpg" alt="" title="Desks and Two Open Positions" width="536" height="356" class="alignnone size-full wp-image-143" style="border: 2px solid #ffffff; -moz-box-shadow: 0 0 5px rgba(0, 100, 130, 0.15); -webkit-box-shadow: 0 0 5px rgba(0, 100, 130, 0.15); box-shadow: 0 0 5px rgba(0, 100, 130, 0.15); margin: 0 -10px;" /><br />
<img src="http://assets2.perfectline.ee/wp-content/uploads/we-have-some-space-for-you.jpg" alt="" title="We Have Some Space for You" width="536" height="356" class="alignnone size-full wp-image-146" style="border: 2px solid #ffffff; -moz-box-shadow: 0 0 5px rgba(0, 100, 130, 0.15); -webkit-box-shadow: 0 0 5px rgba(0, 100, 130, 0.15); box-shadow: 0 0 5px rgba(0, 100, 130, 0.15); margin: 0 -10px;" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.perfectline.ee/blog/we-are-hiring-and-other-news/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Heroku Nightly Database Backups with Cron</title>
		<link>http://www.perfectline.ee/blog/heroku-nightly-database-backups-with-cron</link>
		<comments>http://www.perfectline.ee/blog/heroku-nightly-database-backups-with-cron#comments</comments>
		<pubDate>Fri, 19 Aug 2011 08:29:48 +0000</pubDate>
		<dc:creator>Tarmo Lehtpuu</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Cron]]></category>
		<category><![CDATA[Heroku]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://www.perfectline.ee/?p=140</guid>
		<description><![CDATA[I thought I&#8217;d share a quick tip how to do nightly database backups with Cron at Heroku. First you&#8217;ll need to enable Cron for your Heroku application. That can be done from Heroku control panel and the basic version is [...]]]></description>
			<content:encoded><![CDATA[<p>I thought I&#8217;d share a quick tip how to do nightly database backups with Cron at <a href="http://www.heroku.com/">Heroku</a>.</p>
<p><span id="more-140"></span></p>
<p>
First you&#8217;ll need to enable Cron for your Heroku application. That can be done from Heroku control panel and the basic version is free. It runs once per day which is enough for this use case.
</p>
<p>
The next thing you have to do is add the Heroku gem to your <b>Gemfile</b>:
</p>
<div class="codecolorer-container ruby dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">gem <span style="color:#996600;">'heroku'</span></div></div>
<p>The last step is to create <b>lib/tasks/cron.rake</b> and copy the below code:</p>
<div class="codecolorer-container ruby dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">HEROKU_USERNAME = <span style="color:#996600;">&quot;HEROKU_USERNAME&quot;</span><br />
HEROKU_API_KEY &nbsp;= <span style="color:#996600;">&quot;HEROKU_API_KEY&quot;</span><br />
HEROKU_APP &nbsp; &nbsp; &nbsp;= <span style="color:#996600;">&quot;HEROKU_APP&quot;</span><br />
<br />
task <span style="color:#ff3333; font-weight:bold;">:cron</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
<br />
&nbsp; <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;heroku&quot;</span><br />
&nbsp; <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;heroku/command&quot;</span><br />
&nbsp; <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;heroku/command/pgbackups&quot;</span><br />
<br />
&nbsp; <span style="color:#6666ff; font-weight:bold;">Heroku::Auth</span>.<span style="color:#9900CC;">credentials</span> = <span style="color:#006600; font-weight:bold;">&#91;</span>HEROKU_USERNAME, HEROKU_API_KEY<span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; <span style="color:#6666ff; font-weight:bold;">Heroku::Command</span>.<span style="color:#CC0066; font-weight:bold;">load</span><br />
&nbsp; <span style="color:#6666ff; font-weight:bold;">Heroku::Command::Pgbackups</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>, <br />
&nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#123;</span>:app <span style="color:#006600; font-weight:bold;">=&gt;</span> HEROKU_APP, <span style="color:#ff3333; font-weight:bold;">:expire</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">capture</span><br />
<br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></div>
<p>
You can get <code class="codecolorer ruby dawn"><span class="ruby">HEROKU_USERNAME</span></code> and <code class="codecolorer ruby dawn"><span class="ruby">HEROKU_API_KEY</span></code> from <b>~/heroku/.credentials</b>. Probably <code class="codecolorer ruby dawn"><span class="ruby">HEROKU_API_KEY</span></code> is just an hashed password and not really an API key, but it will work just fine :)
</p>
<p>
Just remember it&#8217;s not really public information so don&#8217;t use it in open source projects or anything big &#8211; it&#8217;s probably fine for personal and small projects where you are not worried about someone stealing your Heroku login &#8211; pretty much what the free Heroku package is for anyway.
</p>
<p>
With the shared database you are allowed 2 backups for free and the above script will always delete the oldest one before capturing a new backup. This means that you can have nightly backups with 2 days history for free.
</p>
<p>
Enjoy :)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.perfectline.ee/blog/heroku-nightly-database-backups-with-cron/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tips and Tricks for creating WordPress based websites</title>
		<link>http://www.perfectline.ee/blog/tips-and-tricks-for-creating-wordpress-based-websites</link>
		<comments>http://www.perfectline.ee/blog/tips-and-tricks-for-creating-wordpress-based-websites#comments</comments>
		<pubDate>Mon, 08 Aug 2011 11:25:59 +0000</pubDate>
		<dc:creator>Martin Kivi</dc:creator>
				<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Subversion]]></category>

		<guid isPermaLink="false">http://www.perfectline.ee/?p=90</guid>
		<description><![CDATA[In the past I&#8217;ve covered some technicalities on how to get yourself up and running for WordPress on Mac OS X based systems. This time around it&#8217;s time for some tips and tricks on how I do things with WordPress. [...]]]></description>
			<content:encoded><![CDATA[<p>In the past I&#8217;ve covered some technicalities on how to get yourself up and running for WordPress on Mac OS X based systems. This time around it&#8217;s time for some tips and tricks on how I do things with WordPress. I&#8217;m sure you&#8217;ll find some of these tips helpful as well.</p>
<p><span id="more-90"></span></p>
<h2>Lets keep it easy and maintainable</h2>
<p>WordPress works rather well for creating awesome websites. Even our own site is built on top of WordPress with some customization here and there. What should you keep in mind when you&#8217;re just starting your WordPress development career? I&#8217;m actually not going too much into the technical stuff (you need to become friends with WordPress code anyway) but instead I&#8217;ll share some tips and tricks that have worked well for me in the past.</p>
<h3>Clean start for a new project</h3>
<p>I&#8217;ve created a clean database dump that I can use to easily setup new project from scratch. It doesn&#8217;t have any posts, categories etc &#8211; just a blank skeleton that I can easily import.</p>
<p>If you do lot of themes then you probably want to create a skeleton theme that you base your other themes on. That&#8217;s what I did and it saves me bunch of time when starting with new projects.</p>
<h3>Version Control System (VCS) to use with WordPress</h3>
<p>Just one word &#8211; <strong>Git</strong>. If you&#8217;ve ever tried to use Subversion with WordPress then you&#8217;ll know that updating any plugins will mess up your live installation. Subversion keeps .svn folders in every folder that has been checked into VCS. When you update the plugin then the old version&#8217; folder will be deleted, zip file downloaded and the folder re-created. This time, without the .svn folder and we&#8217;ll have a problem.</p>
<h3>WordPress Core, themes and plugins</h3>
<p>All of the core files are kept in Git repository. When an update comes out I&#8217;ll just download it to my local development machine and make sure that it&#8217;s working fine with my plugins etc. From there on I&#8217;ll just push it to the repository and deploy to live system. Same pretty much applies to themes.
<p>When upgrading plugins, quite often a database update is needed as well. That&#8217;s one of the main reasons why I don&#8217;t keep the plugins in Git repository but instead upgrade them in our live system. Of course, first I&#8217;ll make sure that they work on my development system.</p>
<h3>Importing older versions made easy</h3>
<p>We&#8217;ve created a rake script that converts data from one messy WordPress database to a new and clean one. It pretty much takes over the content part of the database &#8211; posts, tags, categories etc. Helped me a lot to create this site in rather short time.</p>
<h3>W3 Total Cache for performance</h3>
<p>W3 Total Cache is your best friend for performance. All of our assets are hosted on Amazon AWS and served to you quickly. On top of that, you&#8217;ll get a good Google Page Speed score.</p>
<h3>Disable WordPress AutoSave and Post Revisions</h3>
<p>I find both of them to be highly annoying and usually turn them off as the first thing I do. There&#8217;s few lines that should be added before the end of <code class="codecolorer apache dawn"><span class="apache">wp-config.php</span></code>. Just before where it says &#8220;That&#8217;s all, stop editing! Happy blogging.&#8221; (and they mean that).</p>
<div class="codecolorer-container apache dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="apache codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">/** Set time for autosave **/<br />
define(<span style="color: #7f007f;">'AUTOSAVE_INTERVAL'</span>, <span style="color: #ff0000;">604800</span>);<br />
<br />
/** Disable post revisions **/<br />
define(<span style="color: #7f007f;">'WP_POST_REVISIONS'</span>, false);</div></div>
<h2>That&#8217;s all folks</h2>
<p>As you see, getting started with developing websites that are based on WordPress isn&#8217;t really rocket science. It&#8217;s always helpful if you&#8217;re already familiar with PHP and MySQL &#8211; makes your life with WordPress a lot easier.</p>
<p>If you have any comments or questions then just post them below here and I&#8217;ll update the post to answer these (or reply to your comment).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.perfectline.ee/blog/tips-and-tricks-for-creating-wordpress-based-websites/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cron tasks for your Rails application with Resque</title>
		<link>http://www.perfectline.ee/blog/cron-tasks-for-your-rails-application-with-resque</link>
		<comments>http://www.perfectline.ee/blog/cron-tasks-for-your-rails-application-with-resque#comments</comments>
		<pubDate>Thu, 28 Jul 2011 07:10:24 +0000</pubDate>
		<dc:creator>Tanel Suurhans</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Cron]]></category>
		<category><![CDATA[Resque]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://www.perfectline.ee/?p=137</guid>
		<description><![CDATA[The most common way to have cron tasks with your Rails application is to have a Rake task and configure it&#8217;s periodic execution in the crontab. This allows you to easily re-use any models and other code from your application, [...]]]></description>
			<content:encoded><![CDATA[<p>The most common way to have cron tasks with your Rails application is to have a Rake task and configure it&#8217;s periodic execution in the crontab.<br />
This allows you to easily re-use any models and other code from your application, making the development of the task itself relatively easy.<br />
Now while this is perfectly okay in most cases, there are time when this approach will <strong>do more harm than good</strong> and I will explain why.</p>
<p><span id="more-137"></span></p>
<p>Let&#8217;s take a theoretical example &#8211; you have a medium sized Rails application with a need to calculate statistics based on the data. This calculation has to be done often (like once per 10 minutes or once per hour) and it&#8217;s really not <strong>that</strong> expensive &#8211; let&#8217;s say it takes about 1500ms to complete.<br/><br />
Note that the calculation task itself is defined in a model and it uses various resources from the application, which means the taks has to <strong>load the whole application environment</strong>.</p>
<div class="codecolorer-container rails dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">namespace <span style="color:#ff3333; font-weight:bold;">:awesome</span><br />
&nbsp; task <span style="color:#ff3333; font-weight:bold;">:calculate</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:environment</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; Sales.<span style="color:#9900CC;">calculate_stats</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></div>
<p><em>I will skip the actual crontab definition as it would serve no purpose at this time.</em></p>
<p>Now this task will be ran every 10 minutes, and as it&#8217;s not really expensive, it doesn&#8217;t require much resources either. But what happens when this task runs during the peak hours of your application, when you have the most visitors?</p>
<p>As the task loads up your Rails application environment <strong>every single time the cron job is invoked</strong>, it will eat up HUGE amount of resources because booting the Rails environment is really expensive (and I mean <strong>really</strong> expensive). So even though the task itself is harmless, the rake task will cause spikes in your server load, which coupled with peak visitor hours will cause swapping and slow response times.</p>
<p>In our case, we had 3 different cron tasks, which ran in 5, 10 and 1 hour intervals. This means that every hour there were <strong>3 Rails environments booted and loaded and 2 environments every 10 minutes</strong>.<br />
You can imagine the strain this is putting on the application server. We saw response times up to 20 seconds because of <a href="http://en.wikipedia.org/wiki/Thrashing_(computer_science)">trashing</a>.</p>
<p>Some people suggested that I should use <a href="https://github.com/javan/whenever">Whenever</a> instead of plain old cron, but what they did not realize is that this gem just eases the process of defining cron tasks, but the end result of invoking the task is the same &#8211; the rake task loads the whole environment. The ultimate goal is to <strong>avoid booting up an extra Rails application environment</strong> and to re-use an instance already loaded in memory instead.</p>
<p>One of the first solutions I considered was having a separate, special controller which would contain the task specific logic and then invoke those controller actions from cronjobs via <a href="http://www.gnu.org/s/wget/">wget</a>.<br />
While this would achieve the ultimate goal of re-using an existing instance of the application environment (as the Passenger worker handling the request would already be bootstrapped), this felt somehow fragile<br />
and inefficient. Plus I&#8217;d have to deal with some extra security to prevent those actions from being accessed from the outside.</p>
<p>The other solution was to use <a href="https://github.com/bvandenbos/resque-scheduler">resque-scheduler</a> which let&#8217;s you to schedule tasks for <a href="https://github.com/defunkt/resque">Resque</a>  similar to crontab. And we are already using it for several background jobs anyhow.</p>
<p>The way Resque scheduler works is it runs a separate scheduler worker, which polls the configured schedules after every 5 seconds and checks if there are any tasks that should be ran. If any are found, it looks up the task definition and pushes the task to the configured queue for <strong>Resque</strong> to handle. From here on everything is handled like a regular background job.</p>
<p>In case you are not familiar with <strong>Resque</strong>, I&#8217;ll briefly explain how it works in general. Basically you take a piece of code you want to execute asynchronously and queue it with <strong>Resque</strong>. Jobs are stored in <a href="http://redis.io">Redis</a>, with the ability to define multiple different queues and also set a specific queue per task. To process the tasks, you run worker processes, which can monitor one or multiple queues and execute any tasks found in them.</p>
<p>Booting up a worker process loads the whole Rails environment into memory and the process itself will running infinitely until you shut it down. This fits our needs perfectly, as we can queue any number of tasks we would otherwise run from cron, and there would be zero bootstrapping overhead. The only thing left now is to configure the scheduler.</p>
<p>I will provide the original cron configuration and the whole scheduler setup by code examples.</p>
<div class="codecolorer-container rails dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># Gemfile</span><br />
<br />
gem <span style="color:#996600;">&quot;resque&quot;</span><br />
gem <span style="color:#996600;">&quot;resque-scheduler&quot;</span></div></div>
<div class="codecolorer-container rails dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># config/initializers/resque.rb</span><br />
<br />
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'resque'</span><br />
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'resque_scheduler'</span><br />
<br />
config = <span style="color:#CC00FF; font-weight:bold;">YAML</span>.<span style="color:#9900CC;">load_file</span><span style="color:#006600; font-weight:bold;">&#40;</span>Rails.<span style="color:#9900CC;">root</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'config'</span>, <span style="color:#996600;">'resque.yml'</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
schedule = <span style="color:#CC00FF; font-weight:bold;">YAML</span>.<span style="color:#9900CC;">load_file</span><span style="color:#006600; font-weight:bold;">&#40;</span>Rails.<span style="color:#9900CC;">root</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'config'</span>, <span style="color:#996600;">'schedule.yml'</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
<br />
<span style="color:#008000; font-style:italic;"># configure redis connection</span><br />
Resque.<span style="color:#9900CC;">redis</span> = config<span style="color:#006600; font-weight:bold;">&#91;</span>Rails.<span style="color:#9900CC;">env</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
<br />
<span style="color:#008000; font-style:italic;"># configure the schedule</span><br />
Resque.<span style="color:#9900CC;">schedule</span> = schedule<br />
<br />
<span style="color:#008000; font-style:italic;"># set a custom namespace for redis (optional)</span><br />
Resque.<span style="color:#9900CC;">redis</span>.<span style="color:#9900CC;">namespace</span> = <span style="color:#996600;">&quot;resque:myapp&quot;</span></div></div>
<div class="codecolorer-container yaml dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="yaml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: blue;"># config/resque.yml </span><br />
<span style="color: green;"><br />
development</span><span style="font-weight: bold; color: brown;">: </span>localhost:<span style="">6379</span><span style="color: green;"><br />
staging</span><span style="font-weight: bold; color: brown;">: </span>localhost:<span style="">6379</span><span style="color: green;"><br />
test</span><span style="font-weight: bold; color: brown;">: </span>localhost:<span style="">6379</span><span style="color: green;"><br />
production</span><span style="font-weight: bold; color: brown;">: </span>production_db_server_address:<span style="">6379</span></div></div>
<div class="codecolorer-container yaml dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="yaml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: blue;"># config/schedule.yml</span><br />
<span style="color: #007F45;"><br />
calculate</span>:<span style="color: green;"><br />
&nbsp; cron</span><span style="font-weight: bold; color: brown;">: </span><span style="color: #CF00CF;">&quot;*/10 * * * *&quot;</span><span style="color: green;"><br />
&nbsp; queue</span><span style="font-weight: bold; color: brown;">: </span>cron<span style="color: green;"><br />
&nbsp; class</span><span style="font-weight: bold; color: brown;">: </span>CronTask<span style="color: green;"><br />
&nbsp; args</span><span style="font-weight: bold; color: brown;">: </span><span style="color: #CF00CF;">&quot;calculate&quot;</span><span style="color: green;"><br />
&nbsp; description</span><span style="font-weight: bold; color: brown;">: </span>Calculates stats<span style="color: green;"><br />
&nbsp; rails_envs</span><span style="font-weight: bold; color: brown;">: </span>development, production, staging</div></div>
<p>Note that all <strong>Resque</strong> tasks must implement the class method <code class="codecolorer rails dawn"><span class="rails"><span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">perform</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span></span></code>, which is invoked when the task is processed.<br />
I preferred to group all my cron tasks into one single class <code class="codecolorer rails dawn"><span class="rails">CronTask</span></code> and work a little magic to handle all of them from single point of invocation.</p>
<div class="codecolorer-container rails dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># app/tasks/cron_task.rb</span><br />
<span style="color:#008000; font-style:italic;"># I also included a simple logging functionality, </span><br />
<span style="color:#008000; font-style:italic;"># along with benchmarking, which allows you to get </span><br />
<span style="color:#008000; font-style:italic;"># a pretty good idea how long your tasks run etc.</span><br />
<br />
<span style="color:#9966CC; font-weight:bold;">class</span> CronTask<br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#0000FF; font-weight:bold;">self</span><br />
<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> perform<span style="color:#006600; font-weight:bold;">&#40;</span>method<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; with_logging method <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#5A0A0A; font-weight:bold;">new</span>.<span style="color:#9900CC;">send</span><span style="color:#006600; font-weight:bold;">&#40;</span>method<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> with_logging<span style="color:#006600; font-weight:bold;">&#40;</span>method, <span style="color:#006600; font-weight:bold;">&amp;</span>block<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; log<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;starting...&quot;</span>, method<span style="color:#006600; font-weight:bold;">&#41;</span><br />
<br />
&nbsp; &nbsp; &nbsp; time = <span style="color:#CC00FF; font-weight:bold;">Benchmark</span>.<span style="color:#9900CC;">ms</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">yield</span> block<br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp; &nbsp; log<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;completed in (%.1fms)&quot;</span> <span style="color:#006600; font-weight:bold;">%</span> <span style="color:#006600; font-weight:bold;">&#91;</span>time<span style="color:#006600; font-weight:bold;">&#93;</span>, method<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> log<span style="color:#006600; font-weight:bold;">&#40;</span>message, method = <span style="color:#0000FF; font-weight:bold;">nil</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; now = <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span>.<span style="color:#9900CC;">strftime</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;%Y-%m-%d %H:%M:%S&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;#{now} %s#%s - #{message}&quot;</span> <span style="color:#006600; font-weight:bold;">%</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">name</span>, method<span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> calculate<br />
&nbsp; &nbsp; Sales.<span style="color:#9900CC;">calculate_stats</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> some_other_task<br />
&nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># logic here</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></div>
<p>The logic behind this implementation is pretty easy &#8211; you define your job class, queue name and cron schedule in the <code class="codecolorer rails dawn"><span class="rails">schedule.<span style="color:#9900CC;">yml</span></span></code> file and when the task is queued for processing, the <code class="codecolorer rails dawn"><span class="rails"><span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">process</span></span></code> method is invoked with the method name as it&#8217;s argument. This will in turn create a new instance of <code class="codecolorer rails dawn"><span class="rails">CronTask</span></code>, and invoke the method that was passed to <code class="codecolorer rails dawn"><span class="rails"><span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">perform</span></span></code>. Simple and effective.</p>
<p>&#8220;So how big of an optimization was it?&#8221; you may ask. This image should speak for itself &#8211; it&#8217;s the application servers load for the last 24 hours (those big spikes are deployments and application server restarts).</p>
<p><a href="http://assets2.perfectline.ee/wp-content/uploads/graphs.png"><img src="http://assets2.perfectline.ee/wp-content/uploads/graphs.png" alt="" title="24 hour load" width="520" height="155" class="alignnone size-full wp-image-138" /></a></p>
<p>The application went <strong>from choking on peak hours to almost completely idle</strong>. The improvement in response times and in general performance was huge that it actually baffles me how this issue is overlooked in most of the discussions of about how to handle cron tasks with Rails applications.</p>
<p>If your periodical tasks do not run that often, or they run during idle hours (when there is next to no traffic), you are probably okay with using a simple cron/rake solution. But if you have tasks that run often, and even more if there are several of them, I strongly suggest checking out <strong>Resque</strong> and <strong>resque-scheduler</strong> and hopefully this post will be of help understanding and configuring it for your application</p>
<p>If you have any questions or notes about this post, please leave a comment.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.perfectline.ee/blog/cron-tasks-for-your-rails-application-with-resque/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Rails 3.1 and asset pipeline</title>
		<link>http://www.perfectline.ee/blog/rails-3-1-and-asset-pipeline</link>
		<comments>http://www.perfectline.ee/blog/rails-3-1-and-asset-pipeline#comments</comments>
		<pubDate>Thu, 02 Jun 2011 09:11:55 +0000</pubDate>
		<dc:creator>Tanel Suurhans</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://www.perfectline.ee/?p=134</guid>
		<description><![CDATA[When we heard the announcement of Ruby on Rails 3.1 RC, we agreed that we upgrade one of our internal applications and check out all of the new features. This of course meant porting all of our asset packing and [...]]]></description>
			<content:encoded><![CDATA[<p>When we heard the announcement of <strong>Ruby on Rails 3.1 RC</strong>, we agreed that we upgrade one of our internal applications and check out all of the new features.<br />
This of course meant porting all of our asset packing and management from <a href="http://documentcloud.github.com/jammit/">Jammit</a> to <a href="https://github.com/sstephenson/sprockets">Sprockets</a> backed asset pipeline. Everything didn&#8217;t go as smooth as expected though.</p>
<p><span id="more-134"></span></p>
<p>The first issue I encountered with assets was that they were only concatenated in production, but not minimized or packed or anything like that. Now as we didn&#8217;t generate a new blank Rails 3.1 application, we missed out on some critical configuration variables (and the documentation on the new stuff is understandably pretty sparse at the moment). So to enable any kind of compression for your assets, you need to add the following configuration statements to your <strong>environment specific configuration file</strong> (these are default values in 3.1 applications).</p>
<div class="codecolorer-container rails dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; config.<span style="color:#9900CC;">assets</span>.<span style="color:#9900CC;">js_compressor</span> &nbsp;= <span style="color:#ff3333; font-weight:bold;">:uglifier</span><br />
&nbsp; config.<span style="color:#9900CC;">assets</span>.<span style="color:#9900CC;">css_compressor</span> = <span style="color:#ff3333; font-weight:bold;">:scss</span></div></div>
<p>I did a little of poking around in the source and it seems that in addition to <a href="https://github.com/lautis/uglifier">Uglifier</a>, you can also use <a href="https://github.com/sstephenson/ruby-yui-compressor">YUI Compressor</a> and <a href="https://github.com/documentcloud/closure-compiler">Closure Compiler</a> as Javascript compressor backends.
</p>
<p>Now the second issue was a bit more weird &#8211; only a really small subset of the assets were being compiled with <code class="codecolorer rails dawn"><span class="rails">rake assets:precompile</span></code>.<br />
I spent quite a lot of time tracking the cause for this behavior and finally stumbled upon the configuration for the assets feature:</p>
<div class="codecolorer-container rails dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color:#0066ff; font-weight:bold;">@assets</span>.<span style="color:#9900CC;">precompile</span> = <span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#006600; font-weight:bold;">/</span>\w<span style="color:#006600; font-weight:bold;">+</span>\.<span style="color:#006600; font-weight:bold;">&#40;</span>?!js<span style="color:#006600; font-weight:bold;">|</span>css<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#006600; font-weight:bold;">+/</span>, <span style="color:#996600;">&quot;application.js&quot;</span>, <span style="color:#996600;">&quot;application.css&quot;</span> <span style="color:#006600; font-weight:bold;">&#93;</span></div></div>
<p>The regexp is meant to find all of the <strong>non-css and non-js files</strong> in the asset paths and compile them &#8211; I&#8217;m guessing that this is mainly to handle <a href="https://github.com/chriseppstein/sass">SCSS</a> and <a href="http://jashkenas.github.com/coffee-script/">CoffeScript</a> files (again the documentation is hard to come by).<br />
As an unexpected side-effect it&#8217;s matching files like <strong>jquery.min.js</strong> and <strong>jquery.autocomplete.js</strong>, but not top-level assets like <strong>admin.js</strong>, which does not really seem to be the desired behavior.
</p>
<p>There are basically two ways asset compiling would make sense:</p>
<ul>
<li><strong>All of your assets get compiled:</strong> every single file from the asset path &#8211; from plain .css to .scss and .coffee files and manifests &#8211; get compiled and compressed. Then you just use whatever assets you like in your layouts.<br/><br/></li>
<li><strong>Only the top-level manifests are compiled:</strong> this means the files you are explicitly linking in your layouts, stuff like application.js and admin.css and so on.</li>
</ul>
<p>
Considering that you have top-level manifest files that group all of your dependencies, you rarely need to just use one single asset so I decided to go with the second option.<br />
In order to only compile the top-level manifest files, you need to avoid the built-in regexp from being run and define the files your want to compile manually.</p>
<div class="codecolorer-container rails dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color:#008000; font-style:italic;"># config/environments/production.rb</span><br />
&nbsp; <span style="color:#008000; font-style:italic;"># just list all of your top level assets here</span><br />
&nbsp; config.<span style="color:#9900CC;">assets</span>.<span style="color:#9900CC;">precompile</span> = <span style="color:#006600; font-weight:bold;">%</span>w<span style="color:#006600; font-weight:bold;">&#40;</span> admin.<span style="color:#9900CC;">js</span> admin.<span style="color:#9900CC;">css</span><span style="color:#006600; font-weight:bold;">&#41;</span></div></div>
<p>This does seem a bit verbose (especially if you have lots of top level manifests), but I prefer this over the default broken solution or a mess of files that compiling every single asset would result in.
</p>
<h2>Still not satisfied</h2>
<p>There is one more thing that bugs me about the asset pipeline in Ruby on Rails 3.1 &#8211; if you reference a manifest file in your layouts in development mode, you will get a <strong>concatenated resource</strong> as the output.</p>
<p>
If you are requiring a lot of different files in your manifest, it will most definitely be annoying to debug your javascripts/stylesheets. This is where <strong>Jammit</strong> really outperforms Sprockets &#8211; you define<br />
a resource (basically the same as a manifest) and in development mode that resource is expanded into separate files, making debugging really easy as you know exactly which file you need to check etc.<br />
And in production the same resource is concatenated and compressed into one single, small file.</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">&lt;!-- development --&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/javascripts/admin/foo.js&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/javascripts/admin/bar.js&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a>&gt;</span><br />
<br />
<span style="color: #808080; font-style: italic;">&lt;!-- production --&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/assets/admin.js?1295621337&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a>&gt;</span></div></div>
<p>I feel this is the way how assets should work in Rails 3.1 by default also &#8211; the benefit is pretty clear, at least for me.
</p>
<p>
  <strong>Update:</strong> So it seems you can avoid having your assets being concatenated in development like this:</p>
<div class="codecolorer-container rails dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color:#5A0A0A; font-weight:bold;">javascript_include_tag</span> <span style="color:#ff3333; font-weight:bold;">:admin</span>, <span style="color:#ff3333; font-weight:bold;">:debug</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><br />
<br />
&nbsp; <span style="color:#008000; font-style:italic;"># or if you want to have debugging on automatically in development</span><br />
&nbsp; <span style="color:#5A0A0A; font-weight:bold;">javascript_include_tag</span> <span style="color:#ff3333; font-weight:bold;">:admin</span>, <span style="color:#ff3333; font-weight:bold;">:debug</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> Rails.<span style="color:#9900CC;">env</span>.<span style="color:#9900CC;">development</span>?</div></div>
<p>Thanks for the tip, Bruno Michel!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.perfectline.ee/blog/rails-3-1-and-asset-pipeline/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Welcome aboard, Kuldar Kalvik</title>
		<link>http://www.perfectline.ee/blog/welcome-aboard-kuldar-kalvik</link>
		<comments>http://www.perfectline.ee/blog/welcome-aboard-kuldar-kalvik#comments</comments>
		<pubDate>Thu, 26 May 2011 13:09:18 +0000</pubDate>
		<dc:creator>Martin Kivi</dc:creator>
				<category><![CDATA[PerfectLine]]></category>
		<category><![CDATA[Team]]></category>
		<category><![CDATA[User Interface Designer]]></category>

		<guid isPermaLink="false">http://www.perfectline.ee/?p=131</guid>
		<description><![CDATA[I&#8217;m pleased to introduce a new member to the PerfectLine team, Kuldar Kalvik, as our User Interface Designer. He&#8217;s going to bring some of that new creative air to our team that hopefully will make our apps even more awesome. [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m pleased to introduce a new member to the PerfectLine team, Kuldar Kalvik, as our User Interface Designer. He&#8217;s going to bring some of that new creative air to our team that hopefully will make our apps even more awesome.<span id="more-131"></span></p>
<p><img src="http://assets0.perfectline.ee/wp-content/uploads/kuldar-kalvik.jpg" alt="Kuldar Kalvik" title="Kuldar Kalvik - User Interface Designer at PerfectLine" width="536" height="260" style="border: 2px solid #ffffff; -moz-box-shadow: 0 0 5px rgba(0, 100, 130, 0.15); -webkit-box-shadow: 0 0 5px rgba(0, 100, 130, 0.15); box-shadow: 0 0 5px rgba(0, 100, 130, 0.15); margin: 0 -10px;" /></p>
<p>His previous work experience includes a small design agency and bunch of freelance experience. Over the years he has created wonderful website, user interfaces and logo designs (and lets not forget the iOS user interfaces). </p>
<p>His first task at PerfectLine is to give <a href="http://www.photry.com">Photry</a> a new, better looking face. Thanks to his design and excellent collaborative skills, Photry will become better service that I hope you&#8217;ll enjoy. More about the work we&#8217;re doing with Photry in my next post.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.perfectline.ee/blog/welcome-aboard-kuldar-kalvik/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adobe Reader Protected Mode</title>
		<link>http://www.perfectline.ee/blog/adobe-reader-protected-mode</link>
		<comments>http://www.perfectline.ee/blog/adobe-reader-protected-mode#comments</comments>
		<pubDate>Tue, 12 Apr 2011 08:56:43 +0000</pubDate>
		<dc:creator>Tarmo Lehtpuu</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Adobe]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://www.perfectline.ee/?p=129</guid>
		<description><![CDATA[Adobe Reader Protected mode is a new security sandbox feature in Adobe Reader 10. For Reader plugin maintainers it&#8217;s can be a huge nightmare, I just wanted to share some of my findings with you in the hopes it saves [...]]]></description>
			<content:encoded><![CDATA[<p>Adobe Reader Protected mode is a new security sandbox feature in Adobe Reader 10. For Reader plugin maintainers it&#8217;s can be a huge nightmare, I just wanted to share some of my findings with you in the hopes it saves someone a few hours of head scratching.<br />
<span id="more-129"></span></p>
<h2>What&#8217;s allowed by default</h2>
<p>The sandbox disables almost everything by default. The two major exceptions are that reading/writing to <em>%TEMP%</em> is allowed and reading from the registry is allowed. If this is all your plugin needs you are lucky :) </p>
<p><a href="http://blogs.adobe.com/asset/2010/11/inside-adobe-reader-protected-mode-part-3-broker-process-policies-and-inter-process-communication.html">Part 3</a> of Inside Adobe Reader Protected Mode discusses the whitelisted features in more detail. <a href="http://blogs.adobe.com/asset/2010/10/inside-adobe-reader-protected-mode-part-1-design.html">Part 1</a>, <a href="http://blogs.adobe.com/asset/2010/10/inside-adobe-reader-protected-mode-%E2%80%93-part-2-%E2%80%93-the-sandbox-process.html">Part 2</a> and <a href="http://blogs.adobe.com/asset/2010/11/inside-adobe-reader-protected-mode-part-4-the-challenge-of-sandboxing.html">Part 4</a> are also worth reading for more background information on protected mode.</p>
<h2>What&#8217;s possible</h2>
<p>Fortunately it&#8217;s possible to customize the very restrictive default policies. </p>
<p>The Inside Protected Mode series indicates that there seems to be some sort of API to customize the sandbox rules (<em>AddRule()</em> examples), however it seems yet to be released or it doesn&#8217;t even exist (which kind of makes sense from a security point of view).</p>
<p>Fortunately there&#8217;s another way: <em>ProtectedModeWhiteList.txt</em>.</p>
<p><em>ProtectedModeWhitelist.txt</em> must be in the same directory as <em>AcroRd32.exe</em> (<em>HKLM\Software\Adobe\Acrobat Reader\10.0\InstallPath</em>).</p>
<p>It must also be enabled by creating the following registry key <em>bUseWhitelistConfigFile</em> (type: <em>DWORD</em>, value: <em>0&#215;1</em>) under <em>HKLM\SOFTWARE\Policies\Adobe\Acrobat\Reader\10.0\FeatureLockDown</em>.</p>
<p>After enabling the usage of whitelist config we can define our own custom policies that allow the plugin to read/write to any location on the filesystem or any location in the registry.</p>
<h3>Adding registry exceptions</h3>
<p><em>REG_ALLOW_ANY = HKEY_CURRENT_USER\Software\MyPlugin</em></p>
<h3>Adding filesystem exceptions</h3>
<p><em>FILES_ALLOW_ANY = %APPDATA%\MyPlugin\data.txt</em></p>
<p>There are actually a few more things that can be allowed using this file, see <a href="http://learn.adobe.com/wiki/download/attachments/64389123/AcrobatApplicationSecurity.pdf?version=1">Adobe Application Security</a> for more details.</p>
<h2>Debugging Protected Mode</h2>
<p>If you are having a problem with Reader X that doesn&#8217;t exist in Reader 9 or Reader 8 then Protected Mode is a very likely cause. </p>
<p>The first thing you should do is to try disable Protected Mode and see if the problem continues to exist. To do that uncheck <em>Edit -> Preferences -> General -> Enable Protected Mode at startup</em>.</p>
<p>When you have determined that the problem is really caused by Protected Mode the next thing you should do is enable Protected Mode Log file. To that check <em>Edit -> Preferences -> General -> Create Protected Mode log file</em>. </p>
<p>With this file enabled you can see most things being denied by Protected Mode and hopefully it will also recommend a rule to add to <em>ProtectedModeWhitelist.txt</em>.</p>
<h2>What&#8217;s impossible</h2>
<p>Also there are a few things that I&#8217;ve found impossible to do with Protected Mode enabled.</p>
<p>First it seems to be impossible to use the Windows Help system. It seems that the call to HtmlHelp() wants to launch an external process and it gets denied silently by Protected Mode. Another thing that seems impossible is reading proxy settings stored by Internet Explorer. </p>
<p>I have tried creating <em>ProtectedModeWhitelist.txt</em> rules that allow almost anything (events, process exec, files, registry etc.) and have no ACCESS_DENIED lines in there &#8211; but it still doesn&#8217;t help. When disabling Protected Mode everything works fine so those things somehow get blocked silently.</p>
<p>The general rule seems to be: don&#8217;t try to talk to other processes :)</p>
<h2>Conclusion</h2>
<p>Last thing I would like to mention is that when creating <em>ProtectedModeWhitelist.txt</em> files (probably by your plugin installer) &#8211; be nice and leaving the existing rules there, don&#8217;t overwrite anything. </p>
<p>Hope this was useful to someone and don&#8217;t be shy to leave comments if you discover something more about Protected Mode :)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.perfectline.ee/blog/adobe-reader-protected-mode/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using apc (Feed is rejected)
Page Caching using apc
Database Caching 1/35 queries in 0.011 seconds using apc
Object Caching 1971/2066 objects using apc
Content Delivery Network via Amazon Web Services: CloudFront: assets0.perfectline.ee

Served from: www.perfectline.ee @ 2012-02-22 19:17:24 -->
