<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
 
 <title>New Forge Technologies</title>
 
 <link href="http://blog.newforge-tech.com/" />
 <updated>2010-08-04T10:18:18-04:00</updated>
 <id>http://blog.newforge-tech.com/</id>
 <author>
   <name>New Forge Technologies Blog</name>
   <email>support@newforge-tech.com</email>
 </author>

 
 <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/NewForgeTechnologies" /><feedburner:info uri="newforgetechnologies" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:browserFriendly></feedburner:browserFriendly><entry>
   <title>Realized on Hacker News</title>
   <link href="http://blog.newforge-tech.com/news/2010/08/04/hacker-news-invite.html" />
   <updated>2010-08-04T10:15:00-04:00</updated>
   <id>http://blog.newforge-tech.com/news/2010/08/04/hacker-news-invite</id>
   <content type="html">&lt;p&gt;Today, I am inviting readers of &lt;a href='http://news.ycombinator.com/'&gt;Hacker News&lt;/a&gt; to sign up for &lt;a href='http://realized-app.com'&gt;Realized&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To start using Realized now, sign up at &lt;a href='http://realized-app.com'&gt;http://realized-app.com&lt;/a&gt;. If you have a few minutes, check out the &lt;a href='http://realized-app.com/tour'&gt;product tour&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;What is Realized?&lt;/h3&gt;
&lt;p&gt;Realized is a web app for investors who want to get higher returns by lowering their investment costs. And the biggest costs are &lt;strong&gt;not&lt;/strong&gt; commissions or management fees, but rather capital gains tax.&lt;/p&gt;
&lt;p&gt;If you are an individual investor or financial advisor, you may have already found it surprisingly difficult to manage your stock portfolio on the web. Most financial web sites are devoted to what might be called the &lt;strong&gt;buy&lt;/strong&gt; side of investing. Financial analysts love to recommend stocks. Buying is easy and nearly cost free, with online brokerages and low commissions. Everybody has thousands of choices: stocks, ETFs and mutual funds.&lt;/p&gt;

&lt;h3&gt;The sell side is what generates the real costs&lt;/h3&gt;
&lt;p&gt;Almost no one provides guidance about when and what to &lt;strong&gt;sell&lt;/strong&gt; from your portfolio. But selling is specific to only those securities that you already hold. Selling also generates taxable capital gains. Selling the wrong security at the wrong time can have a catastrophic effect on your rate of return.&lt;/p&gt;
&lt;p&gt;Managing a portfolio well requires real discipline with regard to selling securities.&lt;/p&gt;

&lt;h3&gt;Forget about timing the market: focus on timing your portfolio&lt;/h3&gt;
&lt;p&gt;By netting out gains and losses, most investors can sharply lower their tax burden. Turning unrealized into actual losses allows for other sales to become literally tax free.&lt;/p&gt;
&lt;p&gt;Most investment finance software concentrates on calculating capital gains tax at the end of the year. You find out where you stand after the fact. By that time, it may be too late to offset gains with losses. You are stuck with the capital gains tax that might have been avoided.&lt;/p&gt;
&lt;p&gt;&lt;a href='http://realized-app.com'&gt;Realized&lt;/a&gt; aims to change things.&lt;/p&gt;
&lt;p&gt;Individual investors and financial advisors need a tool that helps them avoid making trades that cost dearly. &lt;a href='http://realized-app.com'&gt;Realized&lt;/a&gt; does just that, making stock investing and capital gains tax simple and straightforward, year-round.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Launch of Realized-app</title>
   <link href="http://blog.newforge-tech.com/news/2010/07/30/realized-launch.html" />
   <updated>2010-07-30T11:45:00-04:00</updated>
   <id>http://blog.newforge-tech.com/news/2010/07/30/realized-launch</id>
   <content type="html">&lt;p&gt;Yesterday we launched &lt;a href='http://realized-app.com'&gt;Realized-app.com&lt;/a&gt; in a no cost, preview phase.&lt;/p&gt;
&lt;p&gt;As &lt;a href='http://localhost:4000/strategy/2009/07/26/startup-ideas-like-fund.html'&gt;previously&lt;/a&gt; mentioned, &lt;a href='http://realized-app.com'&gt;Realized-app&lt;/a&gt; began as a simple &lt;a href='http://rubyonrails.org/'&gt;Ruby on Rails&lt;/a&gt; demonstration project. Quickly the proof of concept became a viable app, due mainly to the developer productivity that Rails provides.&lt;/p&gt;
&lt;p&gt;For a preview of its capabilities, check out the &lt;a href='http://realized-app.com/tour'&gt;product tour&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With nearly 60 models in this release, &lt;a href='http://realized-app.com'&gt;Realized-app&lt;/a&gt; represents a relatively modest Rails app. For those developers who would like to explore the app, you are welcome to &lt;a href='http://www.realized-app.com/signup'&gt;sign up for free&lt;/a&gt; and try it.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Workflow for Realized-app support</title>
   <link href="http://blog.newforge-tech.com/strategy/2010/06/28/workflow-realized-app-support.html" />
   <updated>2010-06-28T15:45:00-04:00</updated>
   <id>http://blog.newforge-tech.com/strategy/2010/06/28/workflow-realized-app-support</id>
   <content type="html">&lt;p&gt;&lt;a href='http://www.squarespace.com/'&gt;Squarespace&lt;/a&gt; has an extensive &lt;a href='http://manual.squarespace.com/'&gt;user manual&lt;/a&gt;. Beginning users can easily find a &lt;a href='http://manual.squarespace.com/squarespace-basics'&gt;Getting Started&lt;/a&gt; section. A searchable set of &lt;a href='http://manual.squarespace.com/faqs'&gt;how-to articles and FAQ&lt;/a&gt; answer questions from more experienced users.&lt;/p&gt;
&lt;p&gt;When we explored alternative platforms for &lt;a href='https://realized.tenderapp.com/home'&gt;Realized-app support&lt;/a&gt;, we wanted to emulate Squarespace as a starting point. We anticipated that a typical need for support might pass through three stages:&lt;/p&gt;
&lt;ul class='smpl'&gt;
	&lt;li&gt;Reading the manual&lt;/li&gt;
	&lt;li&gt;Searching the forums for similar issues&lt;/li&gt;
	&lt;li&gt;Asking a question via email&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One aspect of &lt;a href='http://www.tenderapp.com/'&gt;Tender&lt;/a&gt; stood out from the other SaaS providers. It provides a searchable knowledge base to &lt;a href='http://tenderapp.com/tour/help/'&gt;'Help your customers help themselves'&lt;/a&gt;. After seeing that feature, other platforms seemed to be just combinations of forums and email managers.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Fancybox screenshots with jQuery</title>
   <link href="http://blog.newforge-tech.com/technical/2010/05/08/fancybox-screenshots-jquery.html" />
   <updated>2010-05-08T12:30:00-04:00</updated>
   <id>http://blog.newforge-tech.com/technical/2010/05/08/fancybox-screenshots-jquery</id>
   <content type="html">&lt;p&gt;In late April, we added screenshots to the &lt;a href='http://www.realized-app.com/tour'&gt; Realized-app product tour&lt;/a&gt;. Our design drew upon an idea we saw at &lt;a href='http://agilezen.com/'&gt;AgileZen.com&lt;/a&gt;, where clicking a thumbnail expands into a larger screenshot lightbox.&lt;/p&gt;
&lt;p&gt;The &lt;a href='http://realized-app.com'&gt;Realized-app&lt;/a&gt; already makes use of &lt;a href='http://jquery.com/'&gt;jQuery&lt;/a&gt;, mainly for client-side processing of stock ticker choices. To animate our screenshots, we adopted the jQuery plugin that AgileZen uses, &lt;a href='http://fancybox.net/'&gt;Fancybox&lt;/a&gt;. Our configuration:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;ready&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;.fancybox &amp;gt; a&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;fancybox&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;hideOnContentClick&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;titleShow&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;transitionIn&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;elastic&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;transitionOut&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;elastic&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;speedIn&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;speedOut&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;easingIn&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;easeInOutExpo&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;easingOut&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;easeInOutExpo&amp;#39;&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;One interesting aspect of configuring Fancybox is its support of the &lt;a href='http://gsgd.co.uk/sandbox/jquery/easing/'&gt;Easing&lt;/a&gt; plugin to control the transitions. Easing controls how an animation progresses over time by varying its acceleration, giving each transition a more natural effect.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Remove functionality to improve usability</title>
   <link href="http://blog.newforge-tech.com/strategy/2010/03/10/remove-functionality-improve-usability.html" />
   <updated>2010-03-10T10:00:00-05:00</updated>
   <id>http://blog.newforge-tech.com/strategy/2010/03/10/remove-functionality-improve-usability</id>
   <content type="html">&lt;p&gt;The stock of ABC (AmerisourceBergen Corp) split 2 for 1 on June 15, 2009. The split doubled the number of shares that each of the thousands of ABC stockholders held. For those tracking their investments with Quicken, each would then need to enter a transaction to record the stock split.&lt;/p&gt;
&lt;p&gt;Having each of our customers enter the same publicly available information about a stock split seems like a missed opportunity. If &lt;a href='http://realized-app.com'&gt;Realized-app&lt;/a&gt; stored the stock split once, then why should it ever need to be entered again?&lt;/p&gt;
&lt;h3&gt;Realized automatically applies stock splits&lt;/h3&gt;
&lt;p&gt;As an example, two investors have purchased ABC stock. The first bought 100 shares on March 1, 2009 (before the stock split). The second bought 200 shares last week. Today, each holds 200 shares.&lt;/p&gt;
&lt;p&gt;How does the share quantity of the first investor get adjusted for the split? The &lt;a href='http://realized-app.com'&gt;Realized-app&lt;/a&gt; already stores stock split info. Rather than asking the first investor to record the stock split, the &lt;a href='http://realized-app.com'&gt;Realized-app&lt;/a&gt; applies the stock split to that holding during the  &lt;a href='http://blog.realized-app.com/tax-lot/'&gt;tax lot&lt;/a&gt; setup process.&lt;/p&gt;
&lt;h3&gt;Better usability&lt;/h3&gt;
&lt;p&gt;Because a web app uses a common data store, it can share public information among individual accounts. By reusing the specifics about a stock split among all of our users, &lt;a href='http://realized-app.com'&gt;Realized-app&lt;/a&gt; has removed one source of redundant or erroneous data input. In effect, we have improved the usability by removing the functionality of recording a stock split.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Git workflow for a staging environment with Heroku and GitHub</title>
   <link href="http://blog.newforge-tech.com/technical/2010/02/01/git-workflow.html" />
   <updated>2010-02-01T13:30:00-05:00</updated>
   <id>http://blog.newforge-tech.com/technical/2010/02/01/git-workflow</id>
   <content type="html">&lt;p&gt;Having a staging environment to verify changes adds an extra measure of confidence to each deployment. &lt;a href='http://git-scm.com/'&gt;Git&lt;/a&gt; is the primary means for deploying apps to Heroku. For &lt;a href='http://www.heroku.com'&gt;Heroku&lt;/a&gt;, a staging environment corresponds to another app. For Git, it is just a branch.&lt;/p&gt;
&lt;p&gt;&lt;a href='http://suitmymind.com/'&gt;Thomas Balthazar&lt;/a&gt; has written a full outline of how to &lt;a href='http://suitmymind.com/blog/2009/06/02/deploying-multiple-environments-on-heroku-while-still-hosting-code-on-github'&gt; deploy multiple environments on Heroku and still host your code on GitHub&lt;/a&gt;. With the Heroku and &lt;a href='http://github.com'&gt;GitHub&lt;/a&gt; repos thus configured, our local repo has three branches:&lt;/p&gt;
&lt;ul class='smpl'&gt;
	&lt;li&gt;Working&lt;/li&gt;
	&lt;li&gt;Staging&lt;/li&gt;
	&lt;li&gt;Production (master)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Why do we use Git?&lt;/h3&gt;
&lt;p&gt;We build and test all changes in the Working branch before merging with the Production master. Our workflow to deploy a tested change from &lt;strong&gt;Working&lt;/strong&gt; through &lt;strong&gt;Staging&lt;/strong&gt; to &lt;strong&gt;Production&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# standing in /rails_app_root&lt;/span&gt;
git checkout -b working
&lt;span class="c"&gt;# after committing a change&lt;/span&gt;
git status
&lt;span class="c"&gt;# nothing to commit (working directory clean)&lt;/span&gt;
git checkout staging
git merge working
&lt;span class="c"&gt;# &amp;#39;see&amp;#39; Fast forward&lt;/span&gt;
git push heroku_staging staging:master
heroku maintenance:off --app staging_app_name
&lt;span class="c"&gt;# exercise the staging app to verify change&lt;/span&gt;
heroku maintenance:on --app staging_app_name
git push  &lt;span class="c"&gt;# to GitHub&lt;/span&gt;
git checkout master
git merge staging
&lt;span class="c"&gt;# &amp;#39;see&amp;#39; Fast forward&lt;/span&gt;
heroku maintenance:on --app production_app_name
git push heroku_production
heroku maintenance:off --app production_app_name
git push  &lt;span class="c"&gt;# to GitHub&lt;/span&gt;
git checkout working
&lt;span class="c"&gt;# go forth and make more changes&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Witness the ease with which a local Git repo operates with remotes on GitHub and Heroku. Those who have not yet tried Git may not know what they have been missing.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Beta testing started</title>
   <link href="http://blog.newforge-tech.com/news/2010/01/07/beta-testing.html" />
   <updated>2010-01-07T09:15:00-05:00</updated>
   <id>http://blog.newforge-tech.com/news/2010/01/07/beta-testing</id>
   <content type="html">&lt;p&gt;As announced on &lt;a href='http://blog.realized-app.com'&gt;blog.realized-app.com&lt;/a&gt;, we started beta testing &lt;a href='http://realized-app.com'&gt;Realized-app&lt;/a&gt; via invitations in December.&lt;/p&gt;
&lt;p&gt;For developers who want to check out a medium-scale Rails application before its public release, you are also welcome to test. Just go to &lt;a href='http://realized-app.com/beta'&gt;www.realized-app.com/beta&lt;/a&gt; and mention 'open source' in the remarks section.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Background processing on Heroku</title>
   <link href="http://blog.newforge-tech.com/technical/2009/12/04/deploy-heroku.html" />
   <updated>2009-12-04T11:00:00-05:00</updated>
   <id>http://blog.newforge-tech.com/technical/2009/12/04/deploy-heroku</id>
   <content type="html">&lt;p&gt;Some months ago we adopted &lt;a href='http://github.com/collectiveidea/delayed_job'&gt;delayed_job&lt;/a&gt; as our asynchronous background processor. In &lt;a href='http://www.realized-app.com'&gt;Realized-app&lt;/a&gt; several tasks, particularly tax lot setup, benefit from background processing.&lt;/p&gt;
&lt;p&gt;Taking the advice from this &lt;a href='http://github.com/blog/197-the-new-queue'&gt;blog post&lt;/a&gt; on &lt;a href='http://github.com'&gt;GitHub&lt;/a&gt;, we reduced the coupling between models and the message queue by placing the background methods in lib/msg_queue.rb.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;MsgQueue&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserActivationConfirm&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Struct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform&lt;/span&gt;
      &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;activation_confirmation_email&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;We create the corresponding delayed job in models/user.rb.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;activation_confirmation_mq&lt;/span&gt;
    &lt;span class="n"&gt;mq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;MsgQueue&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;UserActivationConfirm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;Delayed&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Job&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enqueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mq&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The call to Job#enqueue remains within each model to allow for passing a priority parameter, should that be needed.&lt;/p&gt;
&lt;h3&gt;Deployment on Heroku&lt;/h3&gt;
&lt;p&gt;&lt;a href='http://www.heroku.com'&gt;Heroku&lt;/a&gt; began limited&lt;a href='http://blog.heroku.com/archives/2009/7/15/background_jobs_with_dj_on_heroku/'&gt; support for delayed_job&lt;/a&gt; in July. Yesterday Heroku broadened that support with a new feature that provides for &lt;a href='http://blog.heroku.com/archives/2009/12/3/dj_has_evolved_into_workers'&gt;multiple delayed_job workers per app&lt;/a&gt;. That capability sealed our decision to deploy, at least initially, on Heroku.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Unit testing ActiveRecord validations and PostgreSQL constraints</title>
   <link href="http://blog.newforge-tech.com/technical/2009/11/16/unit-test-validation.html" />
   <updated>2009-11-16T14:45:00-05:00</updated>
   <id>http://blog.newforge-tech.com/technical/2009/11/16/unit-test-validation</id>
   <content type="html">&lt;p&gt;Some of the more rudimentary aspects of unit testing involve validation. These tests may exercise ActiveRecord or the database constraints created by a migration. &lt;/p&gt;
&lt;p&gt;In a chapter from &lt;a href='http://oreilly.com/catalog/9780596515201'&gt;&lt;i&gt;Enterprise Rails&lt;/i&gt;&lt;/a&gt;, 'Database As a Fortress', author Dan Chak advocates for employing the data integrity features of modern databases, particularly PostgreSQL. With &lt;a href='http://www.realized-app.com'&gt;Realized-app&lt;/a&gt;, we use PostgreSQL as a persistent data store.&lt;/p&gt;
&lt;p&gt;To go beyond just testing the ActiveRecord model validations, in testing a database constraint Dan suggests using the following test_helper.rb method:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;expect_db_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;begin&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt;
  &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;StatementInvalid&lt;/span&gt;
    &lt;span class="n"&gt;database_threw_error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;rescue&lt;/span&gt;
    &lt;span class="n"&gt;something_else_threw_error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;something_else_threw_error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;defective case&amp;#39;&lt;/span&gt;
  &lt;span class="n"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;database_threw_error&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;something_else_threw_error&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;One difficulty with testing database constraints is that the ActiveRecord model validations may catch some errors before they reach the PostgreSQL database. As a work-around, we can add another method:
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;svf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save_with_validation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;	
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Using these test helpers, this test will properly exercise the database constraints defined by a migration.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;name too long&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;expect_db_error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;svf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_model_save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;name_too_long&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Such validation tests tend to be similar among different models. Just as &lt;a href='/technical/2009/09/03/concerned-with-model.html'&gt;concerned_with&lt;/a&gt; allowed for division of model logic into discrete files, we place unit test validation tests in a separate /test/unit/validation directory. This prevents cluttering model-specific logic with boilerplate validation checks.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Using Objected Oriented CSS</title>
   <link href="http://blog.newforge-tech.com/technical/2009/10/05/object-oriented-css.html" />
   <updated>2009-10-05T09:00:00-04:00</updated>
   <id>http://blog.newforge-tech.com/technical/2009/10/05/object-oriented-css</id>
   <content type="html">&lt;p&gt;Most web apps can benefit by leveraging a CSS framework to follow best practices. &lt;a href='http://realized-app.com'&gt;Realized-app&lt;/a&gt; is no different.&lt;/p&gt;
&lt;p&gt;Our chosen CSS framework, &lt;a href='http://wiki.github.com/stubbornella/oocss/'&gt;Object Oriented CSS&lt;/a&gt; stood out because of two underlying principles:&lt;/p&gt;
&lt;ul class='smpl'&gt;
	&lt;li&gt;Separate structure and skin&lt;/li&gt;
	&lt;li&gt;Separate container and content&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With Object Oriented CSS, columns or grids control width. Content controls height. Modules provide containers. Skins are applied to any of these structures.&lt;/p&gt;
&lt;p&gt;Like Rails, the framework continues to evolve. Our adoption of Object Oriented CSS divides it into three parts:&lt;/p&gt;
&lt;ul class='smpl'&gt;
	&lt;li&gt;Core&lt;/li&gt;
	&lt;li&gt;Core mods&lt;/li&gt;
	&lt;li&gt;Skins&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The core consists of five .css files: libraries, template, grid, content and module. Rather than modifying the core, we place any  modifications to the core in five core mods files. We then associate a distinct skin.css to each of the core elements. As the core files evolve, we simply replace them without disturbing the remaining files.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>concerned_with readable rails models</title>
   <link href="http://blog.newforge-tech.com/technical/2009/09/03/concerned-with-model.html" />
   <updated>2009-09-03T15:15:00-04:00</updated>
   <id>http://blog.newforge-tech.com/technical/2009/09/03/concerned-with-model</id>
   <content type="html">&lt;p&gt;Several models within our web app, &lt;a href='http://www.realized-app.com'&gt;Realized-app&lt;/a&gt;, have grown to more than 500 lines. Rapidly grasping the relationships among methods in these models had become difficult. Some means of dividing the models into coherent pieces was needed.&lt;/p&gt;
&lt;p&gt;An elegant fix came about while reading the code for the rails-based forum, &lt;a href='http://github.com/courtenay/altered_beast'&gt;altered_beast&lt;/a&gt;. First, app/models contains a 'user' directory. Near the top of models/user.rb, also note a call to &lt;strong&gt;concerned_with&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;concerned_with&lt;/span&gt; &lt;span class="ss"&gt;:validation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:states&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:activation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:posting&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;One of the rails initializers defines concerned_with. Four files named by the symbols passed to concerned_with reside in app/models/user. The user methods pertaining to validation are found in models/user/validation.rb. Without the separation provided by concerned_with, this validation logic would exist in models/user.rb.&lt;/p&gt;
&lt;p&gt;Using &lt;strong&gt;concerned_with&lt;/strong&gt;, we have refactored the largest models in &lt;a href='http://www.realized-app.com'&gt;Realized-app&lt;/a&gt;. Now, at a glance, most of the functionality unique to a particular model becomes readily apparent.&lt;/p&gt;
&lt;p&gt;For a good perspective on the origin of concerned_with and how to use it, see this &lt;a href='http://paulbarry.com/articles/2008/08/30/concerned-with-skinny-controller-skinny-model'&gt;post by Paul Barry&lt;/a&gt;.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Startup ideas we'd like to fund</title>
   <link href="http://blog.newforge-tech.com/strategy/2009/07/26/startup-ideas-like-fund.html" />
   <updated>2009-07-26T23:30:00-04:00</updated>
   <id>http://blog.newforge-tech.com/strategy/2009/07/26/startup-ideas-like-fund</id>
   <content type="html">&lt;p&gt;A year ago, &lt;a href='http://www.paulgraham.com'&gt;Paul Graham&lt;/a&gt; listed a few &lt;a href='http://ycombinator.com/ideas.html'&gt;Startup Ideas We'd Like to Fund&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;#21: "Finance software for individuals and small businesses. Intuit seems ripe for picking off. The difficulty is that they've got data connections with all the banks. That's hard for a small startup to match. But if you can start in a neighboring area and gradually expand into their territory, you could displace them."&lt;/p&gt;
&lt;p&gt;We all watched as &lt;a href='http://www.mint.com'&gt;Mint&lt;/a&gt; entered that space. But both Quicken and Mint fall short when it comes to handling stock investments. Their data connections with financial institutions provide real convenience, but pose issues of security and privacy.&lt;/p&gt;
&lt;p&gt;The web is full of personal finance sites with ideas about buying stock. Few address the problem of selling stock from a portfolio to minimize realized capital gains and maintain balanced diversification. And even fewer calculate capital gains and support the preparation of Schedule D.&lt;/p&gt;
&lt;p&gt;To maintain privacy, rather than relying on a direct import from each broker, &lt;a href='http://www.realized-app.com'&gt;Realized-app&lt;/a&gt; uses the &lt;a href='http://fastercsv.rubyforge.org/'&gt;FasterCSV gem&lt;/a&gt; to import trade history from a .csv history file.&lt;/p&gt;
&lt;p&gt;&lt;a href='http://www.realized-app.com'&gt;Realized-app&lt;/a&gt; began as a &lt;a href='http://rubyonrails.org/'&gt;Ruby on Rails&lt;/a&gt; demonstration project. Time will tell whether security and privacy trump convenience.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Realized-app blog</title>
   <link href="http://blog.newforge-tech.com/news/2009/06/02/blog-realized.html" />
   <updated>2009-06-02T12:15:00-04:00</updated>
   <id>http://blog.newforge-tech.com/news/2009/06/02/blog-realized</id>
   <content type="html">&lt;p&gt;Last week we launched our product blog &lt;a href='http://blog.realized-app.com'&gt;blog.realized-app.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Development of our web app, &lt;a href='http://realized-app.com'&gt;Realized-app&lt;/a&gt;, will require several more months before we begin beta testing. With &lt;a href='http://blog.realized-app.com'&gt;blog.realized-app.com&lt;/a&gt;, we will focus on the investment issues faced by individual investors and financial advisors. Many of the underlying concepts of &lt;a href='http://realized-app.com'&gt;Realized-app&lt;/a&gt; came about because these issues have few solutions available online.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Using Jekyll to generate our blog</title>
   <link href="http://blog.newforge-tech.com/technical/2009/05/11/jekyll.html" />
   <updated>2009-05-11T08:45:00-04:00</updated>
   <id>http://blog.newforge-tech.com/technical/2009/05/11/jekyll</id>
   <content type="html">&lt;p&gt;Welcome to our blog. We have been working for nearly five months to create a simple and effective stock portfolio management tool.&lt;/p&gt;
&lt;p&gt;Much of our energy this year has been devoted to building our web app, &lt;a href='http://realized-app.com'&gt;Realized-app&lt;/a&gt;. Taking a few hours to look into a blog architecture was a welcome change in direction. Very quickly we settled on &lt;a href='http://wiki.github.com/mojombo/jekyll/'&gt;Jekyll&lt;/a&gt; for use as a blog generator.&lt;/p&gt;

&lt;p&gt;Jekyll is written in Ruby. Because of that, we are confident that if our needs outgrow Jekyll, we should be able to bolt something on without too much difficulty. One of its early proponents, &lt;a href='http://henrik.nyh.se/'&gt;Henrik Nyh&lt;/a&gt; did just that by adding support for Haml. Using Haml allowed us to streamline the design of our blog archive page.&lt;/p&gt;

&lt;p&gt;Look for the launch of the Realized-app blog soon, also to be built on Jekyll.&lt;/p&gt;

 </content>
 </entry>
 
 
</feed>
