<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1137761125875994292</id><updated>2026-01-04T21:43:32.440-05:00</updated><category term=".NET"/><category term="Review"/><category term="ASP.NET"/><category term="visual studio 2008"/><category term="c#"/><category term=".NET 3.5"/><category term="MVC"/><category term="SQL Server 2008"/><category term="sql"/><category term="Book Review"/><category term="unit-testing"/><category term="Excel"/><category term="Team Foundation Server"/><category term="VB.NET"/><category term="WPF"/><category term="free"/><category term="Mirth"/><category term="nopCommerce"/><category term="visual sourcesafe"/><category term="vss"/><category term="IIS"/><category term="MSTest"/><category term="Mac OS"/><category term="SQL Reporting Services"/><category term="books"/><category term="ruby"/><category term="source control"/><category term="Ajax"/><category term="Android"/><category term="Apache"/><category term="Balsamiq Mockups"/><category term="Docker"/><category term="JavaScript"/><category term="Lunchtime Sessions"/><category term="Mac"/><category term="Media Center"/><category term="Money"/><category term="NDepend"/><category term="Powershell"/><category term="SSRS"/><category term="Software"/><category term="Syntax Highlighting"/><category term="Version Control"/><category term="Vista"/><category term="Windows 8"/><category term="clickonce"/><category term="ebook"/><category term="gallio"/><category term="git"/><category term="itvn"/><category term="powerquery"/><category term="refactor"/><category term="resharper"/><category term="security"/><category term="streaming media"/><category term="sublime-text"/><category term="subversion"/><category term="training"/><category term="typemock"/><category term="virtual server"/><category term="visual studio 2012"/><category term="#develop"/><category term="ASP.NET MVC"/><category term="COVID-19"/><category term="Charity"/><category term="Cocoa"/><category term="Continuous Integration"/><category term="Crystal Reports"/><category term="Eclipse"/><category term="Elmah"/><category term="Finances"/><category term="Google Chrome"/><category term="Google Documents"/><category term="Google Reader"/><category term="Hardware"/><category term="JQTouch"/><category term="JQuery"/><category term="JustMock"/><category term="MOQ"/><category term="MacHeist"/><category term="Matplotlib"/><category term="MbUnit"/><category term="Messaging"/><category term="Microsoft Health - Common User Interface"/><category term="Mobile Device Browser File"/><category term="NHibernate"/><category term="NUnit"/><category term="Napkee"/><category term="OSS"/><category term="Obihai"/><category term="OpenSSL"/><category term="Personal"/><category term="PowerCommands"/><category term="PowerPivot"/><category term="PyCharm"/><category term="Python"/><category term="Rant"/><category term="Razor View Engine"/><category term="Reflector"/><category term="Screen Design"/><category term="Syncfusion"/><category term="Tableau"/><category term="Tableau-Desktop"/><category term="Tableau-Server"/><category term="Tuner"/><category term="VHD"/><category term="VHD Resizer"/><category term="VLC"/><category term="Web Deployment Project"/><category term="Windows 7"/><category term="active directory"/><category term="adsi"/><category term="blogger"/><category term="bug"/><category term="certification"/><category term="clisp"/><category term="clojure"/><category term="coderush"/><category term="couchbase"/><category term="events"/><category term="functional-programming"/><category term="gradle"/><category term="hadoop"/><category term="hauppauge"/><category term="home office"/><category term="html"/><category term="iPhone"/><category term="java"/><category term="linq"/><category term="macOS"/><category term="making-life-easier"/><category term="manifest"/><category term="mcpd"/><category term="memcached"/><category term="nuget"/><category term="opinion"/><category term="pc anywhere"/><category term="postgresql"/><category term="powertools"/><category term="scala"/><category term="subversion hooks"/><category term="sysadmin"/><category term="sysinternals"/><category term="terminal"/><category term="visual studio 2010"/><category term="visual-studio"/><category term="windows"/><category term="windows home server"/><category term="windows server 2008"/><category term="working remotely"/><category term="xUnit"/><category term="xaml"/><title type='text'>Hello (cruel) World</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://irwinj.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default?alt=atom&amp;redirect=false'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default?alt=atom&amp;start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>138</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-5421431762555299759</id><published>2022-01-07T11:28:00.002-05:00</published><updated>2022-01-11T22:24:52.424-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Tableau"/><category scheme="http://www.blogger.com/atom/ns#" term="Tableau-Desktop"/><category scheme="http://www.blogger.com/atom/ns#" term="Tableau-Server"/><title type='text'>Tableau Desktop - SSLHandshakeException when logging into Tableau Server</title><content type='html'>&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;I had issues this morning loging into Tableau Server from Tableau Desktop (2021.4). Specifically, the following error:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;SSLHandshakeException&lt;/p&gt;&lt;p&gt;PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Interestingly, when entering my credentials it was via the chrome browser rather than the previous in-app dialog. After a &lt;a href=&quot;https://community.tableau.com/s/question/0D54T000013FaGWSA0/ssl-handshake-error&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;bit of digging&lt;/a&gt;&amp;nbsp;the fix turned out to be simple enough via creation of a single registry key to bypass browser-based login.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Computer\HKEY_CURRENT_USER\Software\Tableau\Tableau 2021.4\Settings&lt;/li&gt;&lt;li&gt;Create a new DWORD value named WorkgroupUseEmbeddedBrowserServerSignIn&lt;/li&gt;&lt;li&gt;For the value enter 1&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://irwinj.blogspot.com/feeds/5421431762555299759/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1137761125875994292/5421431762555299759?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/5421431762555299759'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/5421431762555299759'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2022/01/tableau-desktop-sslhandshakeexception.html' title='Tableau Desktop - SSLHandshakeException when logging into Tableau Server'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-8737370947396618305</id><published>2021-04-14T07:36:00.025-04:00</published><updated>2021-04-14T07:36:00.628-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Excel"/><category scheme="http://www.blogger.com/atom/ns#" term="powerquery"/><title type='text'>PowerQuery - Merging Columns with a Line Break</title><content type='html'>&lt;p&gt;It is possible to merge columns with a line feed/break when using Power Query using #(lf) as a custom separator.&amp;nbsp;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVkggluiufjvm_F7JPC8ZqQ1KQPsuLYlYl-UM0M9ZpkBslg4cK-uQcLI6Ncs65sIc7IgR9ks_qn5ZdLILZqNzoOt92ytB_Ew_MDB5HzWNG6hu2mWM4nc0Zh-4MmfUh9L1btvqBNSHQgQKT/s705/1.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;294&quot; data-original-width=&quot;705&quot; height=&quot;205&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVkggluiufjvm_F7JPC8ZqQ1KQPsuLYlYl-UM0M9ZpkBslg4cK-uQcLI6Ncs65sIc7IgR9ks_qn5ZdLILZqNzoOt92ytB_Ew_MDB5HzWNG6hu2mWM4nc0Zh-4MmfUh9L1btvqBNSHQgQKT/w495-h205/1.PNG&quot; width=&quot;495&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;i&gt;However&lt;/i&gt;, attempting to do so&amp;nbsp;as in the above example results in the following:&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQk9XcciVBy5wxRd6xuBJS7OEacNsiq2r4Nm46UxfNhQhSMUMDnRUMFcmtrWoiS74n-I3u99tucz1yj6rifGcFpyQ7r-53p7LAXVSY1-_vO6C5s8sWV6NAY_aYEJxGgp_J6wFKT4QFwXfy/s1111/2.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;40&quot; data-original-width=&quot;1111&quot; height=&quot;24&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQk9XcciVBy5wxRd6xuBJS7OEacNsiq2r4Nm46UxfNhQhSMUMDnRUMFcmtrWoiS74n-I3u99tucz1yj6rifGcFpyQ7r-53p7LAXVSY1-_vO6C5s8sWV6NAY_aYEJxGgp_J6wFKT4QFwXfy/w638-h24/2.PNG&quot; width=&quot;638&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;That is, &lt;b&gt;#(lf) &lt;/b&gt;is (seemingly escaped) and replaced with &lt;b&gt;#(#)(lf)&lt;/b&gt;. The easiest thing to do at this point to manually update the formula in the 2nd screenshot removing the middle &lt;b&gt;(#)&lt;/b&gt;. Don&#39;t forget to wrap text on the column that will expose this data.&amp;nbsp;&lt;div&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://irwinj.blogspot.com/feeds/8737370947396618305/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1137761125875994292/8737370947396618305?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/8737370947396618305'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/8737370947396618305'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2021/04/powerquery-merging-columns-with-line.html' title='PowerQuery - Merging Columns with a Line Break'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVkggluiufjvm_F7JPC8ZqQ1KQPsuLYlYl-UM0M9ZpkBslg4cK-uQcLI6Ncs65sIc7IgR9ks_qn5ZdLILZqNzoOt92ytB_Ew_MDB5HzWNG6hu2mWM4nc0Zh-4MmfUh9L1btvqBNSHQgQKT/s72-w495-h205-c/1.PNG" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-7759212747333337814</id><published>2021-04-13T10:04:00.001-04:00</published><updated>2021-04-13T10:04:23.114-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Excel"/><category scheme="http://www.blogger.com/atom/ns#" term="PowerPivot"/><category scheme="http://www.blogger.com/atom/ns#" term="powerquery"/><title type='text'>Excel - Adding an existing Pivot table to the data model</title><content type='html'>&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;I&#39;ve been working more with, and continue to be amazed by, Power Pivot. I recently ran into an issue where I needed to add the data for an existing Power Pivot report to the Data Model. There is a checkbox that makes this easy when creating a PivotTable:&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwzQDAuiS7Cr4wkQw7q8oTZo0j7aNV1bLlYPSUS5jfwG-UISFapwI-c_ZOtK8NCh8fNTO88SgwJGkA5f7bYhk9094T8gnMz-6q5E1WYDQ5EgllMzZM_E7nMteUoKzTguNqPuqVLgkHjPM5/s395/1.+Dialog.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;Create PivotTable dialog highlighting option to add data to data model&quot; border=&quot;0&quot; data-original-height=&quot;353&quot; data-original-width=&quot;395&quot; height=&quot;286&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwzQDAuiS7Cr4wkQw7q8oTZo0j7aNV1bLlYPSUS5jfwG-UISFapwI-c_ZOtK8NCh8fNTO88SgwJGkA5f7bYhk9094T8gnMz-6q5E1WYDQ5EgllMzZM_E7nMteUoKzTguNqPuqVLgkHjPM5/w320-h286/1.+Dialog.PNG&quot; title=&quot;PivotTable Dialog&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;As so often happens, the analysis grew in scope/importance and I found myself needing to add the data to the data model. While it&#39;s not obvious how, there &lt;i&gt;is &lt;/i&gt;a way to add an existing Pivot table to the data model. There&#39;s a &lt;i&gt;More Tables... &lt;/i&gt;link in the PivotTable Fields pane.&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJ2Nwy_ubEzHKt6gddfco442DEJDIEKhwh-JR8NhkUVi8P-3_AnpgCDu8CLcGR8o0-zagklchAy9mHOgvll79IC5xisGTjeqQAFOmu9lQozueugk-y6d1bDiipAaLC8bXlN7sMJ1zXIB10/s404/2.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;PivotTable fields pane highlighting the &#39;more tables...&#39; link&quot; border=&quot;0&quot; data-original-height=&quot;404&quot; data-original-width=&quot;336&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJ2Nwy_ubEzHKt6gddfco442DEJDIEKhwh-JR8NhkUVi8P-3_AnpgCDu8CLcGR8o0-zagklchAy9mHOgvll79IC5xisGTjeqQAFOmu9lQozueugk-y6d1bDiipAaLC8bXlN7sMJ1zXIB10/w266-h320/2.PNG&quot; title=&quot;PivotTable fields&quot; width=&quot;266&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;Clicking on the&amp;nbsp;&lt;i&gt;More Tables... &lt;/i&gt;results in a dialog confirming that you want to &lt;i&gt;Create a New PivotTable&lt;/i&gt;.&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1tz6n-tBMD2pPzxHw00iiJ95ZUO_RrXeS64ng2_xrxSs-sXiVGcGngJL_9v5l7L33YTwiHlP-31H0H8717YVwtsmkFK4egHtYj92fdkCcTXQQkNWQnAx1v_zNn7D5Tb883wOAb8nCr6VK/s447/3.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;Create a New PivotTable dialog. The prompt is received when the &#39;More Tables...&#39; option is clicked&quot; border=&quot;0&quot; data-original-height=&quot;147&quot; data-original-width=&quot;447&quot; height=&quot;105&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1tz6n-tBMD2pPzxHw00iiJ95ZUO_RrXeS64ng2_xrxSs-sXiVGcGngJL_9v5l7L33YTwiHlP-31H0H8717YVwtsmkFK4egHtYj92fdkCcTXQQkNWQnAx1v_zNn7D5Tb883wOAb8nCr6VK/w320-h105/3.PNG&quot; title=&quot;Create a New PivotTable dialog&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;Doing so will result in the creation of the new PivotTable in a new sheet. By default the data is added to the data model. You&#39;ll likely lose some formatting but for anything other than a trivial PivotTable, this should save effort, as it did for me.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://irwinj.blogspot.com/feeds/7759212747333337814/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1137761125875994292/7759212747333337814?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/7759212747333337814'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/7759212747333337814'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2021/04/excel-adding-existing-pivot-table-to.html' title='Excel - Adding an existing Pivot table to the data model'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwzQDAuiS7Cr4wkQw7q8oTZo0j7aNV1bLlYPSUS5jfwG-UISFapwI-c_ZOtK8NCh8fNTO88SgwJGkA5f7bYhk9094T8gnMz-6q5E1WYDQ5EgllMzZM_E7nMteUoKzTguNqPuqVLgkHjPM5/s72-w320-h286-c/1.+Dialog.PNG" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-3558678600365212346</id><published>2020-11-16T16:31:00.002-05:00</published><updated>2020-11-16T16:33:32.543-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Excel"/><category scheme="http://www.blogger.com/atom/ns#" term="Money"/><title type='text'>Money in Excel - Fatal Flaw Fixed</title><content type='html'>&lt;p&gt;In June I posted about a &lt;a href=&quot;https://irwinj.blogspot.com/2020/06/money-in-excel-fatal-flaw.html&quot; rel=&quot;&quot; target=&quot;_blank&quot;&gt;Fatal Flaw&lt;/a&gt; in &lt;i&gt;Money in Excel &lt;/i&gt;- the inability to add multiple accounts at the same institution. It&#39;s a short read so I won&#39;t rehash it.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Fortunately, a few months on and I received this very satisfying email from Microsoft, indicating that Multi-Credential Support has been added (I tested and it works great!).&amp;nbsp;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjU_h8ReKXx9Wx4ut0YQgie9j9O4xbxDw6vnynRigktaGp3-Hhjn6pVk4lrM80D5pDyhk4F9zevms4bmX3TRKlJ_M6gtnVMVVzVIkX1XQjFmbpnFH-9v7AITo773_2bDcKILz2Hrt2iKArT/s1480/Money_in_Excel_Message.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;936&quot; data-original-width=&quot;1480&quot; height=&quot;253&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjU_h8ReKXx9Wx4ut0YQgie9j9O4xbxDw6vnynRigktaGp3-Hhjn6pVk4lrM80D5pDyhk4F9zevms4bmX3TRKlJ_M6gtnVMVVzVIkX1XQjFmbpnFH-9v7AITo773_2bDcKILz2Hrt2iKArT/w400-h253/Money_in_Excel_Message.jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;This add-in has a ton of potential. I am especially excited to use the tools I have expertise in to help manage my finances. This was the only roadblock to adoption for me. Kudos to Microsoft for listening to feedback and making the appropriate updates.&amp;nbsp;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://irwinj.blogspot.com/feeds/3558678600365212346/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1137761125875994292/3558678600365212346?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/3558678600365212346'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/3558678600365212346'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2020/11/money-in-excel-fatal-flaw-fixed.html' title='Money in Excel - Fatal Flaw Fixed'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjU_h8ReKXx9Wx4ut0YQgie9j9O4xbxDw6vnynRigktaGp3-Hhjn6pVk4lrM80D5pDyhk4F9zevms4bmX3TRKlJ_M6gtnVMVVzVIkX1XQjFmbpnFH-9v7AITo773_2bDcKILz2Hrt2iKArT/s72-w400-h253-c/Money_in_Excel_Message.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-2679801722027885401</id><published>2020-07-16T16:01:00.002-04:00</published><updated>2020-07-16T22:06:49.432-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="COVID-19"/><category scheme="http://www.blogger.com/atom/ns#" term="Hardware"/><category scheme="http://www.blogger.com/atom/ns#" term="home office"/><category scheme="http://www.blogger.com/atom/ns#" term="Obihai"/><category scheme="http://www.blogger.com/atom/ns#" term="working remotely"/><title type='text'>Obi2162 with Plantronics CS540</title><content type='html'>COVID has made many of us rethinking our remote-work setup. With the whole family home it became clear that I needed a better phone and one with a headset, since I spend a lot of time on calls. I use Google Voice as my main home/work/cell number as it gives me the flexibility to be anywhere, without needing to worry about missing calls.&amp;nbsp;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I purchased the Obi2162 (part of Obihais&#39; OBi2000 Series Gigabit IP Phone range). I separately purchased a Plantronics CS540 headset. While they worked together out of the box, the Plantronics phone lifter - which is used to mechanically lift the handset when the button on the headset is pressed - was finicky. It didn&#39;t appear to have the strength to lift and put down the phone, likely because of the angles allowed by the phone stand and the physical shape of the phone.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I realized the need for an electronic hook (a device which electronically connects a wireless headset and phone). For those looking, you&#39;ll need two cables - first an OBiEHS cable from Obi, and secondly an&amp;nbsp;APS-11 cable from Plantronics. The OBiEHS was $40 which is exorbitant for a cable, especially considering the phone itself was only $90. The&amp;nbsp;OBiEHS comes with straightforward instructions and connecting the two took about 30 seconds. Work calls may never be the same again.&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://irwinj.blogspot.com/feeds/2679801722027885401/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1137761125875994292/2679801722027885401?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/2679801722027885401'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/2679801722027885401'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2020/07/obi2162-with-plantronics-cs540.html' title='Obi2162 with Plantronics CS540'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-25464794163802989</id><published>2020-06-18T21:26:00.001-04:00</published><updated>2020-07-16T16:02:21.262-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Excel"/><category scheme="http://www.blogger.com/atom/ns#" term="Finances"/><category scheme="http://www.blogger.com/atom/ns#" term="Money"/><title type='text'>Money in Excel - The Fatal Flaw</title><content type='html'>&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGLlWD2I0mqylMX6zuq57h0U8IxOSv3V6S4tVXHmI02uxk2Ne0kWvFsJBKhZVd5vhd2UPBpFlgDN91mEXlpXDohpfU0jRTpVTbLPFphK4tcEYgDWeu7b7fipPFu__GidnmhjSASug1ItIp/s1030/Money.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1030&quot; data-original-width=&quot;668&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGLlWD2I0mqylMX6zuq57h0U8IxOSv3V6S4tVXHmI02uxk2Ne0kWvFsJBKhZVd5vhd2UPBpFlgDN91mEXlpXDohpfU0jRTpVTbLPFphK4tcEYgDWeu7b7fipPFu__GidnmhjSASug1ItIp/s320/Money.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;Money in Excel was recently released to much fanfare. It has the potential, in my eyes at least, to liberate data from Intuit (Mint) and other organizations that offer all-in-one financial tools. Aggregating data from banks, credit cards, etc. and facilitating budgeting through a powerful tool that people are already familiar with is a great value proposition and I was excited to roll up my sleeves.&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;Immediately I ran into its fatal flaw - one so obvious it beggars belief that it made it to production but one I will be happy to forgive once fixed, such is my excitement for this plugin. The issue: dual accounts are not allowed. So, say, you and your partner have the same 401k provider, or separate credit cards with the same company, or separate bank accounts with the same company...that&#39;s a problem. You can only have one of each.&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://irwinj.blogspot.com/feeds/25464794163802989/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1137761125875994292/25464794163802989?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/25464794163802989'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/25464794163802989'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2020/06/money-in-excel-fatal-flaw.html' title='Money in Excel - The Fatal Flaw'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGLlWD2I0mqylMX6zuq57h0U8IxOSv3V6S4tVXHmI02uxk2Ne0kWvFsJBKhZVd5vhd2UPBpFlgDN91mEXlpXDohpfU0jRTpVTbLPFphK4tcEYgDWeu7b7fipPFu__GidnmhjSASug1ItIp/s72-c/Money.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-2275735617302323902</id><published>2018-07-06T10:00:00.002-04:00</published><updated>2020-07-16T20:31:23.474-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Version Control"/><category scheme="http://www.blogger.com/atom/ns#" term="vss"/><title type='text'>Visual SourceSafe - Automating Permission Setup</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div class=&quot;&quot; dir=&quot;auto&quot;&gt;
At this point there can&#39;t be too many shops out there still using VSS. We still have a couple of legacy databases out there that recently had to move to updated servers. Microsoft has a&amp;nbsp;&lt;a href=&quot;https://msdn.microsoft.com/en-us/library/ms181068(v=vs.80).aspx&quot; target=&quot;_blank&quot;&gt;nice guide&lt;/a&gt;detailing requisite permissions and shares but providing Modify permissions on the Users/&amp;lt;username&amp;gt; folder is arduous. Here&#39;s a little shortcut to help. CD into the relevant &quot;Users&quot; folder and execute the following command:&lt;/div&gt;
&lt;div class=&quot;&quot; dir=&quot;auto&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
icacls * /t /grant:r &quot;vss_users&quot;:(OI)(CI)M&lt;/blockquote&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://irwinj.blogspot.com/feeds/2275735617302323902/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1137761125875994292/2275735617302323902?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/2275735617302323902'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/2275735617302323902'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2018/07/visual-sourcesafe-automating-permission.html' title='Visual SourceSafe - Automating Permission Setup'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-3333946732113210254</id><published>2017-05-23T12:52:00.000-04:00</published><updated>2017-05-23T12:52:34.013-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Docker"/><category scheme="http://www.blogger.com/atom/ns#" term="Matplotlib"/><category scheme="http://www.blogger.com/atom/ns#" term="PyCharm"/><category scheme="http://www.blogger.com/atom/ns#" term="Python"/><title type='text'>Pycharm, Docker and Matplotlib on a Mac</title><content type='html'>&lt;h2&gt;The Issue&lt;/h2&gt;&lt;p dir=&quot;auto&quot;&gt;I&#39;m playing with Tensorflow at the moment. I&#39;m loving PyCharm&#39;s docker integration, but the drawback I&#39;ve run into is plotting Matplotlib graphs. When attempting to plot a graph, the following error occurs:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;RuntimeError: Invalid DISPLAY variable&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;h2&gt;The Workaround&lt;/h2&gt;&lt;p dir=&quot;auto&quot;&gt;The standard workaround is to save plots as images and open them from the local filesystem, like so:&lt;br&gt;&lt;/p&gt;&lt;div class=&quot;embed-wrapper&quot; data-url=&quot;gist.github.com/jasonirwin/af56c7bf9d0ac4cfc4fbc3233c6efe81&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;script src=&quot;https://gist.github.com/jasonirwin/af56c7bf9d0ac4cfc4fbc3233c6efe81.js&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;p dir=&quot;ltr&quot;&gt;This is a minor annoyance, at best.&lt;/p&gt;&lt;h2&gt;The Solution&lt;/h2&gt;&lt;p dir=&quot;ltr&quot;&gt;But there is another way! In order to get things working in PyCharm, three steps are necessary:&lt;/p&gt;&lt;h5&gt;1. Install and start Socat&lt;/h5&gt;&lt;p dir=&quot;ltr&quot;&gt;Kudos goes to &lt;a href=&quot;http://kartoza.com/en/blog/how-to-run-a-linux-gui-application-on-osx-using-docker/&quot; target=&quot;_blank&quot;&gt;this blog post&lt;/a&gt;&lt;a href=&quot;http://kartoza.com/en/blog/how-to-run-a-linux-gui-application-on-osx-using-docker/&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt; for the tip and requisite install and setup instructions.&lt;/p&gt;&lt;div class=&quot;embed-wrapper&quot; data-url=&quot;gist.github.com/jasonirwin/fdd8c885a94da749930e27d9c5012007&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;script src=&quot;https://gist.github.com/jasonirwin/fdd8c885a94da749930e27d9c5012007.js&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;h5&gt;2. Make sure XQuartz is installed&lt;/h5&gt;&lt;p dir=&quot;ltr&quot;&gt;This one should be fairly straightforward. Worth upgrading to latest and greatest if steps do not work out of the box...&lt;/p&gt;&lt;h5&gt;3. Edit PyCharm run/debug configuration&lt;/h5&gt;&lt;p dir=&quot;ltr&quot;&gt;PyCharm allows docker flags to be set via it&#39;s run/debug configuration settings. The DISPLAY environment variable needs to be set to the appropriate address (my local IP is 192.168.0.6 but yours likely isn&#39;t...). Ideally I could use the hostname versus IP address but I need to dig some more.&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6LGLY3zuu-XQR7YeaODWgoOfxYf5SmOZCYP1Mzm1kcwGxHX4sfNk5aIU2R8HNHrIkQhkUekbg3NrAQI_SXNBQIeeN2Lq3Eo6ASk8JugMPrfZLF6DkXivQzeeS_JPwjZ4k5OlJZ3n1S6s3/s9999/Edit_Docker_Container_Settings_and_Run_-_install_test.png&quot; width=&quot;1044&quot; style=&quot;max-width: 100%;&quot;&gt;&lt;/div&gt;&lt;h2&gt;The Outcome&lt;/h2&gt;&lt;p dir=&quot;ltr&quot;&gt;If all goes well, when you plot your graph you&#39;ll end up with a nice little XQuartz window displaying said graph&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNnzCV-_WMH-5Pjsfpr9_e-W90KuGr4K7jIsGHLLY8NTwzsrrDucW8_dI-8oF0BqO2l1Y9FpLdkbBK5ndvSw7Zghbb0kIddx7cUc-Igb4JXegXx07ZLnFajdufYBKCjw90KY6Trib0l61O/s9999/Figure_1_and_docker_ui_integration_py_-_tensorflow_-____PycharmProjects_tensorflow_.png&quot; width=&quot;800&quot; style=&quot;max-width: 100%;&quot;&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/3333946732113210254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/3333946732113210254'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2017/05/pycharm-docker-and-matplotlib-on-mac.html' title='Pycharm, Docker and Matplotlib on a Mac'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6LGLY3zuu-XQR7YeaODWgoOfxYf5SmOZCYP1Mzm1kcwGxHX4sfNk5aIU2R8HNHrIkQhkUekbg3NrAQI_SXNBQIeeN2Lq3Eo6ASk8JugMPrfZLF6DkXivQzeeS_JPwjZ4k5OlJZ3n1S6s3/s72-c/Edit_Docker_Container_Settings_and_Run_-_install_test.png" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-5176767895213366621</id><published>2017-04-10T19:27:00.005-04:00</published><updated>2017-05-23T11:05:42.079-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="c#"/><category scheme="http://www.blogger.com/atom/ns#" term="nopCommerce"/><title type='text'>Adding functionality to Nopcommerce&#39;s admin screens without copying and pasting existing views</title><content type='html'>&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;h2&gt;Introduction&lt;/h2&gt;&lt;p dir=&quot;auto&quot;&gt;Nopcommerce&#39;s plugin engine is fairly powerful, providing extension points to expand core functionality. A sizable ecosystem has been built aroudn these extension points. When it works, it adds a lot whole lot of value. However, oftentimes required extension points do not exist, and extending the platform becomes much trickier.&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;In the past I have made modifications directly to the Admin site, but this leads to maintenance pain and I much prefer a plugin approach. In this post, I&#39;ll outline how I developed a trivial plugin, adding a button to the Order List screen, without duplicating any code.&lt;/p&gt;&lt;h2&gt;Background&lt;/h2&gt;&lt;p dir=&quot;ltr&quot;&gt;For a long time administrators on my site have been able to print delivery labels from the Order List and Order Details screens. This requires adding a button to these screens, adding some Javascript to these screens and also adding some controller code. The result looks something like this:&lt;br&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRPLOxkWl2Ka7elh_vzcPE7KGpFxeann1RCV27s210WxzoPG7MwvVecv0zjQHKy1JmPKLhZ8FZCyQ8WY5Z5tNJGZTxRH8sv7hhg1bE3ZmGKRDR3n-gcVNjvVHiXld7NIpgPS0gzsx5pvtq/s9999/Napkin.png&quot; width=&quot;800&quot; style=&quot;max-width: 100%;&quot;&gt;&lt;/div&gt;&lt;p dir=&quot;ltr&quot;&gt;As of right now, Nopcommerce does not have &lt;em&gt;much &lt;/em&gt;support for admin page modifications. There are a limited number of widget zones (allowing custom widgets to be placed on screen) and otherwise very limited UI customizability.&lt;/p&gt;&lt;h2&gt;Standard Suggestion&lt;/h2&gt;&lt;p dir=&quot;ltr&quot;&gt;The most common advice you see in these situations is to create a plugin, create a new view engine and point it to customized versions of the existing cshtml view files. So, in my case, I&#39;d take a copy of Orders\Edit.cshtml and Orders\List.cshtml, modify them with my desired behavior and point my viewengine at the modified files. In theory this is fine, and it works well for small partial views. However, for the two files in question we&#39;re looking at a totalk of 700+ lines of code being duplicated.&lt;/p&gt;&lt;h2&gt;My Solution&lt;/h2&gt;&lt;p dir=&quot;ltr&quot;&gt;The solution in my case is similar to the above, but without the redundancy implied by duplicate code.&lt;/p&gt;&lt;h3&gt;Step 1: Create as Misc plugin&lt;/h3&gt;&lt;p dir=&quot;ltr&quot;&gt;I&#39;ll asume the reader is experienced enough with Nopcommerce to complete this step without help&lt;/p&gt;&lt;h3&gt;Step 2: Create Your View Engine&lt;/h3&gt;&lt;p dir=&quot;ltr&quot;&gt;All we&#39;re doing here is telling the plugin where to find our views.&lt;/p&gt;&lt;div class=&quot;embed-wrapper&quot; data-url=&quot;gist.github.com/jasonirwin/df1febbb3761b6ba142c39232cc5a63e&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;script src=&quot;https://gist.github.com/jasonirwin/df1febbb3761b6ba142c39232cc5a63e.js&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;div class=&quot;custom-html-block&quot;&gt;&lt;div class=&quot;embed-wrapper&quot; data-url=&quot;&quot; style=&quot;clear: both; text-align: center;&quot;&gt;undefined&lt;/div&gt;&lt;/div&gt;&lt;h3&gt;Step 3: Create Your Routeprovider&lt;/h3&gt;&lt;p&gt;This step is pretty straightforward. The goal is to overwrite the routes that the admin page currently uses when listing/editing orders.&lt;br&gt;&lt;/p&gt;&lt;div class=&quot;embed-wrapper&quot; data-url=&quot;gist.github.com/jasonirwin/8d58269afd4e40513fd7d0795eedb3e5&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;script src=&quot;https://gist.github.com/jasonirwin/8d58269afd4e40513fd7d0795eedb3e5.js&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;h3&gt;Step 4: Create your Controller&lt;/h3&gt;&lt;p dir=&quot;ltr&quot;&gt;It doesn&#39;t get much more simple than this&lt;br&gt;&lt;/p&gt;&lt;div class=&quot;embed-wrapper&quot; data-url=&quot;gist.github.com/jasonirwin/1957ba4d7793d5c97b4326a573fe57a7&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;script src=&quot;https://gist.github.com/jasonirwin/1957ba4d7793d5c97b4326a573fe57a7.js&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;h3&gt;Step 5: Create Your Views&lt;/h3&gt;&lt;p dir=&quot;ltr&quot;&gt;So here&#39;s where the magic happens. Rather than duplicating and modifying the original view, we render it as an action in our new view,  adding our button(s) and events via jQuery. Below is an example of my List.cshtml view. Orders.cshtml works the same way.&lt;/p&gt;&lt;div class=&quot;embed-wrapper&quot; data-url=&quot;gist.github.com/jasonirwin/55527de21da1832c3ebae1dce2e82575&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;script src=&quot;https://gist.github.com/jasonirwin/55527de21da1832c3ebae1dce2e82575.js&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;p dir=&quot;ltr&quot;&gt;Assuming future changes by the Nopcommerce team are not too impactful, this plugin should continue to work without requiring any re-coding.&lt;/p&gt;&lt;h2&gt;Potential Drawbacks&lt;/h2&gt;&lt;p dir=&quot;ltr&quot;&gt;This is far from a perfect solution.&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;1. It potentially has a performance impact as view processing will take a little longer due to the nested nature of our action rendering. To me, this is insignifcant. I&#39;m not sure if the difference is noticable and, even if it is, I am more concerned about consumer-facing and search-engine-facing performance than performance that my administrators see.&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;2. You can only do this once per screen. By that I mean, you can&#39;t have multiple plugins ammending the same screen. Remember, we are overriding our route list, replacing the default with our own routes. If we do this more than once, the last in wins...whichever routes are loaded last will determine what is seen by the user.&lt;/p&gt;&lt;h2&gt;In Closing&lt;/h2&gt;&lt;p&gt;Look, this is a hack. Undoubtedly so. At some point in the near future the Nopcomerce team will expand upon the available widget zones in the admin area and/or add further extension points to the admin panel, making all of this unnecessary. When they do, I will most certainly update my code. But, in the short term, this allows additional value to be addded to administrative screens without having to copy and paste a bunch of code.&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/5176767895213366621'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/5176767895213366621'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2017/04/adding-button-to-nopcommerces-admin.html' title='Adding functionality to Nopcommerce&#39;s admin screens without copying and pasting existing views'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRPLOxkWl2Ka7elh_vzcPE7KGpFxeann1RCV27s210WxzoPG7MwvVecv0zjQHKy1JmPKLhZ8FZCyQ8WY5Z5tNJGZTxRH8sv7hhg1bE3ZmGKRDR3n-gcVNjvVHiXld7NIpgPS0gzsx5pvtq/s72-c/Napkin.png" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-9212938325942927509</id><published>2016-11-07T23:27:00.002-05:00</published><updated>2020-07-16T16:02:56.677-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="macOS"/><title type='text'>Siri not working on Mac OS Sierra</title><content type='html'>&lt;p dir=&quot;auto&quot;&gt;I&#39;ve been holding out on rebuilding/reimaging my 2012 Macbook Pro in the hope of picking up a 2016 model. Underwhelmed by this year&#39;s offerings, I went ahead and rebuilt this evening.&lt;/p&gt;&lt;p dir=&quot;auto&quot;&gt;Everything worked well in its vanilla state, but after installing a bunch of dev tools Siri on Mac OS Sierra failed to work. Clicking on either Siri icon and/or holding the prescribed keyboard shortcut did nothing. No error, no nothing. This happened on my prior build. I logged the issue with Apple&#39;s beta feedback team but the conversation was fruitless (despite me sending a video of my actions, the rep asked if I was &lt;em&gt;holding &lt;/em&gt;the shortcut keys or merely &lt;em&gt;pressing &lt;/em&gt;them...) and I temporarily gave up on Siri on Mac OS.&lt;/p&gt;&lt;p dir=&quot;auto&quot;&gt;I&#39;m unable to prove it at this juncture but suspect there is something installed as by Donne Martin&#39;s awesome &lt;a href=&quot;http:// https://github.com/donnemartin/dev-setup&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;dev tools&lt;/a&gt; that somehow conflicts with Siri, but cannot be 100% sure without further testing. I&#39;m including this comment not to disparage his setup scripts (they are the first thing I run any time I rebuild) but to provide a fix in case one of the installed tools is the culprit.&lt;/p&gt;&lt;p dir=&quot;auto&quot;&gt;Fortunately, I ran into a &lt;a href=&quot;http:// https://discussions.apple.com/thread/7679080?start=0&amp;amp;tstart=0 &quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;discussion thread&lt;/a&gt; on Apple&#39;s support forums indicating tha the problem stemmed from the notification center process being disabled. The steps to fix the issue are as follows:&lt;/p&gt;&lt;p dir=&quot;auto&quot;&gt;1. From a terminal:&lt;br&gt;* launchctl load -w /System/Library/LaunchAgents/com.apple.notificationcenterui.plist&lt;br&gt;* killall NotificationCenter&lt;/p&gt;&lt;p dir=&quot;auto&quot;&gt;2. Disable and re-enable siri&lt;/p&gt;&lt;p dir=&quot;auto&quot;&gt;3. Reboot&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/9212938325942927509'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/9212938325942927509'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2016/11/siri-not-working-on-mac-os-sierra.html' title='Siri not working on Mac OS Sierra'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-1796501287979733443</id><published>2016-08-23T17:43:00.000-04:00</published><updated>2016-08-23T17:43:04.399-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="Docker"/><title type='text'>Android Studio -  incompatibility between HAXM hypervisor and VirtualBox 4.3.30+ </title><content type='html'>&lt;p dir=&quot;ltr&quot;&gt;I ran into the following error when launching the simulator in Android Studio on my Macbook Pro today:&lt;br&gt;&lt;/p&gt;&lt;blockquote&gt;emulator: ERROR: Unfortunately, there&#39;s an incompatibility between HAXM hypervisor and VirtualBox 4.3.30+ which doesn&#39;t allow multiple hypervisors to co-exist.  It is being actively worked on; you can find out more about the issue at &lt;a href=&quot;http://b.android.com/197915&quot; target=&quot;_blank&quot;&gt;http://b.android.com/197915&lt;/a&gt; (Android) and &lt;a href=&quot;http://https//www.virtualbox.org/ticket/14294&quot; target=&quot;_blank&quot;&gt;https://www.virtualbox.org/ticket/14294&lt;/a&gt; (VirtualBox)&lt;/blockquote&gt;&lt;p dir=&quot;ltr&quot;&gt;For me the fix was a simple one. I run Docker Beta on the same box. Apparently the hypervisor doesn&#39;t like this. So, in order to run the simulator, all I had to do was exit Docker completely. Not ideal, but a quick fix...&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/1796501287979733443'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/1796501287979733443'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2016/08/android-studio-incompatibility-between.html' title='Android Studio -  incompatibility between HAXM hypervisor and VirtualBox 4.3.30+ '/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-9101797207315060508</id><published>2015-06-30T14:06:00.002-04:00</published><updated>2015-06-30T14:06:42.512-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="git"/><category scheme="http://www.blogger.com/atom/ns#" term="terminal"/><title type='text'>Issues with default git editor</title><content type='html'>&lt;p&gt;Sublime is my editor of choice, but I guess at some point in the past I used Textmate as I recently started running into some Textmate-related issues when pulling code from GitHub. Effectively, when pulling code from GitHub for a merge. I got an error stating that the mate command could not be found.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;$ git pull origin masterFrom github.com:jasonirwin/repo * branch            master     -&amp;gt; FETCH_HEADCan’t find TextMate.app (error -10814)error: /usr/local/bin/mate -w died of signal 6error: There was a problem with the editor &#39;/usr/local/bin/mate -w&#39;.Not committing merge; use &#39;git commit&#39; to complete the merge.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;I assumed the issue was related to my global git config or my bash profile but, after much digging, the issue was in fact caused by a GIT_EDITOR environment variable&lt;/p&gt;&lt;pre&gt;&lt;code&gt;$ echo $GIT_EDITOR/usr/local/bin/mate -w&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;Unsetting this variable got things working again&lt;/p&gt;&lt;pre&gt;&lt;code&gt;unset GIT_EDITOR&lt;/code&gt;&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://irwinj.blogspot.com/feeds/9101797207315060508/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1137761125875994292/9101797207315060508?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/9101797207315060508'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/9101797207315060508'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2015/06/issues-with-default-git-editor_30.html' title='Issues with default git editor'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-5571690831668920403</id><published>2015-06-04T18:54:00.000-04:00</published><updated>2020-07-16T20:31:44.191-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="sublime-text"/><title type='text'>Intel Quick Access breaks Sublime Text Hot Keys</title><content type='html'>&lt;p&gt;CTRL-ALT-UP and CTLR-ALT-DOWN are two hotkeys that I use *all the time*. They’re used in Sublime to execute multi-select on the previous/next line. Mulit-select is one of those features that is difficult to live without once you’ve experienced it and when I set up my new laptop the shortcuts didn’t work correctly.&lt;/p&gt;&lt;p&gt;As it happens those same shortcuts were kidnapped by Intel’s graphic features. What once made me productive was instead hijacked to rotate my display clockwise and counter-clockwise (not something that the majority of people would need a hotkey for, but I digress…)&lt;/p&gt;&lt;p&gt;Anyhow, one would assume that disabling hot keys via Intel’s Graphics Options menu would do the trick, but alas it did not.&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;file:///Users/jirwin/Library/Containers/com.blogo.Blogo/Data/Library/Caches/com.blogo.Blogo/1433452394_full.png&quot; target=&quot;_blank&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitssZIVe6lYA1dLKBFX5dWY0RBG3KpVs_5_mn7T2d6gDOR-V61xgIWCMmt172_LDSe8duw-oveKSef8XJZWtBDoDzlZYZlNfPQ56Yd8Wo_MiT2lrjDv4PZUo6pNEArfkL5DrM-nMffGx3L/&quot;&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;br&gt;Instead it is necessary to override each hotkey via Intel’s HD Graphics Control Panel (thanks a lot, Intel)&lt;br&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxx_OiPiUFpKSMV2G5u_Vc0Uz3zlm65je4lkTi0PvtuQsTsbJ1ftcYDNhRKLkIDPlrO9qyrObWY9thaWLIOPniaiTaRQfxawboSRCKKcsK-peQFrNOUDGOKoiY3YVuXnMJ1WCm8tQzPN7Q/&quot; target=&quot;_blank&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhl13mlqfsmPBxPKDaaLM1AJA4wRYg35dL01aHeehmNgAykFLSYFyQjasiCoB9uAzmbZvI8N6UnAkHXjMtI4tsTSV0FfNzR8e-Ab6fTs2NSz2CwkoGlBtW_stMhir6ba-Qo0j-ahWSo-WMG/&quot;&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;I’m back to running at full speed with keyboard-invoked multi-select in tow. Happiness.&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/5571690831668920403'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/5571690831668920403'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2015/06/intel-quick-access-breaks-sublime-text.html' title='Intel Quick Access breaks Sublime Text Hot Keys'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitssZIVe6lYA1dLKBFX5dWY0RBG3KpVs_5_mn7T2d6gDOR-V61xgIWCMmt172_LDSe8duw-oveKSef8XJZWtBDoDzlZYZlNfPQ56Yd8Wo_MiT2lrjDv4PZUo6pNEArfkL5DrM-nMffGx3L/s72-c" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-5085072633970704157</id><published>2015-06-03T23:57:00.004-04:00</published><updated>2020-07-16T20:31:55.613-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="sysadmin"/><title type='text'>Windows 7 - %windir% is not recognized as an internal or external command</title><content type='html'>&lt;p&gt;I’m in the process of getting acquainted with my new work laptop, a Lenovo W550s. I’ve had the laptop for a couple of weeks now, and very recently, and randomly, strange things started to happen.&lt;/p&gt;&lt;p&gt;I started getting weird error messages when I attempted to perform any kind of system related tasks and couldn’t modify the domain I was connected to.&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2PXbWRHAR_PgrNSgn4gjxU6SXkQp4T-JIhLbyG5JzV07jFt9TXVTNqjh2lsedPKhwTsTjKkkzlOB6cHwoma3iMD-ZF6hE0jfov2YQjbeDcJCcv4IYO-BVOHDMcipoSKwPxpvEPu5rAzPJ/&quot; target=&quot;_blank&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi60snAeYF2dae1YigqnIhljiedDkqxyTiYDmzHaL0qw28Je6NbyTGwvlD2Ilk9LSggj3m7MMIeFssCXAw6bgziSnJtSfLvYpYk4axycWjLowxqZooYPNg0qIF0Nce7n-TpUKXzn9Kqy0SF/&quot;&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;Icons in the start menu (Command Prompt, Paint, Snipping Tool, etc.) changed from meaningful to generic, indicating that something was wrong.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnzkk24PnjFuepp9VxlQZlYgZrEotfHxRdUstqK8lcr8oo-IsfmYLN-v8GKXOkHzHmnpbSw56AFsuFHmEH3dFEqgUBuxEEBKcsC6YBKjJl7y4wfvMTI19dmhbdN7iaGsFyXCXg1omZpzpO/&quot; target=&quot;_blank&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiU1jjdwi5PdjeS2gskLpbuLEUgxzZZbf0lfdROUAWtd2slD9oD76lnhyxTMpBOYn177a9CpJkFnPs9_VtCXxQqLrjpMUI0f0k9O7Gc4iV7xgvOxjRGF6ok6DLbFv5gQDpZ75uA7hKTRvQ7/&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;br&gt;I came very close to reimaing by brand new laptop, until the realization that %windir% was not accessible led me to the hunch that my path was corrupted. It wasn’t corrupted, it was just too long. While my user path was short and sweet, the system path environment variable was full of garbage, weighing in at 2164 characters, full of references to varying pre-installed lenovo and intel software. After some more &lt;a href=&quot;http://superuser.com/questions/527728/cannot-resolve-windir-cannot-modify-path-or-path-being-reset-on-boot&quot; target=&quot;_blank&quot;&gt;digging&lt;/a&gt; it appears that Windows can handle up to 2048 characters but no more. After saving out the old path I removed a bunch of (what I perceive to be) junk, rebooted, and things are back to normal. Phew!&lt;/p&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/5085072633970704157'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/5085072633970704157'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2015/06/windows-7-windir-is-not-recognized-as.html' title='Windows 7 - %windir% is not recognized as an internal or external command'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi60snAeYF2dae1YigqnIhljiedDkqxyTiYDmzHaL0qw28Je6NbyTGwvlD2Ilk9LSggj3m7MMIeFssCXAw6bgziSnJtSfLvYpYk4axycWjLowxqZooYPNg0qIF0Nce7n-TpUKXzn9Kqy0SF/s72-c" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-3085261171107444527</id><published>2014-10-01T00:05:00.001-04:00</published><updated>2014-10-01T00:05:16.152-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="sql"/><title type='text'>TSQL–Calculating Date of Irish/UK Mother’s Day</title><content type='html'>&lt;p&gt;While in the US Mother’s day falls on the second Sunday of May, in western Europe things are a little more complicated. Mother’s Day falls on Mothering Sunday which is the 4th Sunday in Lent. I couldn’t find a T-SQL script to calculate this date, so I rolled my own (with a little help from SO). Let me know if you can have a more succinct method of capturing the same. Here’s the script:&lt;/p&gt;&lt;pre style=&quot;overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; width: 650px; border-bottom: #cecece 1px solid; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; min-height: 40px; border-left: #cecece 1px solid; padding-right: 5px; background-color: #fbfbfb&quot;&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt; &lt;span style=&quot;color: #008000&quot;&gt;/* CALCULATE YEAR &lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt; http://stackoverflow.com/questions/2192533/function-to-return-date-of-easter-for-the-given-year&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt; */&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt;&lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=DECLARE&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;DECLARE&lt;/a&gt;  @&lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=year&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;year&lt;/a&gt; &lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=INT&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;INT&lt;/a&gt;, &lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt;@EpactCalc &lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=INT&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;INT&lt;/a&gt;,  &lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt;@paschal_days_calc &lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=INT&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;INT&lt;/a&gt;, &lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt;@num_of_days_to_sunday &lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=INT&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;INT&lt;/a&gt;, &lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt;@easter_sunday_month &lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=INT&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;INT&lt;/a&gt;, &lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt;@easter_sunday_day &lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=INT&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;INT&lt;/a&gt;,&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt;@easter_sunday &lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=DATETIME&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;DATETIME&lt;/a&gt;,&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt;@start_of_lent &lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=DATETIME&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;DATETIME&lt;/a&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt;&lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=SET&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;SET&lt;/a&gt; @&lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=year&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;year&lt;/a&gt; = 2014&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt;&lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=SET&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;SET&lt;/a&gt; @EpactCalc = (24 + 19 * (@&lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=year&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;year&lt;/a&gt; % 19)) % 30 &lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt;&lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=SET&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;SET&lt;/a&gt; @paschal_days_calc = @EpactCalc - (@EpactCalc / 28) &lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt;&lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=SET&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;SET&lt;/a&gt; @num_of_days_to_sunday = @paschal_days_calc - ( &lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt;	(@&lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=year&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;year&lt;/a&gt; + @&lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=year&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;year&lt;/a&gt; / 4 + @paschal_days_calc - 13) % 7 &lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt;) &lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt;&lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=SET&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;SET&lt;/a&gt; @easter_sunday_month = 3 + (@num_of_days_to_sunday + 40) / 44 &lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt;&lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=SET&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;SET&lt;/a&gt; @easter_sunday_day = @num_of_days_to_sunday + 28 - ( &lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt;	31 * (@easter_sunday_month / 4) &lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt;) &lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt; &lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt;&lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=SELECT&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;SELECT&lt;/a&gt; @easter_sunday = &lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=CONVERT&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;CONVERT&lt;/a&gt;      (  &lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=SMALLDATETIME&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;SMALLDATETIME&lt;/a&gt;, &lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt;            RTRIM(@&lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=year&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;year&lt;/a&gt;)  &lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt;    + &lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=RIGHT&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;RIGHT&lt;/a&gt;(&#39;&lt;span style=&quot;color: #8b0000&quot;&gt;0&lt;/span&gt;&#39;+RTRIM(@easter_sunday_month), 2)  &lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt;    + &lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=RIGHT&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;RIGHT&lt;/a&gt;(&#39;&lt;span style=&quot;color: #8b0000&quot;&gt;0&lt;/span&gt;&#39;+RTRIM(@easter_sunday_day), 2)  &lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt;&lt;span style=&quot;color: #008000&quot;&gt;/* CALCULATE START OF LENT */&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt;&lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=SET&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;SET&lt;/a&gt; @start_of_lent = DATEADD(DD,-46,@easter_sunday)&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt;&lt;span style=&quot;color: #008000&quot;&gt;/* CALCULATE MOTHERING SUNDAY */&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt;	&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt;&lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=set&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;set&lt;/a&gt; datefirst 7 &lt;span style=&quot;color: #008000&quot;&gt;-- Sunday&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt;&lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=DECLARE&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;DECLARE&lt;/a&gt; @days_to_first_sunday &lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=INT&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;INT&lt;/a&gt;, @days_to_fourth_sunday &lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=INT&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;INT&lt;/a&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt;&lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=SET&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;SET&lt;/a&gt; @days_to_first_sunday = 7 - datepart(dw, @start_of_lent)&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt;&lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=SET&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;SET&lt;/a&gt; @days_to_fourth_sunday = 28 - @days_to_first_sunday&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt;&lt;a style=&quot;color: #0000ff&quot; href=&quot;http://search.microsoft.com/default.asp?so=RECCNT&amp;amp;siteid=us%2Fdev&amp;amp;p=1&amp;amp;nq=NEW&amp;amp;qu=select&amp;amp;IntlSearch=&amp;amp;boolean=PHRASE&amp;amp;ig=01&amp;amp;i=09&amp;amp;i=99&quot;&gt;select&lt;/a&gt; DATEADD(DD,  @days_to_fourth_sunday, @start_of_lent)&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #fbfbfb&quot;&gt;&lt;/pre&gt;&lt;pre style=&quot;font-size: 12px; font-family: consolas,&#39;Courier New&#39;,courier,monospace; width: 100%; margin: 0em; background-color: #ffffff&quot;&gt;&lt;/pre&gt;&lt;/pre&gt;  </content><link rel='replies' type='application/atom+xml' href='http://irwinj.blogspot.com/feeds/3085261171107444527/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1137761125875994292/3085261171107444527?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/3085261171107444527'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/3085261171107444527'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2014/10/tsqlcalculating-date-of-irishuk-mothers.html' title='TSQL–Calculating Date of Irish/UK Mother’s Day'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-6436211794346655973</id><published>2014-04-03T16:08:00.001-04:00</published><updated>2020-07-16T20:32:31.113-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="books"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="Review"/><title type='text'>Review: You Don&amp;#39;t Know JS: Scope and Closures</title><content type='html'>&lt;p&gt;&lt;strong&gt;Disclosure: I received a review copy of this title from O’Reilly&lt;/strong&gt;&lt;/p&gt;&lt;a href=&quot;http://www.kqzyfj.com/click-7228112-11260198?url=http%3A%2F%2Fshop.oreilly.com%2Fproduct%2F0636920026327.do%3Fcmp%3Daf-prog-books-videos-product_cj_9781449335588_%2525zp&amp;amp;cjsku=0636920026327&quot; target=&quot;_top&quot;&gt;&lt;img border=&quot;0&quot; alt=&quot;You Don&#39;t Know JS: Scope and Closures&quot; src=&quot;http://akamaicovers.oreilly.com/images/0636920026327/cat.gif&quot;&gt;&lt;/a&gt;&lt;img border=&quot;0&quot; src=&quot;http://www.awltovhc.com/image-7228112-11260198&quot; width=&quot;1&quot; height=&quot;1&quot;&gt;  &lt;p&gt;I have three main criteria when purchasing educational content – how much knowledge I can garner (bonus points for anything that I can use in the real world), the time investment required on my part and cost. &lt;em&gt;You Don’t Know JS: Scope and Closures &lt;/em&gt;does well on all 3 fronts. The book is short and sweet, inexpensive (the eBook was $8 at time of writing) and informative. It weighs in at 78 pages (including appendices) and is the first in the multi-part &lt;em&gt;You Don’t Know JS &lt;/em&gt;series, focusing exclusively on a small subset of the Javascript language – scopes and closures. This exclusive focus enables the author, Kyle Simpson, to cut through the fluff that usually forms a good portion of more general titles and deep dive into this narrow (but important) topic. &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;The book is detailed and doesn’t veer away from tricky concepts. At the same time is a very quick and pleasant read – one could easily read it cover-to-cover (including the appendices which were quite interesting) in a single sitting. This might be off-putting to some, but I learned a few new concepts and definitely expanded/reinforced my understanding of existing concepts. As such, in my mind the return on investment is quite high. The title is quite accessible and contains code examples to support each concept. I’d recommend it to developers of any level and think it would be a great foundation for beginners, helping them to avoid frustrating pitfalls caused by misunderstanding of how scope works. It is just as relevant to intermediate/advanced developers – I can only imagine the number of veteran JavaScript developers who don’t fully understand why scope and closures work the way they do. &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;I’m a big fan of this title and look forward to the next installment in the &lt;em&gt;You Don’t Know JS&lt;/em&gt; series.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://irwinj.blogspot.com/feeds/6436211794346655973/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1137761125875994292/6436211794346655973?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/6436211794346655973'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/6436211794346655973'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2014/04/review-you-don-know-js-scope-and.html' title='Review: You Don&amp;#39;t Know JS: Scope and Closures'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-4948523957261264219</id><published>2014-03-24T22:32:00.001-04:00</published><updated>2020-07-16T20:32:13.819-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Team Foundation Server"/><category scheme="http://www.blogger.com/atom/ns#" term="Version Control"/><title type='text'>Team Foundation Server – TF30162 - Task &amp;quot;WITs&amp;quot; from Group &amp;quot;WorkItemTracking&amp;quot; failed</title><content type='html'>&lt;p&gt;I ran into the following error this evening when attempting to create a “new” (more to follow…) Team Project via Visual Studio 2013:  &lt;p&gt;&lt;strong&gt;Event Description: TF30162: Task &quot;WITs&quot; from Group &quot;WorkItemTracking&quot; failed&lt;u&gt;&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;While it looked at first like an issue related to work item tracking templates, the stacktrace in the project creation log (located in your %temp% folder) provided some insight:  &lt;p align=&quot;left&quot;&gt;&lt;strong&gt;Event Description: TF30162: Task &quot;WITs&quot; from Group &quot;WorkItemTracking&quot; failed&lt;u&gt;&lt;/u&gt;&lt;u&gt;&lt;/u&gt; &lt;/strong&gt; &lt;p align=&quot;left&quot;&gt;&lt;strong&gt;Exception Type: Microsoft.TeamFoundation.Client.PcwException&lt;u&gt;&lt;/u&gt;&lt;u&gt;&lt;/u&gt; &lt;/strong&gt; &lt;p align=&quot;left&quot;&gt;&lt;strong&gt;Exception Message: TF24016: Cannot find team project ‘TestProject’.&lt;u&gt;&lt;/u&gt;&lt;u&gt;&lt;/u&gt; &lt;/strong&gt; &lt;p align=&quot;left&quot;&gt;&lt;strong&gt;Stack Trace:&lt;u&gt;&lt;/u&gt;&lt;u&gt;&lt;/u&gt; &lt;/strong&gt; &lt;p align=&quot;left&quot;&gt;&lt;strong&gt;at Microsoft.VisualStudio.TeamFoundation.WorkItemTracking.WitPcwPlugin.PcwPluginComponentCreator.Execute(ProjectCreationContext ctxt, XmlNode taskXml)&lt;u&gt;&lt;/u&gt;&lt;u&gt;&lt;/u&gt; &lt;/strong&gt; &lt;p align=&quot;left&quot;&gt;&lt;strong&gt;at Microsoft.VisualStudio.TeamFoundation.PCW.ProjectCreationEngine.TaskExecutor.PerformTask(IProjectComponentCreator componentCreator, ProjectCreationContext context, XmlNode taskXml)&lt;u&gt;&lt;/u&gt;&lt;u&gt;&lt;/u&gt; &lt;/strong&gt; &lt;p align=&quot;left&quot;&gt;&lt;strong&gt;at Microsoft.VisualStudio.TeamFoundation.PCW.ProjectCreationEngine.RunTask(Object taskObj)&lt;/strong&gt; &lt;p&gt;A noteworthy piece of background is that I was actually &lt;em&gt;re-creating &lt;/em&gt;a deleted project on our test TFS box. Essentially we’re running migrations which requires iterative creation, testing and deletion of projects. So the project I was trying to create (fictitiously called &lt;em&gt;TestProject &lt;/em&gt;above) used to exist on the box, but was recently deleted. I was creating a project with the same name. Apparently project details are being cached locally (it stands to reason), so once I deleted the TFS project on our test box and tried to recreate it from Visual Studio, Visual Studio got confused.&lt;u&gt;&lt;/u&gt;&lt;u&gt;&lt;/u&gt;&lt;/p&gt; &lt;p&gt;&lt;u&gt;&lt;/u&gt;&lt;u&gt;&lt;/u&gt; &lt;p&gt;&lt;b&gt;Fix&lt;u&gt;&lt;/u&gt;&lt;u&gt;&lt;/u&gt;&lt;/b&gt;  &lt;ul&gt; &lt;li&gt;Close Visual Studio&lt;u&gt;&lt;/u&gt;&lt;u&gt;&lt;/u&gt;  &lt;li&gt;Delete everything from the cache folder. On Windows 7:  &lt;ul&gt; &lt;li&gt;C:\Users\{user}\AppData\Local\Microsoft\Team Foundation\{version}\Cache&lt;u&gt;&lt;/u&gt;&lt;u&gt;&lt;/u&gt;&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;Rerun project creation&lt;/li&gt;&lt;/ul&gt;  </content><link rel='replies' type='application/atom+xml' href='http://irwinj.blogspot.com/feeds/4948523957261264219/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1137761125875994292/4948523957261264219?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/4948523957261264219'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/4948523957261264219'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2014/03/team-foundation-server-tf30162-task.html' title='Team Foundation Server – TF30162 - Task &amp;quot;WITs&amp;quot; from Group &amp;quot;WorkItemTracking&amp;quot; failed'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-4560019357145031927</id><published>2014-03-21T23:54:00.001-04:00</published><updated>2020-07-16T20:32:24.540-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="books"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="Review"/><title type='text'>Review: Douglas Crockford JavaScript Master Class</title><content type='html'>&lt;p&gt;&lt;strong&gt;Disclosure: I received a review copy of this title from O’Reilly&lt;/strong&gt; &lt;p&gt;&lt;img alt=&quot;Douglas Crockford JavaScript Master Class&quot; src=&quot;http://akamaicovers.oreilly.com/images/9780596809621/s.gif&quot;&gt;&lt;strong&gt;&lt;/strong&gt; &lt;p&gt;&amp;nbsp; &lt;p&gt;The Douglas Crockford JavaScript Master Class is a 14 part video series (running almost 6 hours in length) recorded in 2009. In the series, Mr. Crockford, long-time JavaScript developer/speaker/writer, the creator of JSLint and commonly recognized as the father of JSON, provides a deep-dive into the JavaScript language. Along the way he often leverages his insight to provide relevant historical references, explaining how language features evolved, where W3C members took divergent routes and why so often we end up writing different code for different browsers. While it’s a matter of taste, and some people prefer only technical content, I found the historical annotations to be deeply interesting and beneficial when arguing for or against the use of a specific language feature or construct. &lt;p&gt;The series begins with an overview of the language, before moving onto inheritance (pseudoclassical, prototypal and functional), the DOM, security, JSON and other and other higher level mechanisms.The technical content is excellent and I probably know more about the JavaScript language (warts and all) than I ever wanted to. Mr. Crockford is clearly an expert in his field and, unlike many other authors on the subject, he is often prescriptive in his approach. Throughout the series he is explicit in his guidance, telling the viewer which language constructs should be preferred and which should be completely avoided. In an industry where “it depends” is a common refrain, I found this very refreshing. It is also very beneficial to hear definitive instruction for a change and he even identified a few bad habits that I’ve picked up over the years that need attention. While the content could easily have been dry and boring the speaker possesses a sardonic wit, dishing out admonishments when required. To his credit, he never falls into the trap of becoming a Microsoft-basher. He’s pretty even-handed throughout and doesn’t pull punches when talking about any browser vendor, language designer, W3C or even himself. &lt;p&gt;There isn’t much negative I can say about this video set. The videos were recorded in 2009, therefore some content is a little outdated. That said, the videos focus on core language concepts, not breakthrough technologies so, for the most part, they are no less relevant today than 5 years ago. Because the videos aren’t as recent the quality of video is not as crisp or clear as more recent O’Reilly offerings. You won’t miss anything, but the difference is noticeable if you’re a fan of O’Reilly’s products. &lt;p&gt;I’d recommend this series to just about anyone developing web-based applications. Novices will learn quite a bit about JavaScript fundamentals and pitfalls to avoid throughout their careers (the more I think about it, the better a foundation this course seems). More advanced developers will undoubtedly learn some new tricks or, more likely, fix some bad habits. &lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://irwinj.blogspot.com/feeds/4560019357145031927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1137761125875994292/4560019357145031927?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/4560019357145031927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/4560019357145031927'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2014/03/review-douglas-crockford-javascript.html' title='Review: Douglas Crockford JavaScript Master Class'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-4978711818289712074</id><published>2013-10-21T23:53:00.001-04:00</published><updated>2013-10-21T23:53:08.574-04:00</updated><title type='text'>PredictionIO - undefined method `configure&#39; for Vagrant:Module</title><content type='html'>&lt;p&gt;I’m dying to play with &lt;a href=&quot;http://prediction.io/&quot;&gt;PredictionIO&lt;/a&gt; and it looks like the easiest way to get up and running is using the wonderful vagrant to spin up a preconfigured VirtualBox VM. Unfortunately, I got the following error message when attempting to do so in Windows or Mac OSX.  &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;C:/PredictionIO-Vagrant/Vagrantfile:10:in `&amp;lt;top (required)&amp;gt;&#39;: undefined method `configure&#39; for Vagrant:Module (NoMethodE
rror)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It turns out that that Vagrant no longer supports RubyGems as an installation method (a whole &lt;a href=&quot;http://mitchellh.com/abandoning-rubygems&quot;&gt;blog post&lt;/a&gt; was dedicated to the reasoning) and I had used &lt;em&gt;gem install&lt;/em&gt; to get her up and running. So, remove Vagrant if you’ve already installed it and download the installer from &lt;a href=&quot;http://www.vagrantup.com/&quot;&gt;http://www.vagrantup.com/&lt;/a&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://irwinj.blogspot.com/feeds/4978711818289712074/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1137761125875994292/4978711818289712074?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/4978711818289712074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/4978711818289712074'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2013/10/predictionio-undefined-method-configure.html' title='PredictionIO - undefined method `configure&#39; for Vagrant:Module'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-1019288801549620699</id><published>2013-09-22T13:12:00.001-04:00</published><updated>2013-09-22T13:12:14.029-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="c#"/><category scheme="http://www.blogger.com/atom/ns#" term="visual-studio"/><title type='text'>C# woes - &quot;call is ambiguous between the following methods&quot; - identical methods</title><content type='html'>&lt;p&gt;Oh the irony. An ambiguous message about ambiguous methods. As you&#39;ll notice, the conflicting method names are the exact same:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Error 48  The call is ambiguous between the following methods or
  properties:
  &#39;Ecommerce.Core.Helpers.DateTimeHelpers.Verify(System.DateTime?)&#39; and
  &#39;Ecommerce.Core.Helpers.DateTimeHelpers.Verify(System.DateTime?)&#39; C:\Ecommerce\Ecommerce.Core\Helpers\DateTimeHelpers.cs  9   24  Ecommerce.Core&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The issue here was that my Ecommerce.Core project was referencing itself. Yes, you heard that right. At first I assumed I was responsible but upon closer inspection it looks like Visual Studio or a Visual Studio plugin was responsible for automatically adding the reference...&lt;/p&gt;

&lt;p&gt;I removed the reference and, voila, the error (actually hundreds of errors for various methods) disappeared. I don&#39;t mean this in a cynical way, but I would legitimately like to know if there are any valid use cases for a project referencing itself.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://irwinj.blogspot.com/feeds/1019288801549620699/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1137761125875994292/1019288801549620699?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/1019288801549620699'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/1019288801549620699'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2013/09/c-woes-call-is-ambiguous-between.html' title='C# woes - &quot;call is ambiguous between the following methods&quot; - identical methods'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-1727466877508798770</id><published>2013-09-03T13:13:00.001-04:00</published><updated>2013-09-03T13:13:20.220-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="clisp"/><category scheme="http://www.blogger.com/atom/ns#" term="sublime-text"/><title type='text'>Sublime Text 3, SublimeREPL and CLISP</title><content type='html'>&lt;p&gt;You may get the following file not found error when attempting to combine CLISP (I installed via MacPorts, but I&#39;m guessing this works the same for homebrew...) with SublimeREPL in Sublime Text 3 on OSX.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;FileNotFoundError(2, &quot;No such file or directory: &#39;clisp&#39;&quot;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Essentially, you need to tell SublimeREPL where to find the CLISP binaries. Simply add the following line to your SublimeREPL user configuration file (Sublime Text-&amp;gt;Preferences-&amp;gt;Package Settings-&amp;gt;SublimeREPL-&amp;gt;Settings - User)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&quot;default_extend_env&quot;: {&quot;PATH&quot;: &quot;{PATH}:/opt/local/bin&quot;}
&lt;/code&gt;&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://irwinj.blogspot.com/feeds/1727466877508798770/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1137761125875994292/1727466877508798770?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/1727466877508798770'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/1727466877508798770'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2013/09/sublime-text-3-sublimerepl-and-clisp.html' title='Sublime Text 3, SublimeREPL and CLISP'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-3223674309063795903</id><published>2013-08-11T02:27:00.001-04:00</published><updated>2020-07-16T20:33:13.215-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="books"/><category scheme="http://www.blogger.com/atom/ns#" term="clojure"/><category scheme="http://www.blogger.com/atom/ns#" term="functional-programming"/><category scheme="http://www.blogger.com/atom/ns#" term="gradle"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="Review"/><category scheme="http://www.blogger.com/atom/ns#" term="scala"/><title type='text'>Review: Functional Thinking</title><content type='html'>&lt;p&gt;&lt;strong&gt;Disclosure: I received a review copy of this title from O’Reilly&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.kqzyfj.com/click-7228112-11260198?url=http%3A%2F%2Fshop.oreilly.com%2Fproduct%2F0636920030393.do%3Fcmp%3Daf-npa-video-product_cj_0636920030416_%25zp&amp;cjsku=0636920030393&quot; target=&quot;_top&quot;&gt;&lt;img src=&quot;http://akamaicovers.oreilly.com/images/0636920030393/cat.gif&quot; border=&quot;0&quot; alt=&quot;Functional Thinking&quot;/&gt;&lt;/a&gt;&lt;img src=&quot;http://www.awltovhc.com/image-7228112-11260198&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; style=&quot;padding:0px; border-style:none&quot; /&gt;
&lt;/p&gt;

&lt;p&gt;Functional Thinking by Neil Ford of Thoughtworks is another great series in the O&#39;Reilly video library. As I&#39;ve come to expect from O&#39;Reilly videos, the production quality, picture and audio are excellent. The content is also pretty great. The key to this title is in the name - Functional &lt;em&gt;Thinking&lt;/em&gt;. The aim of these videos isn&#39;t to teach a specific functional programming language, and you won&#39;t be fluent in a specific language as a result of watching them. Instead, the focus is on thinking a little bit differently. As Mr. Ford emphasizes: learning functional programming isn&#39;t comparable to learning a new language - it is a new way of thinking. This is a very important distinction and one i&#39;m glad that the author made.&lt;/p&gt;

&lt;p&gt;I&#39;d recommend this title for seasoned developers who are new to the functional programming world. The videos seem intended for use by those already schooled in object-oriented paradigm and detail numerous mechanisms employed by functional languages, why they are beneficial and how such mechanisms are permeating into existing mainstream (traditionally object-oriented) languages. The series does not focus on one specific language (though as suggested by the course title Java is often used as the base OOP language for comparison purposes) with Mr. Ford leveraging examples from Gradle, Clojure and Scala to illustrate his points. A little Java knowledge won&#39;t go astray - but developers with experience in any OOP language should be able to follow along.&lt;/p&gt;

&lt;p&gt;The author clearly has a deep understanding of content and is very engaging throughout (I was also impressed at his ability to answer random/difficult questions from the audience). He makes the content extremely accessible and does a great job of explaining constructs available in functional programming that don&#39;t necessarily exist in other languages (first class functions, closures, etc.). To do so, he provides simple examples in OOP languages and iteratively refactors them into their functional counterparts. Along the way he explains the history and the thought process behind the designs of the constructs being discussed. &lt;/p&gt;

&lt;p&gt;I learned a lot from this video series, not only about the benefits of specific functional constructs, but also issues with some OOP concepts that I have for a long time taken for granted (for instance, coupling introduced by polymorphism and limitations to dispatch mechanisms). You won&#39;t be able to write your first program using a functional programming language as a result of watching this course. However, you may just think differently about how you code. I highly recommend this series.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://irwinj.blogspot.com/feeds/3223674309063795903/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1137761125875994292/3223674309063795903?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/3223674309063795903'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/3223674309063795903'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2013/08/review-functional-thinking.html' title='Review: Functional Thinking'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-8246482926040615223</id><published>2013-06-23T21:44:00.001-04:00</published><updated>2014-04-03T14:54:24.015-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET MVC"/><category scheme="http://www.blogger.com/atom/ns#" term="c#"/><category scheme="http://www.blogger.com/atom/ns#" term="security"/><title type='text'>Responsible use of the ASP.NET MVC AntiForgeryToken</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;link href=&quot;http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot;&gt;&lt;/link&gt;
&lt;script language=&quot;javascript&quot; src=&quot;http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
&lt;script language=&quot;javascript&quot; src=&quot;http://google-code-prettify.googlecode.com/svn/trunk/src/lang-css.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
    document.addEventListener(&#39;DOMContentLoaded&#39;,function() {
        prettyPrint();
    });
&lt;/script&gt;
&lt;br /&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
The use of anti-forgery tokens is a necessary safeguard against cross-site request forgery attacks. The ASP.NET MVC framework provides easy-to-use security mechanisms right out of the box, but unfortunately these are opt-in rather than opt-out and are easy to miss/forget. For a non-trivial website it is difficult to guarantee tokens are supplied and checked in all form submissions and AJAX posts. This is how I do it.&lt;br /&gt;
&lt;strong&gt;Note: Web security is a tricky business and I do not consider myself a security expert. Use the information in this post at your own risk.&lt;/strong&gt;&lt;br /&gt;
&lt;h4 id=&quot;1-use-the-validatejsonantiforgerytoken-attribute-for-ajax-calls&quot;&gt;
1. Use the ValidateJsonAntiForgeryToken attribute for AJAX calls&lt;/h4&gt;
There&#39;s a &lt;a href=&quot;http://johan.driessen.se/posts/Updated-Anti-XSRF-Validation-for-ASP.NET-MVC-4-RC&quot;&gt;nice post by Johan Driessen&lt;/a&gt; on anti-XSRF validation with newer versions of the .NET framework. I use Johan&#39;s ValidateJsonAntiForgeryToken attribute to great effect. In summary, Johan&#39;s attribute should be applied to actions invoked via AJAX calls. Check out his blog post - it explains everything in detail.&lt;br /&gt;
&lt;h4 id=&quot;2-ensure-all-ajax-posts-contain-a-verification-token&quot;&gt;
2. Ensure all AJAX posts contain a verification token&lt;/h4&gt;
In my root layout file (master page) I use the following code to set expectations for jQuery AJAX calls. Prior to executing a call, the request verification token is read from the current page (&lt;strong&gt;Note&lt;/strong&gt;: a Html.AntiForgeryToken call needs to be in place in every page which will utilize ajax posts) and passed into the request header. This saves me from needing to specify a token every time I create an AJAX call. (This can easily be modified to only send the token for desired HTTP verbs)&lt;br /&gt;
&lt;div class=&quot;gistLoad&quot; data-id=&quot;9960498&quot;&gt;
Loading ....&lt;/div&gt;
&lt;h4 id=&quot;3-ensure-all-post-methods-have-validation-attributes-applied&quot;&gt;
3. Ensure all POST methods have validation attributes applied&lt;/h4&gt;
It&#39;s very easy to forget to apply the &lt;strong&gt;ValidateAntiForgeryToken&lt;/strong&gt; attribute when developing new actions. I have a little unit test that I run to ensure that &lt;em&gt;all&lt;/em&gt; post methods have either &lt;strong&gt;ValidateAntiForgeryToken&lt;/strong&gt; or &lt;strong&gt;ValidateJsonAntiForgeryToken&lt;/strong&gt; applied. The test fails and prints a list of offender actions when appropriate. This is a lifesaver when, inevitably, I&#39;m developing some new functionality in a rush and haven&#39;t given security its appropriate consideration (hopefully this is a rarity).&lt;br /&gt;
&lt;div class=&quot;gistLoad&quot; data-id=&quot;9960378&quot;&gt;
Loading ....&lt;/div&gt;
Hopefully this saves somebody some time. Let me know if there are any considerations that I have missed, or if you know of a more elegant method of achieving the same!&lt;/div&gt;
&lt;/div&gt;
&lt;script src=&quot;https://raw.github.com/moski/gist-Blogger/master/public/gistLoader.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;

&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://irwinj.blogspot.com/feeds/8246482926040615223/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1137761125875994292/8246482926040615223?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/8246482926040615223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/8246482926040615223'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2013/06/responsible-use-of-aspnet-mvc_23.html' title='Responsible use of the ASP.NET MVC AntiForgeryToken'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-7128656213160297345</id><published>2013-06-21T19:03:00.001-04:00</published><updated>2013-06-23T21:53:18.006-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="typemock"/><category scheme="http://www.blogger.com/atom/ns#" term="unit-testing"/><title type='text'>Mocking NHibernate with Typemock Isolator is Awesome</title><content type='html'>&lt;link href=&quot;http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&gt;
&lt;script type=&quot;text/javascript&quot; language=&quot;javascript&quot; src=&quot;http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; language=&quot;javascript&quot; src=&quot;http://google-code-prettify.googlecode.com/svn/trunk/src/lang-css.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
    document.addEventListener(&#39;DOMContentLoaded&#39;,function() {
        prettyPrint();
    });
&lt;/script&gt;
&lt;p&gt;&lt;strong&gt;Note: I am not affiliated in any way with Typemock&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Unit testing methods that contain NHibernate calls is notoriously difficult. In fact, a common suggestion is to give up and use an in memory database instead. This is fine (I&#39;ve personally tried it on multiple occasions), and it works I suppose, but has always felt more like integration testing than unit testing (what happened to &quot;no external dependencies&quot;?..perhaps I&#39;m a purist) and undoubtedly slows down the test suite - especially in all but non trivial cases where reference data needs to be loaded.&lt;/p&gt;

&lt;p&gt;I&#39;m a novice Isolator user and messed around with the RecordExpectations syntax for a little bit before realizing just how simple Isolator makes things. Once you understand the warnings that Typemock puts out there, things get really easy. &lt;em&gt;Really easy&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First Attempt&lt;/strong&gt; &lt;br&gt;
Let&#39;s say I wanted to fake the count of the products currently mapped to a specific category on my website. Normally the chained nature of NHibernate queryover calls requires mocking a &lt;strong&gt;LOT&lt;/strong&gt; of stuff. &lt;/p&gt;

&lt;p&gt;When you attempt to use Isolator&#39;s Isolate.WhenCalled method like in the case below, you may get an error message. Don&#39;t get despondent!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;/em&gt;      &lt;/p&gt;

&lt;pre class=&quot;prettyprint lang-cs&quot; &gt;&lt;code class=&quot;prettyprint lang-cs&quot; &gt; var session = Isolate.GetFake&amp;lt;ISession&amp;gt;(controller);

 Isolate.WhenCalled(()=&amp;gt;session.QueryOver&amp;lt;CategoryProduct&amp;gt;()
        .Where(x =&amp;gt; x.Category == category &amp;amp;&amp;amp; x.IsEnabled == true)
        .RowCount())
        .WillReturn(1);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Error Message&lt;/strong&gt;&lt;/em&gt; &lt;br&gt;
There is nothing better (or more rare) than getting a useful error message. In fairness, Typemock provides just that - not only highlighting the issue, but suggesting a fix too. Wonderful!&lt;/p&gt;

&lt;pre class=&quot;prettyprint lang-cs&quot; &gt;&lt;code class=&quot;prettyprint lang-cs&quot; &gt;Test &#39;mytest&#39; failed:
    TypeMock.ArrangeActAssert.NestedCallException : 
*** WhenCalled does not support using a method call as an argument.
-   To fix this pass null instead of Expression.Lambda()

***
* Example - this would work:
-   MyObj argument = Something.Other().GetStuff();
-   Isolate.WhenCalled(() =&amp;gt; ObjUnderTest.MethodUnderTest(argument))...;
***
* Example - this would not work:
-   Isolate.WhenCalled(() =&amp;gt; ObjUnderTest.MethodUnderTest(Something.Other().GetStuff()))...;
    at cx.a()
    at g4.a()
    at bh.a(Boolean A_0)
    at dl.b(Boolean A_0)
    at ij.b(Boolean A_0)
    at ij.a(Object A_0, Boolean A_1, Func`1 A_2, Action A_3, Action A_4, Action A_5, Boolean A_6)
    at ij.e(Object A_0)
    at TypeMock.ArrangeActAssert.ExpectationEngine`1.a(TResult A_0)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Updated Syntax&lt;/strong&gt; &lt;br&gt;
The issue here is that in the chained &lt;em&gt;Where&lt;/em&gt; call I am using a lambda expression to filter my query. Since Typemock doesn&#39;t support methods being sent as arguments (and my lambda here is nothing more than an inline anonymous function) I need to break the lambda out into a standalone expression (Resharper is your friend).&lt;/p&gt;

&lt;p&gt;What I end up with is the following terse (certainly compared to the alternative) syntax to mock a chained NHibernate call.&lt;/p&gt;

&lt;pre class=&quot;prettyprint lang-cs&quot; &gt;&lt;code class=&quot;prettyprint lang-cs&quot; &gt;Expression&amp;lt;Func&amp;lt;CategoryProduct, bool&amp;gt;&amp;gt; expression = x =&amp;gt; x =&amp;gt; x.Category == category &amp;amp;&amp;amp; x.IsEnabled == true;

Isolate.WhenCalled(()=&amp;gt;session.QueryOver&amp;lt;CategoryProduct&amp;gt;().Where(expression).RowCount()).WillReturn(1);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;While Isolator is pretty pricey, it&#39;s this kind of power that separates it from the pack. I defy anyone to show me a better/easier way to do this.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://irwinj.blogspot.com/feeds/7128656213160297345/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1137761125875994292/7128656213160297345?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/7128656213160297345'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/7128656213160297345'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2013/06/mocking-nhibernate-with-typemock.html' title='Mocking NHibernate with Typemock Isolator is Awesome'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1137761125875994292.post-678257779614880136</id><published>2013-05-06T17:58:00.001-04:00</published><updated>2013-08-13T14:57:18.825-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Review"/><category scheme="http://www.blogger.com/atom/ns#" term="ruby"/><title type='text'>Review: Computer Science Programming Basics in Ruby</title><content type='html'>&lt;p&gt;&lt;strong&gt;Disclosure: I received a review copy of this title from O’Reilly&lt;/strong&gt;&lt;/p&gt;

&lt;a href=&quot;http://www.dpbolvw.net/click-7228112-11260198?url=http%3A%2F%2Fshop.oreilly.com%2Fproduct%2F0636920028192.do%3Fcmp%3Daf-prog-book-product_cj_9781449355968_%25zp&amp;cjsku=9781449355968&quot; target=&quot;_top&quot;&gt;&lt;img src=&quot;http://akamaicovers.oreilly.com/images/0636920028192/cat.gif&quot; border=&quot;0&quot; alt=&quot;Computer Science Programming Basics in Ruby&quot;/&gt;&lt;/a&gt;&lt;img src=&quot;http://www.ftjcfx.com/image-7228112-11260198&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; style=&quot;padding:0px; border-style:none&quot;/&gt;

 &lt;p&gt;Computer Science, more than any other field I know of, poses a difficult balance between theory and practice. It is difficult to understand the theory without having some practical knowledge. It is difficult to teach the practical aspects of Computer Science without a solid foundation in theory. I&#39;m years into my development career and still discovering the true value of CS concepts I was able to mentally retain long enough to sit an exam. &lt;p&gt;I wanted to review this book for 3 reasons: &lt;p&gt;1. I am on a mini ruby kick at the moment and am reading/viewing everything I can get my hands on &lt;p&gt;2. I wanted to see how Computer Science was taught from a non traditional language (C/Java) standpoint &lt;p&gt;3. I wanted to fill any holes in my knowledge and/or revisit what I&#39;ve already forgotten &lt;p&gt;The book is a short read, at 188 pages, yet does an admirable job of providing a basic overview of both the core Ruby programming language and some fundamental computer science concepts. I was particularly impressed with the overviews of some major sorting/searching algorithms and measurement of complexity (Big O Notation). The authors made these topics very accessible which is an impressive feat. &lt;p&gt;I was admittedly a little disappointed that Ruby was used only because it is a popular modern programming language (as was stated in the book) and not because it provided any deep or novel insights into Computer Science concepts. I don&#39;t really know what I was expecting but I think there is an opportunity for a book to be written that delves down into computer science concepts using modern languages – taking the above examples: which Ruby algorithms use binary search, what do they look like, etc.). Clearly that wasn’t the intent of this particular book, and I’ll take the blame for assuming it was, but the title would have been slightly less desirable to me had I known in advance.&amp;nbsp; &lt;p&gt;As the book’s title indicates, it focuses on basic concepts so it is probably not meant for seasoned developers. All in all this was an interesting title and I&#39;d recommend it for anyone beginning a Computer Science course or thinking about pursuing one. It won&#39;t make you a developer overnight but it will certainly provide insight into the kinds of things you will learn and, by the end of the book, you should be able to write some simple Ruby applications!    </content><link rel='replies' type='application/atom+xml' href='http://irwinj.blogspot.com/feeds/678257779614880136/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/1137761125875994292/678257779614880136?isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/678257779614880136'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1137761125875994292/posts/default/678257779614880136'/><link rel='alternate' type='text/html' href='http://irwinj.blogspot.com/2013/05/review-computer-science-programming.html' title='Review: Computer Science Programming Basics in Ruby'/><author><name>Jason</name><uri>http://www.blogger.com/profile/11140602221519582396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>