<?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>Brandon M. West</title>
	<atom:link href="http://brandonmwest.com/feed" rel="self" type="application/rss+xml" />
	<link>http://brandonmwest.com</link>
	<description></description>
	<lastBuildDate>Sat, 18 Jun 2011 03:48:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>Ruby API Wrapper for Rainmaker</title>
		<link>http://brandonmwest.com/dev/ruby-api-wrapper-for-rainmaker</link>
		<comments>http://brandonmwest.com/dev/ruby-api-wrapper-for-rainmaker#comments</comments>
		<pubDate>Sat, 18 Jun 2011 03:46:14 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://brandonmwest.com/?p=123</guid>
		<description><![CDATA[I&#8217;ve created a Ruby wrapper for the Rainmaker API. Rainmaker is sponsoring a developer contest and I built this gem to assist coders interested in entering. You can find it on RubyGems.org or on Github. My goals when creating this wrapper were to allow developers to use the API in an idiomatic way they were [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve created a Ruby wrapper for the <a title="Rainmaker" href="http://rainmaker.cc">Rainmaker</a> API. Rainmaker is sponsoring a <a title="Rainmaker Challenge" href="http://rainmaker.cc/challenge/">developer contest</a> and I built this gem to assist coders interested in entering.</p>
<p>You can find it on <a title="RubyGems.org" href="https://rubygems.org/gems/rainmaker">RubyGems.org</a> or on <a title="Ruby Rainmaker on Github" href="https://github.com/brandonmwest/rainmaker">Github</a>. My goals when creating this wrapper were to allow developers to use the API in an idiomatic way they were familiar with: accessing properties of an object rather than keys of a collection, using lowercases and underscores instead of camel casing; and to decouple the JSON/XML parsers and HTTP adapters. This was achieved using the excellent <a title="Faraday RubyGem" href="https://rubygems.org/gems/faraday">Faraday</a> gem.</p>
<p>Feel free to make changes or file issues on Github, and happy coding!</p>
]]></content:encoded>
			<wfw:commentRss>http://brandonmwest.com/dev/ruby-api-wrapper-for-rainmaker/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using YSlow to Improve Website Performance</title>
		<link>http://brandonmwest.com/dev/using-yslow-to-improve-website-performance</link>
		<comments>http://brandonmwest.com/dev/using-yslow-to-improve-website-performance#comments</comments>
		<pubDate>Mon, 14 Mar 2011 16:35:11 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[Server Administration]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[yslow]]></category>

		<guid isPermaLink="false">http://brandonmwest.com/?p=83</guid>
		<description><![CDATA[Optimizing web requests and responses is a multi-faceted endeavor. Using YSlow can help you sort through all the available vectors and quickly identify where your website&#8217;s optimization opportunities lie. Your primary tool in the battle against slow load times and abundant http requests is a Firefox extension, Yahoo&#8217;s YSlow. This component integrates with FireBug. FireBug [...]]]></description>
			<content:encoded><![CDATA[<p>Optimizing web requests and responses is a multi-faceted endeavor. Using YSlow can help you sort through all the available vectors and quickly identify where your website&#8217;s optimization opportunities lie.</p>
<p><span id="more-83"></span></p>
<p>Your primary tool in the battle against slow load times and abundant http requests is a Firefox extension, Yahoo&#8217;s <a href="http://developer.yahoo.com/yslow/">YSlow</a>. This component integrates with <a href="http://www.getfirebug.com/">FireBug</a>. FireBug is a fantastic developer-oriented console for firefox that provides all kinds of helpful debugging tools, including JavaScript breakpoints, the ability to edit CSS on the fly, tracking all XHR requests and responses, and more.</p>
<p>YSlow analyzes all the components on a page and gives you a grade based on a number of optimization criteria. For example, it told me that cnn.com has 29 external JS pages, 6 external stylesheets, and 46 css background images. This results in a grade of ‘F’ in the category of ‘Make fewer HTTP Requests’.<br />
<a href="http://brandonmwest.com/wp-content/uploads/yslow.png" target="_blank"><img src="http://brandonmwest.com/wp-content/uploads/yslow-300x106.png" alt="" title="yslow" width="300" height="106" class="alignright size-medium wp-image-99" /></a></p>
<p>If these CSS sheets were combined, the JS minified and combined, and the CSS backgrounds all placed into a <a href="http://alistapart.com/articles/sprites">master sprite image</a>, we could reduce the number of HTTP requests from 81 to 3. This would greatly improve load times due to most browsers limiting the number of allowed HTTP connections per subdomain. Of course this may not be feasible for all of the content coming in from third parties on sites like cnn.com, but for most developers it is extremely helpful information. </p>
<p>Of course applying some of the fixes suggested by YSlow is easier if you have a good working knowledge base to pull from. I found these articles to be very helpful:</p>
<p><a href="http://www.die.net/musings/page_load_time/">Concurrent Pipelines and Hostnames</a> &#8211; This article focuses on concurrent HTTP pipelines and using multiple hostnames to improve performance.</p>
<p><a href="http://www.mnot.net/cache_docs/">Caching</a> &#8211; Deals with the intricacies of caching, and is very thorough. I recommend checking out the tips section for a quick overview.</p>
<p>In my next post I&#8217;ll identify a few WordPress plugins to help improve your site&#8217;s performance (and YSlow grade) out of the box.</p>
]]></content:encoded>
			<wfw:commentRss>http://brandonmwest.com/dev/using-yslow-to-improve-website-performance/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using a Vodacom 3G Card on Mac OS X</title>
		<link>http://brandonmwest.com/hardware/using-a-vodacom-3g-card-on-mac-os-x</link>
		<comments>http://brandonmwest.com/hardware/using-a-vodacom-3g-card-on-mac-os-x#comments</comments>
		<pubDate>Sun, 21 Mar 2010 15:12:16 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Troubleshooting]]></category>
		<category><![CDATA[Wireless]]></category>
		<category><![CDATA[3g]]></category>
		<category><![CDATA[south africa]]></category>
		<category><![CDATA[vodacom]]></category>
		<category><![CDATA[vodafone]]></category>

		<guid isPermaLink="false">http://brandonmwest.com/?p=76</guid>
		<description><![CDATA[I&#8217;m in South Africa at the moment and my CDMA phone is useless here. I got a Huawei wireless USB modem from Vodacom to use, but for the first few days I had it I could only get it to work on my virtualized Windows machine. I finally managed to get it working by allowing [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m in South Africa at the moment and my CDMA phone is useless here. I got a Huawei wireless USB modem from Vodacom to use, but for the first few days I had it I could only get it to work on my virtualized Windows machine. I finally managed to get it working by allowing OS X to do the configuration and dialing rather than the Vodafone Mobile Connect software.</p>
<p><span id="more-76"></span>Here&#8217;s how I managed it:</p>
<ul>
<li>Open the Network panel in System Preferences</li>
<li>Click the + symbol in the lower left to add a new interface and select the modem.</li>
<li>Go to Advanced options.</li>
<li>Select &#8220;Generic&#8221; for the Vendor and &#8220;GPRS (GSM/3g)&#8221; for the model. Enter &#8220;Internet&#8221; for the APN. This seems to matter, as I tried a few other strings and could not authenticate.</li>
<li>Enter *99***1# for the telephone number and save the configuration.</li>
</ul>
<p>To connect, you must first have the Vodafone Mobile Connect application installed, as there is no way that I found to enter the PIN via OS X. Plug in your modem, open Mobile Connect, and enter your pin. Then go back your network preferences, select the interface you&#8217;ve just configured, and click connect. If all goes well you should now be connected. I am not sure if this will work in locales other than South Africa; the phone number to connect may well be different.</p>
]]></content:encoded>
			<wfw:commentRss>http://brandonmwest.com/hardware/using-a-vodacom-3g-card-on-mac-os-x/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Posting a Lead to SugarCRM from Drupal via Webform</title>
		<link>http://brandonmwest.com/dev/posting-a-lead-to-sugarcrm-from-drupal-via-webform</link>
		<comments>http://brandonmwest.com/dev/posting-a-lead-to-sugarcrm-from-drupal-via-webform#comments</comments>
		<pubDate>Sun, 07 Feb 2010 00:33:19 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[CMS]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[crm]]></category>
		<category><![CDATA[drupal]]></category>
		<category><![CDATA[sugarcrm]]></category>
		<category><![CDATA[webform]]></category>

		<guid isPermaLink="false">http://brandonmwest.com/?p=32</guid>
		<description><![CDATA[I was helping a friend solve the issue of capturing a lead to Sugar 5.2 from a form in Drupal 6 and my searching was not turning up a clear answer. This article was a good start but was a bit out of date and missing a couple steps. On the issues page for the [...]]]></description>
			<content:encoded><![CDATA[<p>I was helping a friend solve the issue of capturing a lead to Sugar 5.2 from a form in Drupal 6 and my searching was not turning up a clear answer. <a href="http://www.computerminds.co.uk/how-capture-sugarcrm-leads-drupal">This article</a> was a good start but was a bit out of date and missing a couple steps. On the <a href="http://drupal.org/node/287183">issues page</a> for the SugarCRM Drupal module, I found a couple other useful hints. This guide should work for Drupal 6 and SugarCRM 5.1+.<br />
<span id="more-32"></span><br />
First, download these Drupal modules: <a href="http://drupal.org/project/sugarwebform">SugarCRM Webform Integration</a> and <a href="http://drupal.org/project/webform">Webform</a>. Extract these archives to your server and <a href="http://drupal.org/getting-started/install-contrib/modules">activate the modules in Drupal</a>.</p>
<p>Create a new file named leadCapture_override.php in the root folder of your SugarCRM install on your server. Open the file and paste the following code:</p>
<p>[cc lang="php"]<br />
# set up the array of usernames and hashed password<br />
$users = array(<br />
&#8216;Your_User_Name&#8217; => array(&#8216;name&#8217;=>&#8217;Your_User_Name&#8217;, &#8216;pass&#8217;=>&#8217;Your_User_Hash&#8217;,'userid&#8217;=>&#8217;Your_User_Id&#8217;)<br />
);</p>
<p># identify the web site user by id so we can assign the lead to them<br />
$assigned_user_id = $users[$_REQUEST['user']]['userid'];</p>
<p>if( !isset($_POST['assigned_user_id']) || !empty($_POST['assigned_user_id']) ){<br />
$_POST['assigned_user_id'] = $assigned_user_id;<br />
}</p>
<p># if we have an Opt-In field, we want to get rid of any Opt-Out field that we may have<br />
if ( !empty($_POST['email_opt_in']) ) {<br />
unset($_POST['email_opt_out']);<br />
}</p>
<p># convert opt out to an explicit binary boolean<br />
if ( isset($_POST['email_opt_out']) ) {<br />
$_POST['email_opt_out'] = 1;<br />
}<br />
[/cc]</p>
<p>Now you will need to enter your configuration&#8217;s user values In the $users array declaration (line 3 above). First enter the SugarCRM user name that will be assigned every lead coming from Drupal. Once you have the user name, replace Your_User_Name in the code above with it.</p>
<p>To get the userid and pass values, open your SugarCRM database with a database admin (such as phpMyAdmin) and run the following query: <strong>SELECT id, user_hash FROM users WHERE user_name=&#8217;Your_User_Name&#8217;</strong>. Replace Your_User_Id with the id value, and Your_User_Hash with the user_hash value.</p>
<p>The next step is creating your webform. For the purposes of this article I am assuming that all the fields you need to capture are already setup in Sugar. If not, maybe <a href="http://vimeo.com/5194233">this screencast</a> can help. If you need any help creating the webform, more information can be found in the <a href="http://drupal.org/handbook/modules/webform">Drupal documentation</a>.</p>
<p>Once you have your webform created, you will see a SugarCRM Settings area on the webform configuration screen.<br />
<a href="http://brandonmwest.com/wp-content/uploads/Drupal_SugarCRM_settings.png"><img class="aligncenter size-full wp-image-62" title="Drupal SugarCRM settings" src="http://brandonmwest.com/wp-content/uploads/Drupal_SugarCRM_settings.png" alt="" /></a></p>
<p>In the <em>Sugar Form is posted to</em> field, enter <strong>http://yoursugarinstanceURL/index.php?entryPoint=leadCapture</strong>. <em>Lead Source</em> can be whatever you&#8217;d like. The <em>SugarCRM User</em> field <strong>must </strong>match the value you entered for Your_User_Name in the leadCapture_override.php file created earlier.</p>
<p style="text-align: left;">Congratulations, your Drupal form should now capture leads in Sugar.</p>
<p style="text-align: right;">[ratings]</p>
]]></content:encoded>
			<wfw:commentRss>http://brandonmwest.com/dev/posting-a-lead-to-sugarcrm-from-drupal-via-webform/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Indexing Legacy Data with NHibernate.Search</title>
		<link>http://brandonmwest.com/dev/indexing-legacy-data-with-nhibernate-search</link>
		<comments>http://brandonmwest.com/dev/indexing-legacy-data-with-nhibernate-search#comments</comments>
		<pubDate>Tue, 22 Dec 2009 00:36:52 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[lucene]]></category>
		<category><![CDATA[lucene.net]]></category>
		<category><![CDATA[nhibernate]]></category>
		<category><![CDATA[nhibernate.search]]></category>
		<category><![CDATA[nhsearch]]></category>

		<guid isPermaLink="false">http://brandonmwest.com/?p=8</guid>
		<description><![CDATA[While configuring NHibernate.Search, I ran into an issue while attempting to batch process a million or so legacy records. When I created the index directly from Lucene.Net, things were speedy and working as expected. When I created the index via NHibernate.Search, the indexer was generating way too many index files, numbering into the hundreds of [...]]]></description>
			<content:encoded><![CDATA[<p>While configuring NHibernate.Search, I ran into an issue while attempting to batch process a million or so legacy records. When I created the index directly from <a href="http://incubator.apache.org/lucene.net/">Lucene.Net</a>, things were speedy and working as expected. When I created the index via NHibernate.Search, the indexer was generating way too many index files, numbering into the hundreds of thousands. As a result, the number of file operations was increasing drastically with each iteration of the indexer, such that the FullTextSession.Index call would never finish.</p>
<p>I spent a long time messing about with different merge factors and max file parameters for Lucene.Net, but I was never able to make it work as I expected. The solution ended up being to force an optimize on the index after a certain number of records. Optimizing a Lucene index is analogous to defragging a harddrive; it orders and compacts the thousands of splintered .cfs files into one big file, thereby solving the problem of having to scan a growing number of files before each write.<br />
<span id="more-8"></span><br />
Here is my generic CreateIndex method that includes periodic optimization. This ended up solving the problem and allowed me to index 1.5 million legacy records in about 3 hours. This code depends on a specific finder implementation, as well as a generic method for optimizing an index, but it should be enough to get the idea across.</p>
<p>[cc lang="csharp"]<br />
public static void CreateIndex<T>(int batchSize)<br />
{<br />
    Type type = typeof(T);</p>
<p>    //Get the query object for the type to be indexed<br />
    object finder = Find.Factory.ResolveFinderFor(type);<br />
    var method = finder.GetType().GetMethod(&#8220;get_All&#8221;);<br />
    var objectQuery = method.Invoke(finder, null) as IQueryable<T>;</p>
<p>    IFullTextSession fullTextSession =<br />
        Search.CreateFullTextSession(NH.CurrentSession);</p>
<p>    var total = objectQuery.Count();<br />
    var iterations = total / batchSize;</p>
<p>    const int optimizeThreshold = 10000;<br />
    var optimizeThresholdCounter = 0;</p>
<p>    //Find the generic optimize method<br />
    MethodInfo optimizeMethod =<br />
        typeof(IndexHelper).GetMethod(&#8220;OptimizeIndex&#8221;);</p>
<p>    //Make it generic for the type in question<br />
    MethodInfo genericOptimizeMethod =<br />
        optimizeMethod.MakeGenericMethod(type);</p>
<p>    for (var i = 0; i < iterations; i++)<br />
    {<br />
        var subset = objectQuery.Skip(i * batchSize).Take(batchSize).ToList();</p>
<p>        int startCount = (i*batchSize);<br />
        int endCount = startCount + batchSize;</p>
<p>        optimizeThresholdCounter += batchSize;</p>
<p>        var tx = fullTextSession.BeginTransaction();<br />
        foreach (T instance in subset)<br />
        {<br />
            fullTextSession.Index(instance);<br />
        }<br />
        tx.Commit();</p>
<p>        fullTextSession.Flush();<br />
        fullTextSession.Clear();</p>
<p>        //If we've hit the threshold, optimize<br />
        if(optimizeThreshold != 0 &#038;&#038;<br />
            optimizeThresholdCounter >= optimizeThreshold)<br />
        {<br />
            genericOptimizeMethod.Invoke(null, null);<br />
            optimizeThresholdCounter = 0;<br />
        }<br />
    }</p>
<p>    //optimize the index one final time<br />
    genericOptimizeMethod.Invoke(null, null);<br />
}<br />
[/cc]</p>
<p>I hope this saves someone some headaches &#8211; I know I wasted a lot of time finding this solution.</p>
<p style="text-align: right;">[ratings]</p>
]]></content:encoded>
			<wfw:commentRss>http://brandonmwest.com/dev/indexing-legacy-data-with-nhibernate-search/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/


Served from: brandonmwest.com @ 2012-05-19 21:03:20 -->
