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

<channel>
	<title>Transcending Frontiers &#187; Lights out management of a NetApp FAS2020</title>
	<atom:link href="http://blog.thefrontiergroup.com.au/category/tips-and-tricks/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.thefrontiergroup.com.au</link>
	<description>Your peek inside the collective mind of The Frontier Group</description>
	<lastBuildDate>Mon, 02 Apr 2012 04:32:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>Lights out management of a NetApp FAS2020</title>
		<link>http://blog.thefrontiergroup.com.au/2012/03/lights-out-management-of-a-netapp-fas2020/</link>
		<comments>http://blog.thefrontiergroup.com.au/2012/03/lights-out-management-of-a-netapp-fas2020/#comments</comments>
		<pubDate>Mon, 12 Mar 2012 03:53:05 +0000</pubDate>
		<dc:creator>mlambie</dc:creator>
				<category><![CDATA[Inside TFG]]></category>
		<category><![CDATA[Tips and Tricks]]></category>

		<guid isPermaLink="false">http://blog.thefrontiergroup.com.au/?p=1891</guid>
		<description><![CDATA[Our DEVOPS team manage a NetApp FAS2020 filer for a customer, and recently our network monitoring systems began reporting an issue connecting to the device&#8217;s BMC (Board Management Controller). This is the independent processor that provides the lowest level access to the system. In theory, if everything was to break and the machine was to [...]]]></description>
			<content:encoded><![CDATA[<p>Our <a href="http://en.wikipedia.org/wiki/DevOps">DEVOPS</a> team manage a <a href="http://www.netapp.com/us/products/storage-systems/fas2000/">NetApp FAS2020</a> filer for a customer, and recently our network monitoring systems began reporting an issue connecting to the device&#8217;s BMC (Board Management Controller). This is the independent processor that provides the lowest level access to the system. In theory, if everything was to break and the machine was to blow up, we should be able to log into the BMC and find out what is going on. It&#8217;s an entirely separate computer tasked with providing a (secure!) back-door to the system in case of catastrophic failure.</p>
<p>Even though NetApp has a phenomenal reputation &#8211; at a technical seminar last year, a sales engineer said that no NetApp customer has ever lost data due to a hardware failure &#8211; I still don&#8217;t feel comfortable without access to the BMC.</p>
<p>Access to the BMC (on other NetApp devices the LOM controller is called a Remote Management Controller, or RMC) is via SSH, using <em>naroot</em> as the username. From here you can move &#8220;up the chain&#8221; to a system console, and use CTRL-G to move &#8220;down the chain&#8221; back to the BMC.</p>
<p><code>mlambie@prime:~$ ssh naroot@ilca-netapp-bmc<br />
naroot@ilca-netapp-bmc's password:<br />
=== OEMCLP v1.0.0 BMC v1.2 ===<br />
bmc shell -&gt;<br />
bmc shell -&gt; system console<br />
Press ^G to enter BMC command shell<br />
Data ONTAP (ilca-netapp.thefrontiergroup.net.au)<br />
login: root<br />
Password:<br />
ilca-netapp&gt; Mon Mar 12 11:40:27 WST [console_login_mgr:info]: root logged in from console<br />
ilca-netapp&gt; &lt;<em>ctrl g&gt;</em><br />
=== OEMCLP v1.0.0 BMC v1.2 ===<br />
bmc shell -&gt; </code></p>
<p>The filer also allows management via SSH directly, and not through the BMC. I used this shell to restart the BMC.</p>
<p><code>ilca-netapp&gt; bmc help status<br />
bmc status<br />
- Display status for a Baseboard Managment Controller  (BMC).<br />
ilca-netapp&gt; bmc help reboot<br />
bmc reboot<br />
- Reboot the Baseboard Managment Controller (BMC)<br />
ilca-netapp&gt; bmc reboot<br />
ilca-netapp&gt; The BMC rebooted successfully</code></p>
<p>It looks like the SSH daemon was simply hung (it had an uptime of 270+ days prior to the reboot) and restarting the BMC through the management console in this way corrected the issues the monitoring systems were reporting.</p>
<script src="http://feeds.feedburner.com/~s/TranscendingFrontiers?i=http://blog.thefrontiergroup.com.au/2012/03/lights-out-management-of-a-netapp-fas2020/" type="text/javascript" charset="utf-8"></script>]]></content:encoded>
			<wfw:commentRss>http://blog.thefrontiergroup.com.au/2012/03/lights-out-management-of-a-netapp-fas2020/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Agile Development Sprints &#8211; This is how we do it</title>
		<link>http://blog.thefrontiergroup.com.au/2011/12/agile-development-sprints-this-is-how-we-do-it/</link>
		<comments>http://blog.thefrontiergroup.com.au/2011/12/agile-development-sprints-this-is-how-we-do-it/#comments</comments>
		<pubDate>Tue, 13 Dec 2011 19:40:24 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[Agile Development]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tips and Tricks]]></category>
		<category><![CDATA[agile development]]></category>
		<category><![CDATA[sprint]]></category>

		<guid isPermaLink="false">http://blog.thefrontiergroup.com.au/?p=1853</guid>
		<description><![CDATA[In any given week our company is typically developing five projects at once, with teams of one to three. We run one-week sprints with a half day planning session on Monday morning, and a review session on Friday afternoon. A sprint is the basic unit of development in Agile. Sprints tend to last between one [...]]]></description>
			<content:encoded><![CDATA[<p>In any given week our company is typically developing five projects at once, with teams of one to three. We run one-week sprints with a half day planning session on Monday morning, and a review session on Friday afternoon.</p>
<p><em>A sprint is the basic unit of development in Agile. Sprints tend to last between one week and one month and are a &#8220;timeboxed&#8221; development effort of a constant length.</em></p>
<p><strong>Our sprint planning session is broken down as follows:</strong></p>
<ul>
<li>Product owner &#8211; prioritise and explain highest priority items in the product backlog (we use <a title="Pivotal Tracker" href="http://pivotaltracker.com">Pivotal Tracker</a>). The team can ask questions at this point.</li>
<li>Product owner &#8211; set a sprint goal (what are we achieving this sprint).</li>
<li>Team &#8211; select Pivotal Tracker stories you can commit to, to attain that goal.</li>
<li>Team &#8211; demonstrate a solution to each story in the sprint and ensure no outstanding questions.</li>
</ul>
<p><strong>Our Friday afternoon review session:</strong></p>
<ul>
<li>Product Owner and Team  - demo all completed stories.</li>
<li>Team &#8211; Review estimates from the sprint and note down how you went and how you can improve (if target not met).</li>
<li>Team &#8211; Review points missed from the sprint and why, and how you can improve on that for next sprint.</li>
</ul>
<p>If you&#8217;re running sprints in your organisation do you do things a little differently? Drop us a line in the comments.</p>
<script src="http://feeds.feedburner.com/~s/TranscendingFrontiers?i=http://blog.thefrontiergroup.com.au/2011/12/agile-development-sprints-this-is-how-we-do-it/" type="text/javascript" charset="utf-8"></script>]]></content:encoded>
			<wfw:commentRss>http://blog.thefrontiergroup.com.au/2011/12/agile-development-sprints-this-is-how-we-do-it/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Introducing Has Face for Rails</title>
		<link>http://blog.thefrontiergroup.com.au/2011/07/introducing-has-face-for-rails/</link>
		<comments>http://blog.thefrontiergroup.com.au/2011/07/introducing-has-face-for-rails/#comments</comments>
		<pubDate>Tue, 26 Jul 2011 01:49:17 +0000</pubDate>
		<dc:creator>Mario Visic</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tips and Tricks]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[rubygems]]></category>

		<guid isPermaLink="false">http://blog.thefrontiergroup.com.au/?p=1742</guid>
		<description><![CDATA[Have you ever created an application where users are trusted to upload their own avatars? Wouldn&#8217;t it be great if there was an easy way to ensure the avatar contains a person&#8217;s face? Has Face is a neat little gem that uses the face.com API to ensure that an image contains a persons face. It&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>Have you ever created an application where users are trusted to upload their own avatars? Wouldn&#8217;t it be great if there was an easy way to ensure the avatar contains a person&#8217;s face?</p>
<p><a href="https://github.com/mariovisic/has_face">Has Face</a> is a neat little gem that uses the <a href="http://face.com">face.com API</a> to ensure that an image contains a persons face. It&#8217;s very simple to use and can be easily integrated into an existing rails application.</p>
<p>To get started add the has_face gem to your Gemfile and run a bundle install
<p class="gist-block" data-gist-id="1103591" data-gist-file="Gemfile" id="gist-1103591">Can&rsquo;t see this Gist? <a rel="nofollow" href="http://gist.github.com/1103591">View it on Github!</a></p>
<p>Run the generator to copy over an initializer: </p>
<p class="gist-block" data-gist-id="1103591" data-gist-file="install" id="gist-1103591">Can&rsquo;t see this Gist? <a rel="nofollow" href="http://gist.github.com/1103591">View it on Github!</a></p>
<p>The initializer should look something like this:</p>
<p class="gist-block" data-gist-id="1103591" data-gist-file="initializer.rb" id="gist-1103591">Can&rsquo;t see this Gist? <a rel="nofollow" href="http://gist.github.com/1103591">View it on Github!</a></p>
<p>Now we&#8217;ll need to make a face.com developer account. You can <a href="http://developers.face.com/signup/?g">signup for a free account over at face.com</a>. Once you have signed up, place your API key and API secret in the initializer config.</p>
<p>The last option in the initializer (skip_validation_on_error) will change the behavior of has_face when an error occurs. If set to true, when an error occurs a warning will be logged to the logfile with detailed information about the failure and face validation will be skipped. This can be useful if you want your application to function if the API service is not reachable. If the value is false then an exception will be raised when an API call fails, this will allow you to manually handle the exception yourself, please check the documentation for details on the errors raised.</p>
<p>Once the initializer settings are setup then we can add face validation to a model. In the example below I&#8217;m using carrierwave to attach the image to the model but other image attachment gems should also work fine (anything that correctly responds to `path` should be OK).</p>
<p class="gist-block" data-gist-id="1103591" data-gist-file="user.rb" id="gist-1103591">Can&rsquo;t see this Gist? <a rel="nofollow" href="http://gist.github.com/1103591">View it on Github!</a></p>
<p>That&#8217;s it, that&#8217;s all we need to have a functioning face validator. There are a few other options that I haven&#8217;t covered here in this short guide, please <a href="https://github.com/mariovisic/has_face">consult the readme</a> for more detailed information.</p>
<script src="http://feeds.feedburner.com/~s/TranscendingFrontiers?i=http://blog.thefrontiergroup.com.au/2011/07/introducing-has-face-for-rails/" type="text/javascript" charset="utf-8"></script>]]></content:encoded>
			<wfw:commentRss>http://blog.thefrontiergroup.com.au/2011/07/introducing-has-face-for-rails/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>RSpec 2.6.0 and RCov</title>
		<link>http://blog.thefrontiergroup.com.au/2011/05/rspec-2-6-0-and-rcov/</link>
		<comments>http://blog.thefrontiergroup.com.au/2011/05/rspec-2-6-0-and-rcov/#comments</comments>
		<pubDate>Thu, 19 May 2011 11:02:19 +0000</pubDate>
		<dc:creator>Mario Visic</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tips and Tricks]]></category>
		<category><![CDATA[rcov]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://blog.thefrontiergroup.com.au/?p=1510</guid>
		<description><![CDATA[Just upgraded to the newest RSpec (2.6.0) and found that RCov has stopped working completely? That&#8217;s what happened to me after running a bundle update. RCov refused to run, no error messages, just blank output. After looking around for a little while I found this: https://github.com/rspec/rspec-core/issues/370 In short: the new RSpec has been broken up [...]]]></description>
			<content:encoded><![CDATA[<p>Just upgraded to the newest RSpec (2.6.0) and found that RCov has stopped working completely? That&#8217;s what happened to me after running a bundle update. RCov refused to run, no error messages, just blank output.</p>
<p>After looking around for a little while I found this: <a href="https://github.com/rspec/rspec-core/issues/370">https://github.com/rspec/rspec-core/issues/370</a></p>
<p>In short: the new RSpec has been broken up into modules a tad more, the one that we require for rspec to run correctly <em>&#8216;autorun&#8217;</em> is not included by default, so to solve this simply add <em>require &#8216;rspec/autorun&#8217;</em> to the top of your spec_helper.</p>
<p class="gist-block" data-gist-id="978300" data-gist-file="spec_helper.rb" id="gist-978300">Can&rsquo;t see this Gist? <a rel="nofollow" href="http://gist.github.com/978300">View it on Github!</a></p>
<script src="http://feeds.feedburner.com/~s/TranscendingFrontiers?i=http://blog.thefrontiergroup.com.au/2011/05/rspec-2-6-0-and-rcov/" type="text/javascript" charset="utf-8"></script>]]></content:encoded>
			<wfw:commentRss>http://blog.thefrontiergroup.com.au/2011/05/rspec-2-6-0-and-rcov/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Sending Apple Push notifications in rails with Redis and apn_sender</title>
		<link>http://blog.thefrontiergroup.com.au/2011/05/sending-apple-push-notifications-in-rails-with-redis-and-apn_sender/</link>
		<comments>http://blog.thefrontiergroup.com.au/2011/05/sending-apple-push-notifications-in-rails-with-redis-and-apn_sender/#comments</comments>
		<pubDate>Wed, 11 May 2011 05:39:58 +0000</pubDate>
		<dc:creator>Mario Visic</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Inside TFG]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tips and Tricks]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.thefrontiergroup.com.au/?p=1363</guid>
		<description><![CDATA[Sending iOS push notifications from a Rails application is very easy to do these days, thankfully there are many great Ruby gems that can be used to handle most of the magic for you. Recently I ran into the apn_sender gem which handles sending push notifications in a really neat way. Sending push notifications directly [...]]]></description>
			<content:encoded><![CDATA[<p>Sending iOS push notifications from a Rails application is very easy to do these days, thankfully there are many great Ruby gems that can be used to handle most of the magic for you. Recently I ran into the <a href="https://github.com/kdonovan/apn_sender">apn_sender</a> gem which handles sending push notifications in a really neat way.</p>
<p>Sending push notifications directly from a Rails application can be slow and we probably don&#8217;t want to have the user waiting until the notification is sent, instead apn_sender can be setup to run a worker which is constantly connected to the apple push notification service. When there are new notifications to send, the notifications are queued up and sent through the always open connection that is maintained by the worker.</p>
<p>apn_sender uses <a href="http://redis.io/">redis</a> as a message queue to keep track of the notifications waiting to be sent, you&#8217;ll need to install it before using the gem.</p>
<p>To add apn_sender in your Rails 3 application, just add the gem to your Gemfile. We&#8217;re going to need the daemons gem too so we&#8217;ll include that as well.</p>
<p class="gist-block" data-gist-id="965976" data-gist-file="Gemfile" id="gist-965976">Can&rsquo;t see this Gist? <a rel="nofollow" href="http://gist.github.com/965976">View it on Github!</a></p>
<p>Now we can create our daemon which we will be using for sending push notifications, this can be placed anywhere, I&#8217;ve put mine in script/apn_sender. Make sure to add execute permission to the file after creating so we can run it.</p>
<p class="gist-block" data-gist-id="965976" data-gist-file="apn_sender.rb" id="gist-965976">Can&rsquo;t see this Gist? <a rel="nofollow" href="http://gist.github.com/965976">View it on Github!</a></p>
<p>Before the daemon can start running we&#8217;ll need to put our iOS push certificate into the application. Instructions for generating the certificates are available at the <a href="http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/ProvisioningDevelopment/ProvisioningDevelopment.html#//apple_ref/doc/uid/TP40008194-CH104-SW1">Apple Developer site</a>. The certificates need to be placed inside of /config/certs and should be named <i>apn_development.pem</i> or <i>apn_production.pem</i> for production.</p>
<p>Once the certificates are in their correct locations, we can start up the daemon. The daemon does not know about the Rails environment so we need to specify this when starting it up. The daemon supports <i>start</i>, <i>stop</i> and <i>restart</i> commands. There is a verbose flag available to output more information (which can be helpful when debugging).</p>
<p class="gist-block" data-gist-id="965976" data-gist-file="start_command.bash" id="gist-965976">Can&rsquo;t see this Gist? <a rel="nofollow" href="http://gist.github.com/965976">View it on Github!</a></p>
<p>Our application is now set up to send push notifications, this can now easily be performed by adding a new notification to the queue. The notify method on the APN class will take a push notification token and then our parameters, we can specify the alert message to show the user, whether or not we want sound as well as the number to display on the badge icon. Anything else we pass to notify will be sent as metadata in the push notification. Here&#8217;s an example of creating a notification.</p>
<p class="gist-block" data-gist-id="965976" data-gist-file="notify.rb" id="gist-965976">Can&rsquo;t see this Gist? <a rel="nofollow" href="http://gist.github.com/965976">View it on Github!</a></p>
<p>The worker should pick up the notification within a few seconds and send it off. The apn_sender has many other features that I haven&#8217;t covered, you can view the full documentation over at <a href="https://github.com/kdonovan/apn_sender">https://github.com/kdonovan/apn_sender</a>.</p>
<script src="http://feeds.feedburner.com/~s/TranscendingFrontiers?i=http://blog.thefrontiergroup.com.au/2011/05/sending-apple-push-notifications-in-rails-with-redis-and-apn_sender/" type="text/javascript" charset="utf-8"></script>]]></content:encoded>
			<wfw:commentRss>http://blog.thefrontiergroup.com.au/2011/05/sending-apple-push-notifications-in-rails-with-redis-and-apn_sender/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Allowing Multiple Users to Use The Pivotal Tracker Gem</title>
		<link>http://blog.thefrontiergroup.com.au/2011/05/allowing-multiple-users-to-use-the-pivotal-tracker-gem/</link>
		<comments>http://blog.thefrontiergroup.com.au/2011/05/allowing-multiple-users-to-use-the-pivotal-tracker-gem/#comments</comments>
		<pubDate>Tue, 03 May 2011 07:39:52 +0000</pubDate>
		<dc:creator>Aaron</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Tips and Tricks]]></category>
		<category><![CDATA[Pivotal Tracker]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://blog.thefrontiergroup.com.au/?p=1348</guid>
		<description><![CDATA[I&#8217;ve been using the Pivotal Tracker gem by Justin Smestad on a project to do various things but I ran into a problem using it with multiple API keys. The gem would create a single connection object and continue to mimic the user the first connection was made with, even when you&#8217;d updated the token [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been using the <a href="https://github.com/jsmestad/pivotal-tracker">Pivotal Tracker gem</a> by <a href="https://github.com/jsmestad">Justin Smestad</a> on a project to do various things but I ran into a problem using it with multiple API keys. The gem would create a single connection object and continue to mimic the user the first connection was made with, even when you&#8217;d updated the token to different user&#8217;s token. The Tracker API relies on you passing your API key for access to the projects and stories your account has access to, so I had the problem that the first user to use my app would determin access for everyone using the app. Not good!</p>
<p>After checking out the project the change was pretty simple but it highlighted an issue that I&#8217;ve seen in plenty of code where caching is done too broadly. In this case the cacheing (or memoization) was performed without taking into account the variable that was sent to establish the connection in the first place. The offending method looked like this :</p>
<p class="gist-block" data-gist-id="965963" data-gist-file="multiple-users-1.rb" id="gist-965963">Can&rsquo;t see this Gist? <a rel="nofollow" href="http://gist.github.com/965963">View it on Github!</a></p>
<p>This was set on the class and as such @connection would never be created after the first call, whether the token was reset or not. I just changed it so that the connection is cached for each @token the system uses. For us it&#8217;s a small number or users, but in a larger context of course you&#8217;d need to implement some invalidation protocols to stop the following code from (slowly) swallowing the world :</p>
<p class="gist-block" data-gist-id="965973" data-gist-file="multiple-users-2.rb" id="gist-965973">Can&rsquo;t see this Gist? <a rel="nofollow" href="http://gist.github.com/965973">View it on Github!</a></p>
<p>NoToken is just a class inheriting from StandardError that I chucked in there, the only thing that makes the gem now work properly come afterwards. I setup a hash and then store a new connection for each new incoming token, the connection is keyed by the token in the @connections hash. All pretty simple.</p>
<p>I&#8217;ve created a <a href="https://github.com/jsmestad/pivotal-tracker/pull/29">pull request</a> that will hopefully be accepted soon, I think it fixes an unexpected problem with the gem.</p>
<script src="http://feeds.feedburner.com/~s/TranscendingFrontiers?i=http://blog.thefrontiergroup.com.au/2011/05/allowing-multiple-users-to-use-the-pivotal-tracker-gem/" type="text/javascript" charset="utf-8"></script>]]></content:encoded>
			<wfw:commentRss>http://blog.thefrontiergroup.com.au/2011/05/allowing-multiple-users-to-use-the-pivotal-tracker-gem/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Adding additional processing support to CarrierWave</title>
		<link>http://blog.thefrontiergroup.com.au/2011/03/adding-additional-to-carrierwave/</link>
		<comments>http://blog.thefrontiergroup.com.au/2011/03/adding-additional-to-carrierwave/#comments</comments>
		<pubDate>Thu, 31 Mar 2011 02:24:30 +0000</pubDate>
		<dc:creator>Mario Visic</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Inside TFG]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tips and Tricks]]></category>
		<category><![CDATA[Websites or Tools]]></category>

		<guid isPermaLink="false">http://blog.thefrontiergroup.com.au/?p=1251</guid>
		<description><![CDATA[CarrierWave is a great gem for adding image uploading and basic processing abilities to your Rails applications. By default there is no way to set the quality of the resized images, which could be a very useful feature. One of the applications that we&#8217;re currently building has a requirement to resize and compress images to [...]]]></description>
			<content:encoded><![CDATA[<p><a href="https://github.com/jnicklas/carrierwave">CarrierWave</a> is a great gem for adding image uploading and basic processing abilities to your Rails applications. By default there is no way to set the quality of the resized images, which could be a very useful feature.</p>
<p>One of the applications that we&#8217;re currently building has a requirement to resize and compress images to produce smaller file sizes, as well as stripping out any personal information that may be stored in the uploaded images.</p>
<p>Out of the box CarrierWave provides a consistent interface to process images using RMagick, MiniMagick  or ImageScience. Resizing and cropping is supported for all three image processing engines but setting the quality or removing personal data is not supported. Thankfully, CarrierWave provides an easy way to extend the default functionality so we can do more.</p>
<p>For the examples I&#8217;ll be adding extra functionality to RMagick processing. If you&#8217;re using MiniMagick or ImageScience the methods will need to be altered to work correctly. We&#8217;ll start by adding a new initializer into our application.</p>
<p class="gist-block" data-gist-id="965983" data-gist-file="carrierwave_initializer.rb" id="gist-965983">Can&rsquo;t see this Gist? <a rel="nofollow" href="http://gist.github.com/965983">View it on Github!</a></p>
<p>You may be wondering about the fix_exif_rotation method. Well, some modern cameras always take photos upright, in portrait. When you take a photo in landscape mode the photo is actually saved as a portrait, but the photo will contain some extra orientation metadata. When we remove the embedded data in the photo this value gets removed, so as a result we need to manually rotate the photo, which is what this method does.</p>
<p>The application server will need to be restarted before the new initializer can be used. Once restarted the new filters can be used in an uploader like so:</p>
<p class="gist-block" data-gist-id="965983" data-gist-file="avatar_uploader.rb" id="gist-965983">Can&rsquo;t see this Gist? <a rel="nofollow" href="http://gist.github.com/965983">View it on Github!</a></p>
<p>That&#8217;s it! That&#8217;s all that&#8217;s needed to add extra quality and processing functionality to carrierwave.</p>
<script src="http://feeds.feedburner.com/~s/TranscendingFrontiers?i=http://blog.thefrontiergroup.com.au/2011/03/adding-additional-to-carrierwave/" type="text/javascript" charset="utf-8"></script>]]></content:encoded>
			<wfw:commentRss>http://blog.thefrontiergroup.com.au/2011/03/adding-additional-to-carrierwave/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Accessing ActiveRecord and ActiveModel Callback Chains in Rails 3</title>
		<link>http://blog.thefrontiergroup.com.au/2011/03/accessing-activerecord-and-activemodel-callback-chains-in-rails-3/</link>
		<comments>http://blog.thefrontiergroup.com.au/2011/03/accessing-activerecord-and-activemodel-callback-chains-in-rails-3/#comments</comments>
		<pubDate>Mon, 28 Mar 2011 11:34:18 +0000</pubDate>
		<dc:creator>Aaron</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tips and Tricks]]></category>
		<category><![CDATA[ActiveModel]]></category>
		<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[Rails 3]]></category>

		<guid isPermaLink="false">http://blog.thefrontiergroup.com.au/?p=1244</guid>
		<description><![CDATA[It seems that access to the ActiveRecord callback chain has changed recently, however the documentation still contains the following : To list the methods and procs registered with a particular callback, append _callback_chain to the callback name that you wish to list and send that to your class from the Rails console. This used to [...]]]></description>
			<content:encoded><![CDATA[<p>It seems that access to the ActiveRecord callback chain has changed recently, however the documentation still contains the following :</p>
<blockquote><p>To list the methods and procs registered with a particular callback, append _callback_chain to the callback name that you wish to list and send that to your class from the Rails console.</p></blockquote>
<p>This used to work in Rails 2.3.x and I&#8217;d used it a few times before, however trying to use it in Rails 3 gave me problems :</p>
<p><code><br />
HourEntry.before_save_callback_chain<br />
NoMethodError: undefined method `before_save_callback_chain' for #<br />
</code></p>
<p>After some digging around ActiveRecord then ActiveModel and ActiveSupport I figured I could just access the _#{type}_callbacks method and then reject and select these arrays to get what was required. This is what I came up with to get the before_save callbacks that I was interested in.</p>
<p><code><br />
HourEntry._save_callbacks.select { |callback| callback.kind.eql?(:before) }<br />
</code></p>
<p>This returns me the array of callback objects that are chained before I call save on the HourEntry model. If I want to check for a particular proc being in that chain then I can do :</p>
<p><code><br />
HourEntry._save_callbacks.select { |callback| callback.kind.eql?(:after) }.collect(&amp;:filter).include?(:archive_if_no_users)<br />
</code></p>
<p>It&#8217;s not optimal chaining a number of enumerable methods but I think it seems pretty readable.</p>
<p>I am hoping that the callback_chain methods return at some point (though I only used them sparingly) but more than that I&#8217;m hoping someone might be able to set me straight on how I&#8217;m going about getting around the callback chains on ActiveRecord and ActiveModel.</p>
<script src="http://feeds.feedburner.com/~s/TranscendingFrontiers?i=http://blog.thefrontiergroup.com.au/2011/03/accessing-activerecord-and-activemodel-callback-chains-in-rails-3/" type="text/javascript" charset="utf-8"></script>]]></content:encoded>
			<wfw:commentRss>http://blog.thefrontiergroup.com.au/2011/03/accessing-activerecord-and-activemodel-callback-chains-in-rails-3/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Broken Arrow Keys &#8211; Ubuntu 10.10 / VMWare Fusion / Macbook Pro</title>
		<link>http://blog.thefrontiergroup.com.au/2011/03/broken-arrow-keys-ubuntu-10-10-vmware-fusion-mabook-pro/</link>
		<comments>http://blog.thefrontiergroup.com.au/2011/03/broken-arrow-keys-ubuntu-10-10-vmware-fusion-mabook-pro/#comments</comments>
		<pubDate>Tue, 08 Mar 2011 04:11:22 +0000</pubDate>
		<dc:creator>Mark</dc:creator>
				<category><![CDATA[Inside TFG]]></category>
		<category><![CDATA[Tips and Tricks]]></category>

		<guid isPermaLink="false">http://blog.thefrontiergroup.com.au/?p=1231</guid>
		<description><![CDATA[After installing Ubuntu 10.10 (Maverick Meerkat) in a VMWare Fusion virtual machine on a MacBook Pro, I noticed the arrow keys were broken in Ubuntu. It turned out that the Fusion install wizard had configured the keyboard to use evdev, which did not work correctly inside the VM. The solution is to reconfigure the keyboard [...]]]></description>
			<content:encoded><![CDATA[<p>After installing Ubuntu 10.10 (Maverick Meerkat) in a VMWare Fusion virtual machine on a MacBook Pro, I noticed the arrow keys were broken in Ubuntu. It turned out that the Fusion install wizard had configured the keyboard to use <a href="http://linux.die.net/man/4/evdev">evdev</a>, which did not work correctly inside the VM.</p>
<p>The solution is to reconfigure the keyboard by running the following command:</p>
<pre>sudo dpkg-reconfigure console-setup</pre>
<p>To navigate the setup program without the arrow keys, I pressed the first letter of the desired option (eg. &#8220;a&#8221; for Apple Laptop), then pressed the right command key to cycle downwards through the list.</p>
<p>The configuration options that I chose were:</p>
<p>Apple Laptop for keyboard<br />
USA as origin of keyboard<br />
USA as keyboard layout<br />
No AltGr<br />
No Compose key<br />
Enter for the rest of the defaults.</p>
<p>The arrow keys work fine now.</p>
<script src="http://feeds.feedburner.com/~s/TranscendingFrontiers?i=http://blog.thefrontiergroup.com.au/2011/03/broken-arrow-keys-ubuntu-10-10-vmware-fusion-mabook-pro/" type="text/javascript" charset="utf-8"></script>]]></content:encoded>
			<wfw:commentRss>http://blog.thefrontiergroup.com.au/2011/03/broken-arrow-keys-ubuntu-10-10-vmware-fusion-mabook-pro/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>A brief introduction to the RVM Ruby API</title>
		<link>http://blog.thefrontiergroup.com.au/2010/12/a-brief-introduction-to-the-rvm-ruby-api/</link>
		<comments>http://blog.thefrontiergroup.com.au/2010/12/a-brief-introduction-to-the-rvm-ruby-api/#comments</comments>
		<pubDate>Tue, 14 Dec 2010 02:23:51 +0000</pubDate>
		<dc:creator>Darcy Laycock</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tips and Tricks]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[rvm]]></category>

		<guid isPermaLink="false">http://thefrontiergroup.com.au/blog/?p=1107</guid>
		<description><![CDATA[<p>As part of the work done on rvm during the Ruby Summer of Code, One of the
things I worked to add was a fairly comprehensive ruby version of the bash api.</p>

<p>Since then, the ruby api has been used to build a couple of small projects
and tools but it still maintains relatively undocumented.</p>

<p>Today, I&#8217;m going to introduce the basics of working with the ruby api, starting
by introducing the fundamental concepts you need to know and then going on to
cover how the most common example of it&#8217;s use (rvm gemset support in passenger)
works under the hood.</p>]]></description>
			<content:encoded><![CDATA[<p>As part of the work done on <a title="RVM" href="http://rvm.beginrescueend.com">RVM</a> during the <a title="Ruby Summer of Code" href="http://rubysoc.org">Ruby Summer of Code</a>, One of the things I worked to add was a fairly comprehensive Ruby version of the bash API.</p>
<p>Since then, the Ruby API has been used to build a couple of small projects and tools but it still maintains relatively undocumented.</p>
<p>Today, I’m going to introduce the basics of working with the Ruby API, starting by introducing the fundamental concepts you need to know and then going on to cover how the most common example of it’s use (rvm gemset support in passenger) works under the hood.</p>
<h2 id="getting_started">Getting started</h2>
<p>First off, you’re going to want to make sure you actually have the Ruby API installed. If you have a remotely recent (e.g. newer than 6 or so months) copy of rvm, you’ll already have a copy &#8211; Otherwise, you’re going to need to update your rvm install using <code>rvm update</code>.</p>
<p>To load the API, open up irb and type the following:</p>
<pre><code># First, find where rvm is installed
rvm_path = File.expand_path(ENV['rvm_path'] || '~/.rvm')
# Secondly, add the ruby library to the load path
$LOAD_PATH.unshift File.join(rvm_path, 'lib')
# Finally, actually load rvm
require 'rvm'
</code></pre>
<p>Once said code has been executed, you should have access to <code>RVM</code> constant in your irb session. The method we use to require it means that it is loaded from the currently installed version of rvm so you don’t have to deal with issues related to different versions between rvm itself and the Ruby API.</p>
<h2 id="the_bare_basics">The bare basics</h2>
<p>The ruby api works on the concept of a rvm ‘environment’ &#8211; Essentially, you can think of them as the equivalent of a shell instance &#8211; They keep track of instance variables, have their own ruby / gemset  selection and are sandboxed (for the most part) from other environments. Creating a new environment is as simple as doing the following in your ruby code:</p>
<pre><code>env = RVM.environment 'ree'
</code></pre>
<p>Or, alternatively, you can pass a block and it will be called with the environment as an argument. Along side this, you have <code>RVM.environments</code>, which accepts multiple ruby names and calls the block with each environment.</p>
<p>For convenience sake, RVM exposes <code>RVM.current</code>, an environment that defaults to the currently loaded gemset (e.g. if you open irb in <code>rbx@rails3</code>, it will be an environment using <code>rbx@rails3</code>).</p>
<p>As an added bonus, when you call an undefined method on <code>RVM</code>, we automatically use method missing to call it on <code>RVM.current</code> &#8211; Hence, If <code>RVM::Environment#some_instance_method </code>exists, you can use <code>RVM.some_instance_method</code> to call it in the current environment object.</p>
<h2 id="working_with_environments">Working with environments</h2>
<p>So, now that you know how to get environment object, you need to know how to use it. In the simplest form, the Ruby API mirrors the command line program by translating:</p>
<pre><code>rvm command action arg1 arg2
</code></pre>
<p>Into:</p>
<pre><code>env.command_action arg1, arg2
</code></pre>
<p>With the library automatically taking care of converting arguments (e.g. a hash as the last value will be converted to arguments to the program).</p>
<p>As an example, to call <code>rvm list strings</code>, One would use <code>env.list_strings</code>. Likewise, <code>rvm use</code> becomes <code>env.use</code> and so on and so forth. In these cases, use switches the environments ruby &#8211; not the running ruby itself.</p>
<p>One of the added features in the Ruby API is that <code>use</code> and <code>gemset_use</code> have alternatives with a bang (<code>use!</code> and <code>gemset_use!</code>) that will switch the currently loaded ruby’s gemset (by changing <code>GEM_PATH</code> and <code>GEM_HOME</code> and then telling rubygems about the change) - raising an exception if it’s for a different ruby installation. This switch makes it possibly to dynamically switch your ruby applications gemset whilst running.</p>
<p>Of course, dealing with a direct port of the API isn’t always nice when you’re writing a lot of code <code>env.alias_list</code> feels clunky compared to most ruby code and some of the tools are rough around the edges. With this in mind, the ruby api offers wrappers for situations where this becomes noticeable, e.g <code>env.aliases</code> will return a more ruby-like wrapper for the alias command that lets you do things such as <code>env.alias.all</code>, <code>env.aliases.create</code> and so on. In some cases (e.g. <code>env.list_*</code>), the wrappers add features (such as expanding strings) that aren’t found in the bash API via the wrapper.</p>
<h2 id="a_real_world_example">A real world example</h2>
<p>With that said and done, it’s time to look at a real world example. In this case, the most commonly-used example of the rvm ruby API &#8211; A use of passengers support for a <code>config/setup_load_paths.rb</code> file which lets passenger automatically load <code>.rvmrc</code> files. When a compatible ruby is detected, the file will automatically switch the gemset on the fly &#8211; In essence, letting passenger work with the one-gemset-per-application philosophy we advocate when dealing with rvm.</p>
<p>For references sake, the rvm portion of the code is:</p>
<pre><code>if ENV['MY_RUBY_HOME'] &amp;&amp; ENV['MY_RUBY_HOME'].include?('rvm')
  begin
    rvm_path     = File.dirname(File.dirname(ENV['MY_RUBY_HOME']))
    rvm_lib_path = File.join(rvm_path, 'lib')
    $LOAD_PATH.unshift rvm_lib_path
    require 'rvm'
    RVM.use_from_path! File.dirname(File.dirname(__FILE__))
  rescue LoadError
    # RVM is unavailable at this point.
    raise "RVM ruby lib is currently unavailable."
  end
end
</code></pre>
<p>Line by line, this code essentially:</p>
<ol>
<li>Checks that we’re loading it in an RVM ruby &#8211; rvm always sets the <code>MY_RUBY_HOME</code> environment variable when using wrappers and we ensure that “rvm” is part of said variables value.</li>
<li>It begins a begin-rescue-end section of code to load rvm &#8211; Giving us a nice error message if rvm isn’t available.</li>
<li>Based on my ruby home, We find the location of your rvm install (as <code>rvm_path </code>may or may not be set at this point).</li>
<li>We add the rvm ruby lib directory to the load path</li>
<li>We require the API</li>
</ol>
<p>Up until this point, it is almost exactly like our original example. Where it differs is the next line:</p>
<pre><code>RVM.use_from_path! File.dirname(File.dirname(__FILE__))
</code></pre>
<p>Knowing what I wrote about earlier, we know this is the same as:</p>
<pre><code>RVM.current.use_from_path! File.dirname(File.dirname(__FILE__))
</code></pre>
<p>Which, if we look under the hood, does:</p>
<pre><code>RVM.current.use! RVM.current.tools.path_identifier(path)
</code></pre>
<p>Expanding this again using what we learnt earlier, we know that <code>RVM.current.use! </code>will take a given ruby string (e.g. <code>ree@rails3</code>) and attempt to switch out the gemset when the ruby versions match. Continuing on, we know <code>RVM.current.tools.path_identifier </code>is roughly the same as <code>RVM.current.tools_path_identifier</code> &#8211; a line which takes a path and, taking into account .rvmrc files, returns the identifier (e.g. <code>ree@rails3</code>) we’d get if we had changed into the given directory from the command line.</p>
<p>Putting it all together, the ruby api essentially just finds out which identifier the given path should use (by loading a projects <code>.rvmrc</code> in the given environment), checks they’re for the same ruby install (to avoid issues with binary gems) and finally switches out the <code>GEM_HOME</code> and <code>GEM_PATH</code> variables for the current process, letting your application use a different gemset.</p>
<p>In short, under the hood it simple finds out the gemset details and updates your application to switch them out similar to how rvm would from the command line.</p>
<h2 id="more_examples">More examples</h2>
<p>We’ve only covered the basics of of the ruby api &#8211; For the most part, everything implemented in the bash API is supposed to be (except where it lags behind in terms of updates) exposed via the Ruby API in a simple, consistent manner. In practice, this has primarily been used for things like <a href="https://github.com/tomas-stefano/infinity_test">infinity_test</a> and <a href="http://www.metaskills.net/2010/7/30/the-rvm-ruby-api">various CI-related work</a> which make working with multiple rubies easier from ruby applications.</p>
<p>I’d ultimately love to see it used more for tools built around rvm &#8211; e.g. a web interface for managing a servers system wide install and exposing it over HTTP. Lastly, because it’s written in Ruby, if you’ve ever wanted to contribute to rvm but have felt apprehensive due to the fact it’s written in shell script, the rvm ruby API is a good place to start.</p>
<script src="http://feeds.feedburner.com/~s/TranscendingFrontiers?i=http://blog.thefrontiergroup.com.au/2010/12/a-brief-introduction-to-the-rvm-ruby-api/" type="text/javascript" charset="utf-8"></script>]]></content:encoded>
			<wfw:commentRss>http://blog.thefrontiergroup.com.au/2010/12/a-brief-introduction-to-the-rvm-ruby-api/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

