<?xml version="1.0"?>
<rss version="2.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007" xmlns:atom="http://www.w3.org/2005/Atom">
   <channel>
      <title>salesforce continuous integration jenkins</title>
      <description>Pipes Output</description>
      <link>http://pipes.yahoo.com/pipes/pipe.info?_id=72f9c2fc033a9bb74d5e5b9a67257d9d</link>
      <atom:link rel="next" href="http://pipes.yahoo.com/pipes/pipe.run?_id=72f9c2fc033a9bb74d5e5b9a67257d9d&amp;_render=rss&amp;page=2"/>
      <pubDate>Thu, 01 Oct 2015 07:39:11 +0000</pubDate>
      <generator>http://pipes.yahoo.com/pipes/</generator>
      <item>
         <title>Creating OS Folders and Subfolders with FileMaker</title>
         <link>http://www.soliantconsulting.com/blog/2015/09/creating-os-folders-subfolders-filemaker</link>
         <description>&lt;p&gt;It is very common to generate reoccurring reports in FileMaker that get saved to the user&amp;#8217;s computer. Perhaps you would like to organize these reports by day or type. OS level folders and subfolders are a great way to do this. This demo file attached shows you how to create a folder and a subfolder on [&amp;#8230;]&lt;/p&gt;
&lt;p&gt;The post &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.soliantconsulting.com/blog/2015/09/creating-os-folders-subfolders-filemaker&quot;&gt;Creating OS Folders and Subfolders with FileMaker&lt;/a&gt; appeared first on &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.soliantconsulting.com&quot;&gt;Soliant Consulting&lt;/a&gt;.&lt;/p&gt;</description>
         <guid isPermaLink="false">http://www.soliantconsulting.com/?p=13688</guid>
         <pubDate>Mon, 28 Sep 2015 17:37:54 +0000</pubDate>
         <content:encoded><![CDATA[<p><img class="alignleft wp-image-13699" alt="Folder icon" width="100" height="100"/>It is very common to generate reoccurring reports in FileMaker that get saved to the user&#8217;s computer. Perhaps you would like to organize these reports by day or type. OS level folders and subfolders are a great way to do this. This demo file attached shows you how to create a folder and a subfolder on your user&#8217;s computer using FileMaker.</p>
<p>Here&#8217;s an overview on how the sample file works:</p>
<ul class="bullet-list">
<li>The layout asks you to enter a folder name and a location for the folder (either desktop or documents folder). If the location is the same every time, you can hard code the location in your script.</li>
<li>The script confirms that none of these values are empty.</li>
<li>The subfolder name is calculated based on the date and time. This ensures that no two subfolders will have the same name, which would cause an error.</li>
<li>Check if we are on Windows or Mac.
<ul class="bullet-list">
<li>If we are Windows, we run a Send Event script step that makes the directory specified.</li>
<li>If we are on Mac, perform applescript to create the main folder, and then perform applescript again to create the subfolder.</li>
</ul>
</li>
<li>Let the user know if there was an error or if everything was successful.</li>
</ul>
<p>You can download the demo file here: <a rel="nofollow" target="_blank" href="http://www.soliantconsulting.com/wp-content/uploads/2015/09/CreateFolders.fmp12.zip">CreateFolders.fmp12</a></p>
<p>The post <a rel="nofollow" target="_blank" href="http://www.soliantconsulting.com/blog/2015/09/creating-os-folders-subfolders-filemaker">Creating OS Folders and Subfolders with FileMaker</a> appeared first on <a rel="nofollow" target="_blank" href="http://www.soliantconsulting.com">Soliant Consulting</a>.</p>]]></content:encoded>
      </item>
      <item>
         <title>Combine Existing PDFs in FileMaker Using AppleScript</title>
         <link>http://www.soliantconsulting.com/blog/2015/09/combine-existing-pdfs-filemaker-using-applescript</link>
         <description>&lt;p&gt;When creating a PDF from FileMaker you have the ability to append your new PDF onto an existing PDF. This feature was introduced in FileMaker 8, and is extremely helpful. However, what if you have 2 (or more) existing PDFs that you need to combine? What if you want the first PDF to be generated from FileMaker, [&amp;#8230;]&lt;/p&gt;
&lt;p&gt;The post &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.soliantconsulting.com/blog/2015/09/combine-existing-pdfs-filemaker-using-applescript&quot;&gt;Combine Existing PDFs in FileMaker Using AppleScript&lt;/a&gt; appeared first on &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.soliantconsulting.com&quot;&gt;Soliant Consulting&lt;/a&gt;.&lt;/p&gt;</description>
         <guid isPermaLink="false">http://www.soliantconsulting.com/?p=13649</guid>
         <pubDate>Thu, 24 Sep 2015 14:53:07 +0000</pubDate>
         <content:encoded><![CDATA[<p><img class=" alignleft" src="http://a3.mzstatic.com/us/r30/Purple4/v4/47/7f/68/477f68c6-e755-4167-a9fb-1005272634c5/icon256.png" alt="Picture of PDF files" width="256" height="256"/>When creating a PDF from FileMaker you have the ability to append your new PDF onto an existing PDF. This feature was introduced in FileMaker 8, and is extremely helpful. However, what if you have 2 (or more) existing PDFs that you need to combine? What if you want the first PDF to be generated from FileMaker, but the 2nd one, for example, is uploaded by the user? The solution I found to this problem was introduced to me by my colleague <a rel="nofollow">Mike Duncan</a>. You can use AppleScript to combine the PDFs for you.</p>
<p>Note: Unfortunately AppleScript is only available on Macs, so this solution will not work on Windows machines.</p>
<p>In the sample file below, you will see a demonstration on how to combine 2 PDFs using AppleScript. You will create a shell script that leverages Automator&#8217;s combine PDF function, and then run that shell script using AppleScript.</p>
<p><a rel="nofollow">Download CombingingPDFsWithApplescript.fmp12</a></p>
<p>&nbsp;</p>
<p>The post <a rel="nofollow" target="_blank" href="http://www.soliantconsulting.com/blog/2015/09/combine-existing-pdfs-filemaker-using-applescript">Combine Existing PDFs in FileMaker Using AppleScript</a> appeared first on <a rel="nofollow" target="_blank" href="http://www.soliantconsulting.com">Soliant Consulting</a>.</p>]]></content:encoded>
      </item>
      <item>
         <title>Quickly Find Unstored Calcs and Summary Fields</title>
         <link>http://www.soliantconsulting.com/blog/2015/09/quickly-find-unstored-calcs-summary-fields</link>
         <description>&lt;p&gt;Certain types of fields, like unstored calculation and summary fields, can really slow down a solution, especially if they are used on layouts that are primarily accessed in list or table view. It&amp;#8217;s not uncommon to come across list layouts in inherited solutions – files which you are maintaining but were originally developed by someone [&amp;#8230;]&lt;/p&gt;
&lt;p&gt;The post &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.soliantconsulting.com/blog/2015/09/quickly-find-unstored-calcs-summary-fields&quot;&gt;Quickly Find Unstored Calcs and Summary Fields&lt;/a&gt; appeared first on &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.soliantconsulting.com&quot;&gt;Soliant Consulting&lt;/a&gt;.&lt;/p&gt;</description>
         <guid isPermaLink="false">http://www.soliantconsulting.com/?p=13600</guid>
         <pubDate>Fri, 18 Sep 2015 16:10:46 +0000</pubDate>
         <content:encoded><![CDATA[<p>Certain types of fields, like unstored calculation and summary fields, can really slow down a solution, especially if they are used on layouts that are primarily accessed in list or table view.</p>
<p>It&#8217;s not uncommon to come across list layouts in inherited solutions – files which you are maintaining but were originally developed by someone else – which use unstored calcs and summary fields. If the list view is loading slowly, one of the first step in diagnosing the performance issue is to remove these fields to see what impact that has.</p>
<p>But to do this, we need to determine which fields on the slow layout are unstored calcs or summary fields. When a layout which you didn&#8217;t create in the first place has dozens and dozens of fields, and the field naming convention doesn&#8217;t readily reveal the type of field, then this can be a somewhat tedious task.</p>
<p>Creating a Database Design Report (DDR) will give us this information, but it takes a little bit of time to do, so is there a quicker way?</p>
<p>Yes, there is (with a caveat, of course) – we can use the two FileMaker design functions FieldNames and FieldType to accomplish this.</p>
<p>The caveat is that if the unstored calc or summary field exists on a layout as a merged field, it will not be detected.</p>
<p>The accompanying <a rel="nofollow">demo file</a>, which is based on the FileMaker Assets starter solution, has two approaches built-in:</p>
<p><img class="alignright wp-image-13606 size-medium" alt="Message after running the script" width="300" height="107"/>The first approach uses a script that scans the entire file to create a sort of mini-DDR that lists all layouts containing unstored calc and summary fields. The result is reported in a global variable which you can access using the Data Viewer.<br />
<div class="clear" style="height:20px;"></div><br />
Here is a portion of what is returned when this script is run in the demo file:
<table>
<tbody>
<tr>
<th>Layout</th>
<th>Field</th>
<th>Type</th>
</tr>
<tr>
<td>Asset Details</td>
<td>Assets::Status</td>
<td>UnstoredCalc</td>
</tr>
<tr>
<td>Asset Details</td>
<td>Assets::Days Till Due</td>
<td>UnstoredCalc</td>
</tr>
<tr>
<td>Asset Details</td>
<td>Assets::Selected File Container</td>
<td>UnstoredCalc</td>
</tr>
<tr>
<td>Asset Details</td>
<td>Assets::Book Value</td>
<td>UnstoredCalc</td>
</tr>
<tr>
<td>Asset Details</td>
<td>Assets::Remaining Years</td>
<td>UnstoredCalc</td>
</tr>
<tr>
<td>Asset Details</td>
<td>Assets::Depreciation Value</td>
<td>UnstoredCalc</td>
</tr>
<tr>
<td>Asset Details</td>
<td>Assets::Book Value</td>
<td>UnstoredCalc</td>
</tr>
<tr>
<td>Asset Details</td>
<td>Assets::Count Summary Chart</td>
<td>Summary</td>
</tr>
<tr>
<td>Asset Details | iPad</td>
<td>Assets::Status</td>
<td>UnstoredCalc</td>
</tr>
<tr>
<td>Asset Details | iPad</td>
<td>Assets::Days Till Due</td>
<td>UnstoredCalc</td>
</tr>
<tr>
<td>&#8230;</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p>The second approach uses a custom function, which I named &#8220;SlowFields&#8221;, to find unstored calc and summary fields on the current layout only. Here is an example of what this custom function returns when evaluated on the Asset Details layout:</p>
<p><img class="alignnone size-full wp-image-13615" alt="Custom function &quot;SlowFields&quot;" width="281" height="226"/></p>
<p>The script and the custom function are each standalone and completely portable (and they are independent of each other), making them easy to copy into other solution files.</p>
<p>You can use either approach depending on your preference and the situation you&#8217;re working with.</p>
<p>The post <a rel="nofollow" target="_blank" href="http://www.soliantconsulting.com/blog/2015/09/quickly-find-unstored-calcs-summary-fields">Quickly Find Unstored Calcs and Summary Fields</a> appeared first on <a rel="nofollow" target="_blank" href="http://www.soliantconsulting.com">Soliant Consulting</a>.</p>]]></content:encoded>
      </item>
      <item>
         <title>Logging in Managed Packages</title>
         <link>http://www.soliantconsulting.com/blog/2015/08/logging-in-managed-packages</link>
         <description>&lt;p&gt;Issues with debugging when you install a managed package into the org? Soliant's Damien Phillippi shows you how to build your own logging system.&lt;/p&gt;
&lt;p&gt;The post &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.soliantconsulting.com/blog/2015/08/logging-in-managed-packages&quot;&gt;Logging in Managed Packages&lt;/a&gt; appeared first on &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.soliantconsulting.com&quot;&gt;Soliant Consulting&lt;/a&gt;.&lt;/p&gt;</description>
         <guid isPermaLink="false">http://www.soliantconsulting.com/?p=13304</guid>
         <pubDate>Mon, 17 Aug 2015 19:59:03 +0000</pubDate>
         <content:encoded><![CDATA[<h2>Issues with debugging when you install a managed package into the org?</h2>
<h3>How to build your own logging system.</h3>
<p>A fairly common activity in Salesforce is to create managed packages. There are a few reasons for this. First, it makes it easy to deploy updates to multiple clients. Second, it allows you to protect your intellectual property by preventing your code from being seen or modified. Finally, it is a requirement for listing your package on the AppExchange.</p>
<p>You can create these packages very easily or you can go through a full security review from Salesforce. This review process can be very difficult and there is a lot involved in it, which include checking code for vulnerabilities (which is good to do anyways), making sure sensitive data is hidden from the correct people, making sure all code is bulkified, and ensuring that any external systems that connect with the Salesforce instance are also protected from vulnerabilities. In addition to this, there is a hefty annual fee to post your product on the AppExchange. These things can be daunting and may make you decide that you are better off not doing it. In the case that you don’t complete a security review, it will become very difficult to debug in client orgs. You cannot obtain access to debug logs of managed packages without the security review. This allows the client org to allow you to access the logs in the system. I devised a way in order to add some custom logging into your package that can be turned off and on without all of this extra headway.</p>
<p>Your first step is creating a new object to store these logs in. The simplest setup would be to make an auto numbered name and a long test text area for your logging message. (Keep in mind how long you make this restriction because your code can’t can not exceed it.</p>
<div id="attachment_13433" style="width:260px;" class="wp-caption alignleft"><img class="wp-image-13433" src="http://www.soliantconsulting.com/wp-content/uploads/2015/08/mng-pkg-error-log-obj.png" alt="Error Log Object for storing logs" width="250" height="113"/><p class="wp-caption-text">Figure 1 &#8211; Error Log Object</p></div>
<div class="clear" style="height:20px;"></div>
<div id="attachment_13434" style="width:460px;" class="wp-caption alignleft"><img class="wp-image-13434" src="http://www.soliantconsulting.com/wp-content/uploads/2015/08/mng-pkg-error-log-fields.png" alt="Error log fields" width="450" height="70"/><p class="wp-caption-text">Figure 2 &#8211; Error Log Fields</p></div>
<div class="clear" style="height:20px;"></div>
<p>You will also need a way to denote whether your logging is off enabled or on disabled because you don’t want to be creating lots of records that you will likely never look at. You really only want logging on when you are actually looking for themlogsthem. You should create a new List custom setting with a sufficient name such as &#8216;ErrorLogControl&#8217;. It just needs to contain a single field ‘IsLogging’ in order to denote whether logs are enabled or disabled.</p>
<div id="attachment_13435" style="width:460px;" class="wp-caption alignnone"><img class="wp-image-13435" alt="Error log control" width="450" height="241"/><p class="wp-caption-text">Figure 3 &#8211; New List custom setting</p></div>
<p>The class starts out like any other class except for one important change. This class should start off as pretty much any standard class except for one change. You want to specify It is important to define the class with the &#8216;<strong>without sharing</strong>&#8216; keywords so that no matter what User you are logged in as, the logs still get created.</p>
<pre>
public without sharing class ErrorLogControl
{
</pre>
<p>You only want to check if logging is on once so that you don’t hit governor limits and is just generally efficient. This ensures that you don’t do that. Once you check for logging, the variable gets stored for the next check. If it’s empty, then the code knows that it needs to populate it.</p>
<pre>
private static boolean isLogsOn
{
	private get
	{
		if (isLogsOn == null)
		{
			List&lt;ErrorLogControl__c&gt; control = ErrorLogControl__c.getAll().values();
			//If the custom setting is not here, assume logs should be off
			if (control.isEmpty())
				isLogsOn = false;
			else
				isLogsOn = control[0].IsLogging__c;
		}
		return isLogsOn;
	}
	private set;
}

</pre>
<p>Code should not be allowed to access the logs any way on this class besides how the class dictates. Declaring this as ‘private static’ allows nothing but only this class to touch it. That way you can’t have special circumstances that another developer wants to bake into the code, which can get confusing fast. This keeps everything controlled.</p>
<pre>
//Somewhere to store this list of logs that is hidden
private static List&lt;Error_Log__c&gt; eLogs
{
	private get
	{
		if (eLogs == null)
		{
			eLogs = new List&lt;Error_Log__c&gt;();
		}
		return eLogs;
	}
	private set;
}
</pre>
<p>This controls the actual creation of the logs. The code checks to see if you have logging on, and if so tells it go ahead and create and, if so, creates the log.</p>
<pre>
public static void addLog(String message)
{
	if (isLogsOn)
	{
		forceLog(message);
	}
}
</pre>
<p>The other addLog method uses this the forceLog method to actually create the logs. This is where you can add some flexibility into your own code. Say for instance you wanted to track something special, you can add it in here. The reason I have a second method for doing this, is in case you want to do some logging regardless if you have logging turned on or not. This is useful when an error in the code happens and you want to be able to see the issue regardless if they the user had the logs on. That way you don’t have to turn on logs and replicate the caught error. In this instance here, I added a ‘Created_Time__c’ custom field so that I can sort by the time of execution instead of the CreatedDate (which only tracks date) or the CreatedBy (which will sort by User then the CreatedDate and then the Timecreatedtime).</p>
<pre>
public static void forceLog(String message)
{
	eLogs.add(new Error_Log__c(Created_Time__c = DateTime.now(), Error_Messages__c = message));
}
</pre>
<p>This is one of the harder pain points of this setup. The logs need be added to the database at the end of whatever execution of code is going on. This is one of the harder pain points of this setup. Because of that, you might actually have to commit the logs multiple times. For example, you have work going on in a VF page, that will commit logs at the end of an action, but you also have the commitLogs() at the end of a trigger in case they change data through a standard layout. Because of this case, this method needs to make sure it clears the current set of logs each commit so that it isn’t trying to insert the same log twice causing an error and then other logs to fail on insertion. The rest could be handled however you desire. Originally, I only had the check for empty an empty list and insertion of the records into the database with the clearing of the list afterwards. That is the bare minimum you should have. I added some extra result parsing and exception handling though. These could let me add another log basically to say ‘hey these other logs did not insert, something is wrong’.</p>
<pre>
public static void commitLogs()
{
	if (!eLogs.isEmpty())
	{
		try
		{
			List&lt;Database.SaveResult&gt; results = Database.insert(eLogs, false);
			for (Database.SaveResult res: results)
			{
				if (!res.isSuccess())
				{
					//Handle this how you want
				}
			}
		} catch (Exception e)
		{
			//If for some reason it errored while logging
		}finally
		{
			//So that we don’t accidentally insert the same logs twice for whatever reason.
			eLogs.clear();
		}
	}
}
</pre>
<h2>Full code below:</h2>
<pre>
	@TestVisible
	private static String ERROR_ADDING = 'Errors adding error logs.';

	/*
	Some lazy loadingcaching here so that we only check this once and then store the values for later.
	*/
	private static boolean isLogsOn
	{
		private get
		{
			if (isLogsOn == null)
			{
				List&lt;ErrorLogControl__c&gt; control = ErrorLogControl__c.getAll().values();
				//If the custom setting is here, assume logs should be off
				if (control.isEmpty())
					isLogsOn = false;
				else
					isLogsOn = control[0].IsLogging__c;
			}
			return isLogsOn;
		}
		private set;
	}

	//Somewhere to store this list of logs that is hidden
	private static List&lt;Error_Log__c&gt; eLogs
	{
		private get
		{
			if (eLogs == null)
			{
				eLogs = new List&lt;Error_Log__c&gt;();
			}
			return eLogs;
		}
		private set;
	}

	//Pretty self explanatory.  You only want
	public static void addLog(String message)
	{
		if (isLogsOn)
		{
			forceLog(message);
		}
	}

	//This method is reserved for when you want to log regardless of what the settings are.  Such as an error from a DML that you catch or something like that.
	public static void forceLog(String message)
	{
		eLogs.add(new Error_Log__c(Created_Time__c = DateTime.now(), Error_Messages__c = message));
	}

	//Put this at the end of your execution of code.
	public static void commitLogs()
	{
		if (!eLogs.isEmpty())
		{
			try
			{
				List&lt;Database.SaveResult&gt; results = Database.insert(eLogs, false);
				List&lt;Error_Log__c&gt; tempLogs = new List&lt;Error_Log__c&gt;();
				for (Database.SaveResult res: results)
				{
					if (!res.isSuccess())
					{
						//Handle this how you want
					}
				}
			} catch (Exception e)
			{
				//If for some reason it errored while logging.  You can add this error into a log if desired.
			} finally
			{
				//So that we don’t accidentally insert the same logs twice for whatever reason.
				eLogs.clear();
			}
		}
	}
}
</pre>
<p>The post <a rel="nofollow" target="_blank" href="http://www.soliantconsulting.com/blog/2015/08/logging-in-managed-packages">Logging in Managed Packages</a> appeared first on <a rel="nofollow" target="_blank" href="http://www.soliantconsulting.com">Soliant Consulting</a>.</p>]]></content:encoded>
      </item>
      <item>
         <title>Set Up Postman for Optimal JSON API Debugging</title>
         <link>http://www.soliantconsulting.com/soliant-tv/2015/08/set-up-postman-for-optimal-json-api-debugging</link>
         <description>&lt;p&gt;This video covers the basics of Postman, a Chrome app for testing APIs. See how to define sharable configurations and use environment variables to your advantage.&lt;/p&gt;
&lt;p&gt;The post &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.soliantconsulting.com/soliant-tv/2015/08/set-up-postman-for-optimal-json-api-debugging&quot;&gt;Set Up Postman for Optimal JSON API Debugging&lt;/a&gt; appeared first on &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.soliantconsulting.com&quot;&gt;Soliant Consulting&lt;/a&gt;.&lt;/p&gt;</description>
         <guid isPermaLink="false">http://www.soliantconsulting.com/?p=12916</guid>
         <pubDate>Wed, 05 Aug 2015 22:37:36 +0000</pubDate>
         <content:encoded><![CDATA[<p>This video covers the basics of Postman, a Chrome app for testing APIs. See how to define sharable configurations and use environment variables to your advantage.</p>
<p>The post <a rel="nofollow" target="_blank" href="http://www.soliantconsulting.com/soliant-tv/2015/08/set-up-postman-for-optimal-json-api-debugging">Set Up Postman for Optimal JSON API Debugging</a> appeared first on <a rel="nofollow" target="_blank" href="http://www.soliantconsulting.com">Soliant Consulting</a>.</p>]]></content:encoded>
      </item>
      <item>
         <title>An Introduction to Vagrant and Atlas</title>
         <link>http://www.soliantconsulting.com/soliant-tv/2015/07/introduction-to-vagrant-and-atlas</link>
         <description>&lt;p&gt;This video covers the basics of Vagrant, and how you can use the brand new Atlas service from Hashicorp to optimize your developer virtualization.&lt;/p&gt;
&lt;p&gt;The post &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.soliantconsulting.com/soliant-tv/2015/07/introduction-to-vagrant-and-atlas&quot;&gt;An Introduction to Vagrant and Atlas&lt;/a&gt; appeared first on &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.soliantconsulting.com&quot;&gt;Soliant Consulting&lt;/a&gt;.&lt;/p&gt;</description>
         <guid isPermaLink="false">http://www.soliantconsulting.com/?p=12914</guid>
         <pubDate>Wed, 22 Jul 2015 22:27:00 +0000</pubDate>
         <content:encoded><![CDATA[<p>This video covers the basics of Vagrant, and how you can use the brand new Atlas service from Hashicorp to optimize your developer virtualization.</p>
<p>The post <a rel="nofollow" target="_blank" href="http://www.soliantconsulting.com/soliant-tv/2015/07/introduction-to-vagrant-and-atlas">An Introduction to Vagrant and Atlas</a> appeared first on <a rel="nofollow" target="_blank" href="http://www.soliantconsulting.com">Soliant Consulting</a>.</p>]]></content:encoded>
      </item>
      <item>
         <title>Enterprise-quality Web apps with SimpleFM</title>
         <link>http://www.soliantconsulting.com/blog/2015/07/enterprise-quality-web-apps-with-simplefm</link>
         <description>&lt;p&gt;SimpleFM is a robust choice for interacting with the FileMaker Server XML API. The core SimpleFM package is agnostic about coding style. In this article we will lift the hood on the skeleton app and show how clean and importantly how &lt;em&gt;intuitive&lt;/em&gt; the code is.&lt;/p&gt;
&lt;p&gt;The post &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.soliantconsulting.com/blog/2015/07/enterprise-quality-web-apps-with-simplefm&quot;&gt;Enterprise-quality Web apps with SimpleFM&lt;/a&gt; appeared first on &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.soliantconsulting.com&quot;&gt;Soliant Consulting&lt;/a&gt;.&lt;/p&gt;</description>
         <guid isPermaLink="false">http://www.soliantconsulting.com/?p=12270</guid>
         <pubDate>Tue, 14 Jul 2015 18:25:45 +0000</pubDate>
         <content:encoded><![CDATA[<p>SimpleFM is a robust choice for interacting with the FileMaker Server XML API. The core SimpleFM package is agnostic about coding style. It can be added to a project via Composer (as it is PSR-0 compliant for autoloading) or any other means, such as simply copying it into the project and including the class.</p>
<p>This means it is still a fine choice for legacy projects and/or procedural coding style.</p>
<p>With that said, SimpleFM includes opt-in support for the enterprise patterns that Zend Framework 2 is built for. Specifically, we mean strong <a rel="nofollow" class="external-link" target="_blank" href="http://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29">SOLID </a>principles and <a rel="nofollow" class="external-link" target="_blank" href="http://www.martinfowler.com/books/eaa.html">Patterns of Enterprise Application Architecture</a> (in particular the <a rel="nofollow" class="external-link" target="_blank" href="http://martinfowler.com/eaaCatalog/tableDataGateway.html">Table Data Gateway</a> pattern).</p>
<p>This optional material is not demonstrated in the core SimpleFM package. If you want to work with a demo, it is the focus of the <a rel="nofollow" class="external-link" target="_blank" href="https://github.com/soliantconsulting/SimpleFM-skeleton">SimpleFM-skeleton</a> project, which demonstrates basic usage with the default FMServer_Sample file that ships with every copy of FileMaker Server, and can be used as a starter app for projects.</p>
<p>While at first blush all the enterprise design pattern mumbo-jumbo can sound overwhelming to procedural PHP and FileMaker developers, we&#8217;ve found that an experienced web developer can quickly bootstrap the web project, and then the rigorous separation of concerns makes it far easier to maintain and modify than traditional procedural programming style.</p>
<p>In this article we will lift the hood on the skeleton app and show how clean and importantly how <em>intuitive</em> the code is.</p>
<p>As you&#8217;ll see in these examples, after an initial burst of architectural decision-making and configuration, the code is extremely easy to pick up and modify. We sometimes hear concerns that Zend Framework might be overkill for a simple CWP project, but in practice the &#8220;steep ramp&#8221; argument is not an actual worry, given the right recipes to begin with. As an analogy, it would be unreasonable to assume that someone would have to know how to write VBS as a prerequisite to making useful spreadsheets in Microsoft Excel.</p>
<p>First a quick word about scalability: while using enterprise patterns can benefit a project of any size, these techniques will not change the fact that the project will be communication with the FileMaker Server XML API. There are significant advantages in terms of maintainability, security, etc. These techniques provide excellent encapsulation of all the FileMaker-specific DML, so if the day should come when some or all of the application outgrows the scaling limitations of FileMaker, the switch to an alternative data store such as MongoDb is much simpler.</p>
<h3>Project Structure</h3>
<p>This is the directory structure for the SimpleFM-skeleton application.</p>
<p>For the purpose of this post, <code>module</code> is the only one top-level directory we really dig into, but I&#8217;ll start out with a very brief explanation of the other top level directories first.<br />
<img class=" wp-image-12559 size-full alignright" alt="SimpleFM_skeleton_project_structure" width="157" height="175"/></p>
<ul class="bullet-list">
<li><code>.vagrant</code> is a Vagrant cache directory that we always ignore.</li>
<li><code>config</code> is where all environment configuration files go.</li>
<li><code>data</code> is optional, is ignored by Git and is used for things like caches.</li>
<li><code>documentation</code> is self evident. Put things in there such as sample data and special instructions that are too detailed for the main README</li>
<li><code>module</code> we&#8217;ll come back to.</li>
<li><code>public</code> is the web root. Files in here are directly accessible in the browser.</li>
<li><code>vendor</code> is a Composer-managed directory where all the library code is located.</li>
</ul>
<p>This is a <em>very</em> typical structure, and the <code>modules</code> directory is set up for PSR-0 autoloading. What this means is that everything inside a module&#8217;s <code>src</code> directory are classes with namespaces that match the directory names.</p>
<p>We can see that the application has two modules: <code>Application</code> and <code>SimpleFMAuth</code>. For the purpose of this post we&#8217;ll ignore the latter, except to say that it doesn&#8217;t have any controllers or views of it&#8217;s own. It&#8217;s entire job is to handle authentication and authorization, so it was broken out of the main module for clarity.</p>
<p><img class=" wp-image-12563 size-full alignright" alt="SimpleFM_skeleton_module_structure" width="236" height="478"/>Focusing on <code>module/Application</code>, the structure is <em>very</em> typical as well.</p>
<ul class="bullet-list">
<li><code>config</code> is where all module configuration files go (things which do not change depending on environment).</li>
<li><code>src/Application</code> is the namespace root for the autoloader.</li>
<li><code>view</code> is where the html templates go. These are not classes, so they have no namespace, however, they are typically organized in the same semantic hierarchy.</li>
<li><code>Module.php</code> is required to define a ZF2 module. Everything else pivots off this special duck-typed class.</li>
</ul>
<p>Once <code>Module.php</code> is configured, the two places that we make most changes are <code>view/application</code> for html, and <code>src/Application</code> for most other things. Let&#8217;s assume that <code>view</code> is self-explanatory, and move directly to <code>src</code>.</p>
<p>The <code>src</code> directory puts us into the pure OOP realm. All the classes in it are part of the <code>Application</code> namespace. We see a clear separation of concerns, as we&#8217;d expect if we&#8217;re following OOP best practices. <code>Application&#92;Controller</code> and <code>Application&#92;Form</code> should be fairly self explanatory in the context of an MVC (or Model/View/Controller) application.</p>
<p>Given what we&#8217;ve discussed so far, we can clearly see where to go if we want to manage the views (the V in MVC) and where to go to manage the Controllers (the C in MVC), and Forms, which help bridge between views and controllers, do not get their own letter in MVC, but are a familiar concept, even to non-developers. So where is the model (the M in MVC)?</p>
<h3>The Model</h3>
<p>When it comes to intro-level discussions such as this one, the Model is arguably given short shrift, despite it arguably being the most important. I have hypothesized that one reason that it almost <em>must</em> be left under-addressed is because it is the most inherently variable aspect of an application. There are two primary things that the model encompasses: the persistence strategy (<em>how</em> to store and retrieve information), and the domain model (<em>what</em> to store, and the <em>rules</em> that govern the what). SimpleFM provides a solution for well defined persistence and domain model with an AbstractGateway, and AbstractEntity respectively.</p>
<h4>Domain Model with AbstractEntity</h4>
<p>We&#8217;ll address the concept of Entity first. Entity is the OOP term for what we might loosely call a record. Generally speaking, every record in a table can be loaded into an Entity that and vice versa. This is vastly over-simplifying the matter, so just mentally bookmark the fact that we&#8217;re only making a loose association here, but very often this is exactly what happens. So we will ignore the edge cases and exceptions here. When we work with data in OOP, we need collections of objects, not tables of data. When we convert a table record to an Entity, we <code>hydrate</code> it, in common parlance. In SimpleFM we use <code>unserialize</code> as a synonym for <code>hydrate</code>. An Entity in its pure form does not know anything about how it is serialized, unserialized, etc. A pure Entity should only define the attributes of what it represents. For example, if the domain model has the concept of Project, there will be a ProjectEntity class which defines the properties of a Project, including its relationships with other Entities. For example, a Project might have a collection of zero or more Tasks. So it follows that we have a TaskEntity with a mandatory Project property.</p>
<p>In SimpleFM, we have created an opt-in AbstractEntity which entity classes can extend, and which gives it some entity-specific meta-data characteristics and behaviors. Let&#8217;s take a look at an example Project entity with just it&#8217;s properties first:</p>
<pre>
&lt;?php
namespace Application&#92;Entity;

use Soliant&#92;SimpleFM&#92;ZF2&#92;Entity&#92;AbstractEntity;
use Doctrine&#92;Common&#92;Collections&#92;ArrayCollection;
use Application&#92;Entity&#92;Task;

class Project extends AbstractEntity
{
	/**
	 * Writable Fields
	 */
	protected $projectName;
	protected $description;
	protected $tag;

	/**
	 * Read-only Fields
	 */
	protected $id;
	protected $startDate;
	protected $dueDate;
	protected $daysRemaining;
	protected $daysElapsed;
	protected $statusOnScreen;
	protected $createdBy;
	protected $projectCompletionProgressBar;

	/**
	 * Child Associations
	 */
	protected $tasks;

// snip...
</pre>
<p>We see the properties grouped under three section comments. When defining a SimpleFM entity it&#8217;s important to identify which fields on the FileMaker layout will need to be updated. Clearly it&#8217;s impossible to write to things like calculation fields. For this reason, fields are segregated into writable and read-only. We also have associations, which are related entities which can be displayed in a portal in FileMaker. SimpleFM expects each writable property to have a getter and a setter defined, and each read-only property to have a getter defined, however, we omit the getters/setters here for clarity.</p>
<p>Because we have extended <code>AbstractEntity</code>, we inherit some base behaviors, and we&#8217;re required to implement some abstract methods so that the entity can be interrogated for it&#8217;s own meta information, such as the field mapping to be used for serialization and unserialization. Let&#8217;s take a look at the required mapping methods for our Project entity.</p>
<pre>
// snip...

public
function getFieldMapWriteable()
{
    $map = [
        'projectName' =&gt; 'Project Name',
        'description' =&gt; 'Description',
        'tag' =&gt; 'Tag',
    ];
    return $map;
}

public
function getFieldMapReadonly()
{
    $map = [
        'id' =&gt; 'PROJECT ID MATCH FIELD',
        'startDate' =&gt; 'Start Date',
        'dueDate' =&gt; 'Due Date',
        'daysRemaining' =&gt; 'Days Remaining',
        'daysElapsed' =&gt; 'Days Elapsed',
        'statusOnScreen' =&gt; 'Status on Screen',
        'createdBy' =&gt; 'Created By',
    ];
    return $map;
}

// snip...
</pre>
<p>These are arrays that in turn define which properties are writable and which are read-only. They also define the correlation between the property name and the FileMaker field name.</p>
<p>The final customization required for Project is to define how to handle the associated entity, Task. We start out be overriding the constructor, and defining the <code>tasks</code> property as an empty <code>ArrayCollection</code>. This way, even when empty, it will always be an <code>ArrayCollection</code>. Then we call the parent constructor normally.</p>
<p>SimpleFM design dictates that Associated entities cannot be persisted indirectly, but the entity needs special instructions for unserialization. We override <code>unserialize</code> and call the parent method. Then we handle the portal row by looping over it and adding a new Task instance to the <code>ArrayCollection</code> for each row.</p>
<p>Finally we are required to implement two public methods which define a default layout name for Project and a default route segment for use in constructing routes (urls) with this entity.</p>
<pre>
// snip...

public function __construct($simpleFMAdapterRow = array())
{
    $this-&gt;tasks = new ArrayCollection();
    parent::__construct($simpleFMAdapterRow);
}

public function unserialize()
{
    parent::unserialize();

    if (!empty($this-&gt;simpleFMAdapterRow[&quot;Tasks&quot;][&quot;rows&quot;])){
        foreach ($this-&gt;simpleFMAdapterRow[&quot;Tasks&quot;][&quot;rows&quot;] as $row){
            $this-&gt;tasks-&gt;add(new Task($row));
        }
    }

    return $this;
}

public function getDefaultWriteLayoutName()
{
    return 'Project';
}

public function getDefaultControllerRouteSegment()
{
    return 'project';
}

// snip...
</pre>
<p>This may sound a bit tricky at first, but I assure you, if you maintain your FileMaker web layouts and entities together, you will find that the centralization of the serialize/unserialize rules pays off many times over.</p>
<p>Next, let&#8217;s take a look at persistence of entities.</p>
<h4>Persistence with AbstractGateway</h4>
<p>In many ways the <code>AbstractGateway</code> is simpler to implement than <code>AbstractEntity</code>. The minimum requirements are that a Gateway class be defined along with a factory class to set it up, like these:</p>
<pre>
&lt;?php
namespace Application&#92;Gateway;

use Soliant&#92;SimpleFM&#92;ZF2&#92;Gateway&#92;AbstractGateway;
use Application&#92;Entity&#92;Project as ProjectEntity;

class Project extends AbstractGateway
{

}
</pre>
<pre>
&lt;?php
namespace Application&#92;Gateway&#92;Factory;

use Zend&#92;ServiceManager&#92;FactoryInterface;
use Zend&#92;ServiceManager&#92;ServiceLocatorInterface;
use Application&#92;Entity&#92;Project as Entity;
use Application&#92;Gateway&#92;Project as Gateway;

class ProjectGatewayFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $entity = new Entity();
        $simpleFMAdapter = $serviceLocator-&gt;get('simple_fm');
        return new Gateway($entity, $simpleFMAdapter);
    }
}
</pre>
<p>Sometimes the Gateway class does not need to implement any of it&#8217;s own methods, as in the example above, because there are a number of existing useful methods already defined on <code>AbstractEntity</code>. Custom gateway methods, however, are where you can start to define basic business logic for your model. If you application gets more complicated, you should consider implementing service classes, and keep the Gateways strictly for the persistence methods, however simple use cases often don&#8217;t warrant a separate service layer in the model.</p>
<p>Here&#8217;s a fictional Project gateway method, which implements some nonsesnse business logic by chaining existing <code>find</code> and <code>edit</code> methods every time <code>helloWorld</code> is invoked.</p>
<pre>
&lt;?php
namespace Application&#92;Gateway;

use Soliant&#92;SimpleFM&#92;ZF2&#92;Gateway&#92;AbstractGateway;
use Application&#92;Entity&#92;Project as ProjectEntity;

class Project extends AbstractGateway
{
    public function helloWorld($id) {

        $project = $this-&gt;find($id);
        $project-&gt;setProjectName('Launch web site ' . $project-&gt;getModid())
            -&gt;setDescription('myDescription')
            -&gt;setTag('myTag');

        return $this-&gt;edit($project);
    }
}
</pre>
<h3>Conclusion</h3>
<p>By investing in a little bit of setup with SimpleFM and ZendFramework, it&#8217;s easy to write FileMaker CWP apps with excellent encapsulation and separation of concerns. You too can have controller actions that look as clean as this.</p>
<pre>
public function listMostPopularAction()
{
    return [
        'mostPopular' =&gt; $this-&gt;itemGateway-&gt;getMostPopular(),
        'isActive' =&gt; $this-&gt;userService-&gt;isActive(),
    ];
}
</pre>
<p>The post <a rel="nofollow" target="_blank" href="http://www.soliantconsulting.com/blog/2015/07/enterprise-quality-web-apps-with-simplefm">Enterprise-quality Web apps with SimpleFM</a> appeared first on <a rel="nofollow" target="_blank" href="http://www.soliantconsulting.com">Soliant Consulting</a>.</p>]]></content:encoded>
      </item>
      <item>
         <title>Evan Coury – A simple explanation of git-rebase</title>
         <link>http://www.soliantconsulting.com/blog/2015/07/a-simple-explanation-of-git-rebase</link>
         <description>&lt;p&gt;In December of 2011, Evan Coury posted an article on his now-defunct blog (original link is a 404) titled &amp;#8220;A simple explanation of git-rebase&amp;#8221; and his Twitter post still comes up in searches. I really like this post for its clarity. In Evan&amp;#8217;s own words: …this post was mostly meant to help you feel confident [&amp;#8230;]&lt;/p&gt;
&lt;p&gt;The post &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.soliantconsulting.com/blog/2015/07/a-simple-explanation-of-git-rebase&quot;&gt;Evan Coury &amp;#8211; A simple explanation of git-rebase&lt;/a&gt; appeared first on &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.soliantconsulting.com&quot;&gt;Soliant Consulting&lt;/a&gt;.&lt;/p&gt;</description>
         <guid isPermaLink="false">http://www.soliantconsulting.com/?p=12267</guid>
         <pubDate>Tue, 14 Jul 2015 18:20:48 +0000</pubDate>
         <content:encoded><![CDATA[<p>In December of 2011, Evan Coury posted an article on his now-defunct blog (<a rel="nofollow" target="_blank" href="http://blog.evan.pro/a-simple-explanation-of-git-rebase">original link</a> is a 404) titled &#8220;A simple explanation of git-rebase&#8221; and his <a rel="nofollow" target="_blank" href="https://twitter.com/evandotpro/status/142825015182770176">Twitter post still comes up</a> in searches. I really like this post for its clarity. In Evan&#8217;s own words:</p>
<blockquote><p>…this post was mostly meant to help you feel confident that you really understand what it is that git-rebase is doing, why git-push won’t work properly after a rebase if you’ve already pushed any of the rebased commits, and most importantly, how to avoid one of the most common problems I’ve seen with people using git-rebase…</p></blockquote>
<p>Its main virtue is that it does a great job of explaining the concept without over-complicating it. It&#8217;s not a how-to. It&#8217;s specifically written to help people who are already trying to learn git-rebase understand the <em>concept</em>. I&#8217;ve sent out a <a rel="nofollow" target="_blank" href="https://web.archive.org/web/20120111223303/http://blog.evan.pro/a-simple-explanation-of-git-rebase">link to it in the Internet Archive</a> to people learning git-rebase plenty of times already, so I thought I&#8217;d republish it here, and hopefully give it a new life until and unless Evan decides to bring back blog.evan.pro. What follows is taken verbatim from the original post:</p>
<p><span id="more-12267"></span></p>
<p><em>Posted by Evan Coury on December 2, 2011</em></p>
<p>Using <code>git-rebase</code> without actually understanding what it does can cause headaches for you and the developers you’re working with. I don’t like headaches, so let’s take a minute to review what exactly <code>git-rebase</code> does.</p>
<p>Let’s say <code>master</code> is at commit <code>C</code>, and you create a branch <code>feature/my-topic</code>. So you have two branches pointed at the same commit like this:</p>
<pre>          feature/my-topic
         /
A---B---C master
</pre>
<p>Next, you make two commits <code>D</code> and <code>E</code> in <code>feature/my-topic</code> and push it to your origin (we’ll say GitHub):</p>
<pre>
           D---E feature/my-topic
         / 
A---B---C master
</pre>
<p>Meanwhile, let’s say master also gets two commits, <code>D'</code> and <code>E'</code>:</p>
<pre>           D---E feature/my-topic
         / 
A---B---C---D'---E' master
</pre>
<p>So now you want to rebase your <code>feature/my-topic</code> branch onto <code>master</code>, so you run <code>git rebase master</code>. The result is this:</p>
<pre>                    F---G feature/my-topic
                  / 
A---B---C---D'---E' master
</pre>
<p>The key here is to recognize that commits <code>D</code> and <code>E</code> from <code>feature/my-topic</code> no longer exist, and have been re-written as <code>F</code> and <code>G</code> respectively, with master’s HEAD (<code>E'</code>) as the new base. This means that <strong>some history has been re-written</strong>. Because of this, if you were to try running <code>git push origin feature/my-topic</code>, you would be greeted with a non-fast-forward error. Instead, if you really need to push the rebased branch up to your origin, you’ll need to run <code>git push -f</code> (see note below).</p>
<p><strong>DO NOT PULL, MERGE, OR REBASE FROM <code>origin/feature/my-topic</code> AT THIS POINT!!!</strong></p>
<p>Why not? Because Git simply thinks, “Oh look, <code>origin/feature/my-topic</code> has two commits (<code>D</code> and <code>E</code>) that we don’t have here locally in <code>feature/my-topic</code>. Let’s merge them in!”… That’s a problem though, because we do have those commits, but their hashes were re-written to <code>F</code> and <code>G</code> when we ran <code>git rebase</code>.</p>
<p>So what would happen if you actually did merge? Your history would look something like this mess:</p>
<pre>                    D---E---X---F--G feature/my-topic
                  / 
A---B---C---D'---E' master
</pre>
<p>In the above result, <code>D</code> is a duplicate of <code>F</code>, <code>E</code> is a duplicate of <code>G</code>, and <code>X</code> is a useless merge commit gluing the whole mess together. Using <code>git-rebase</code> may avoid the merge commit, but you’ll still have those pesky duplicates, so you’re no better off.</p>
<p><strong>NOTE:</strong> If there are other developers deriving work from your <code>feature/my-topic</code> branch that is pushed; you must be careful about performing a <code>git push -f</code>, as it can cause problems for those other developers. Also, <code>git push -f</code> can be a somewhat destructive operation if used carelessly. In the context I described, it should be pretty safe, but unless you have a specific reason, it’s generally better to just leave it to the person merging your pull request to perform the rebase locally on their end. This results in <code>master</code> being able to simply fast-forward to the new commit (guaranteed no merge conflicts when merging into <code>master</code>) and no re-written history is forcefully pushed to any public repositories.</p>
<p>The post <a rel="nofollow" target="_blank" href="http://www.soliantconsulting.com/blog/2015/07/a-simple-explanation-of-git-rebase">Evan Coury &#8211; A simple explanation of git-rebase</a> appeared first on <a rel="nofollow" target="_blank" href="http://www.soliantconsulting.com">Soliant Consulting</a>.</p>]]></content:encoded>
      </item>
      <item>
         <title>Annotate and Upload Screen Shots with Skitch</title>
         <link>http://www.soliantconsulting.com/soliant-tv/2015/07/annotate-and-upload-screen-shots-with-skitch</link>
         <description>&lt;p&gt;In this short video, learn how to efficiently make annotated screenshots and upload them directly to web forms, emails, or any other target that accepts dragged files, without interacting directly with the file system.&lt;/p&gt;
&lt;p&gt;The post &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.soliantconsulting.com/soliant-tv/2015/07/annotate-and-upload-screen-shots-with-skitch&quot;&gt;Annotate and Upload Screen Shots with Skitch&lt;/a&gt; appeared first on &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.soliantconsulting.com&quot;&gt;Soliant Consulting&lt;/a&gt;.&lt;/p&gt;</description>
         <guid isPermaLink="false">http://www.soliantconsulting.com/?p=12310</guid>
         <pubDate>Fri, 10 Jul 2015 17:11:59 +0000</pubDate>
         <content:encoded><![CDATA[<p>In this short video, learn how to efficiently make annotated screenshots and upload them directly to web forms, emails, or any other target that accepts dragged files, without interacting directly with the file system.</p>
<p>The post <a rel="nofollow" target="_blank" href="http://www.soliantconsulting.com/soliant-tv/2015/07/annotate-and-upload-screen-shots-with-skitch">Annotate and Upload Screen Shots with Skitch</a> appeared first on <a rel="nofollow" target="_blank" href="http://www.soliantconsulting.com">Soliant Consulting</a>.</p>]]></content:encoded>
      </item>
      <item>
         <title>Web Development</title>
         <link>http://www.soliantconsulting.com/soliant-tv/2015/07/web-development-playlist</link>
         <description>&lt;h4&gt;Playlist for Web Applications videos&lt;/h4&gt;
&lt;p&gt; &lt;a rel=&quot;nofollow&quot;&gt;View all in playlist...&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The post &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.soliantconsulting.com/soliant-tv/2015/07/web-development-playlist&quot;&gt;Web Development&lt;/a&gt; appeared first on &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.soliantconsulting.com&quot;&gt;Soliant Consulting&lt;/a&gt;.&lt;/p&gt;</description>
         <guid isPermaLink="false">http://www.soliantconsulting.com/?p=12297</guid>
         <pubDate>Fri, 10 Jul 2015 16:15:40 +0000</pubDate>
         <content:encoded><![CDATA[<p><div class="clear" style="height:20px;"></div>Building web applications that are easy to use and provide a good user experience are integral to the success of a project. However, sometimes it&#8217;s what you don&#8217;t see that makes a difference. This playlist is a bit of a catch-all for our tools of the trade, tips, and other things we have sitting back on our workbench.
<div class="clearfix divider divider_dashed1 left lessmar "><span></span><span></span></div>
<div class="arve-wrapper arve-normal-wrapper arve-iframe-wrapper alignleft" style="max-width:730px;"><div class="arve-embed-container" style="padding-bottom:56%;"></div></div> 
<h3><a rel="nofollow">Set Up Postman for Optimal JSON API Debugging</a></h3>
<p><div class="clear" style="height:20px;"></div><strong><em>August 5, 2015</em></strong> &#8211; This video covers the basics of Postman, a Chrome app for testing APIs. See how to define sharable configurations and use environment variables to your advantage.
<div class="clearfix divider divider_dashed1 left lessmar "><span></span><span></span></div>
<div class="arve-wrapper arve-normal-wrapper arve-iframe-wrapper alignleft" style="max-width:730px;"><div class="arve-embed-container" style="padding-bottom:56%;"></div></div> 
<h3><a rel="nofollow">Introduction to Vagrant and Atlas</a></h3>
<p><div class="clear" style="height:20px;"></div><strong><em>July 22, 2015</em></strong> &#8211; This video covers the basics of Vagrant, and how you can use the brand new Atlas service from Hashicorp to optimize your developer virtualization.
<div class="clearfix divider divider_dashed1 left lessmar "><span></span><span></span></div>
<div class="arve-wrapper arve-normal-wrapper arve-iframe-wrapper alignleft" style="max-width:730px;"><div class="arve-embed-container" style="padding-bottom:56%;"></div></div> 
<h3 class="yt watch-title-container"><span id="eow-title" class="watch-title " dir="ltr" title="Annotate and Upload Screen Shots with Skitch"><a rel="nofollow">Annotate and Upload Screen Shots with Skitch </a></span></h3>
<p><div class="clear" style="height:20px;"></div><strong><em>July 10, 2015</em></strong> &#8211; In this short video, learn how to efficiently make annotated screenshots and upload them directly to web forms, emails, or any other target that accepts dragged files, without interacting directly with the file system.
<p>The post <a rel="nofollow" target="_blank" href="http://www.soliantconsulting.com/soliant-tv/2015/07/web-development-playlist">Web Development</a> appeared first on <a rel="nofollow" target="_blank" href="http://www.soliantconsulting.com">Soliant Consulting</a>.</p>]]></content:encoded>
      </item>
   </channel>
</rss>
<!-- fe8.yql.bf1.yahoo.com compressed/chunked Thu Oct  1 07:39:09 UTC 2015 -->
