<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>BilsonRails</title>
	<atom:link href="http://bilsonrails.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://bilsonrails.wordpress.com</link>
	<description>David Baldwin</description>
	<lastBuildDate>Mon, 18 Aug 2008 01:44:18 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='bilsonrails.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>BilsonRails</title>
		<link>http://bilsonrails.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://bilsonrails.wordpress.com/osd.xml" title="BilsonRails" />
	<atom:link rel='hub' href='http://bilsonrails.wordpress.com/?pushpress=hub'/>
		<item>
		<title>models_to_utc Rails plugin</title>
		<link>http://bilsonrails.wordpress.com/2008/08/17/models_to_utc-rails-plugin/</link>
		<comments>http://bilsonrails.wordpress.com/2008/08/17/models_to_utc-rails-plugin/#comments</comments>
		<pubDate>Mon, 18 Aug 2008 01:40:28 +0000</pubDate>
		<dc:creator>bilsonrails</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://bilsonrails.wordpress.com/?p=41</guid>
		<description><![CDATA[For me, out-of-the box time zone support is the most useful upgrade in Rails 2.1. For new applications, it just works. However, if your app was originally devised for a single time zone, there is still a bit of work &#8230; <a href="http://bilsonrails.wordpress.com/2008/08/17/models_to_utc-rails-plugin/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bilsonrails.wordpress.com&amp;blog=3510979&amp;post=41&amp;subd=bilsonrails&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>For me, out-of-the box time zone support is the most useful upgrade in Rails 2.1. For new applications, it just works. However, if your app was originally devised for a single time zone, there is still a bit of work ahead of you. You need to convert all of those timestamps in your database to UTC.  With coding support and direction from <a href="http://github.com/jqr">Eli Miller</a>, here is a plugin that performs this conversion in your models via a migration&#8230;all without breaking a sweat or a nail.</p>
<h2>models_to_utc &#8211; Rails &gt;= 2.1</h2>
<h3>The Skinny&#8230;</h3>
<p>This plugin adds a &#8220;models_to_utc&#8221; method to your migrations that converts all legacy :datetime and :timestamp records in a model to UTC.  It also provides the &#8220;revert_models_to_utc&#8221; method for your down migration.  The method takes two arguments:</p>
<ol>
<li>One or more models</li>
<li>The time zone that you are converting from &#8211; run rake time:zones:all|local|us for a list</li>
</ol>
<p>So, if your application was originally developed for the Eastern US time zone, it will add 4 or 5 hours (depending upon DST) to each timestamp.</p>
<h3>Migration Example</h3>
<pre>
class MyUtcMigration &lt; ActiveRecord::Migration

  class User &lt; ActiveRecord::Base; end
  class Dog &lt; ActiveRecord::Base; end
  class Cat &lt; ActiveRecord::Base; end

  self.up
    models_to_utc([User, Dog, Cat], 'Eastern Time (US &amp; Canada)')
  end

  self.down
    revert_models_to_utc([User, Dog, Cat], 'Eastern Time (US &amp; Canada)')
  end

end
</pre>
<h2>Git it!</h2>
<p>The repository is located at GitHub:<br />
<a href="http://github.com/bilson/models_to_utc/tree/master">http://github.com/bilson/models_to_utc/tree/master</a></p>
<p><strong>Standard Disclaimer:</strong>  Always thoroughly test on sample data to make sure this is performing the desired effect on your data.  Patches welcome.</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/bilsonrails.wordpress.com/41/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/bilsonrails.wordpress.com/41/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bilsonrails.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bilsonrails.wordpress.com/41/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bilsonrails.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bilsonrails.wordpress.com/41/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bilsonrails.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bilsonrails.wordpress.com/41/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bilsonrails.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bilsonrails.wordpress.com/41/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bilsonrails.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bilsonrails.wordpress.com/41/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bilsonrails.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bilsonrails.wordpress.com/41/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bilsonrails.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bilsonrails.wordpress.com/41/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bilsonrails.wordpress.com&amp;blog=3510979&amp;post=41&amp;subd=bilsonrails&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bilsonrails.wordpress.com/2008/08/17/models_to_utc-rails-plugin/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/54b55c47f36e7b7153a404a70d97c59e?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">bilsonrails</media:title>
		</media:content>
	</item>
		<item>
		<title>Migrate to UTC in Rails 2.1</title>
		<link>http://bilsonrails.wordpress.com/2008/08/04/migrate-to-utc-in-rails-21/</link>
		<comments>http://bilsonrails.wordpress.com/2008/08/04/migrate-to-utc-in-rails-21/#comments</comments>
		<pubDate>Mon, 04 Aug 2008 17:28:14 +0000</pubDate>
		<dc:creator>bilsonrails</dc:creator>
				<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://bilsonrails.wordpress.com/?p=29</guid>
		<description><![CDATA[UPDATE &#8211; 8/17/2008 &#8211; The spirit of this post has now been vastly improved and delivered as the &#8220;models_to_utc&#8221; migration plugin For me, out-of-the box time zone support is the most useful upgrade in Rails 2.1. For new applications, it &#8230; <a href="http://bilsonrails.wordpress.com/2008/08/04/migrate-to-utc-in-rails-21/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bilsonrails.wordpress.com&amp;blog=3510979&amp;post=29&amp;subd=bilsonrails&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><strong>UPDATE &#8211; 8/17/2008</strong> &#8211; The spirit of this post has now been vastly improved and delivered as the <a href="http://bilsonrails.wordpress.com/2008/08/17/models_to_utc-rails-plugin/">&#8220;models_to_utc&#8221;</a> migration plugin</p>
<p>For me, out-of-the box time zone support is the most useful upgrade in Rails 2.1.  For new applications, it just works.  However, if your app was originally devised for a single time zone, there is still a bit of work ahead of you.  You need to convert all of those timestamps in your database to UTC.  If the app was originally developed for use in Iceland, then you&#8217;re done!  Otherwise, read on&#8230;</p>
<p>I am in the process of migrating an app with about 20 different timestamps (outside of the created_at/updated_at) in various models.  Leveraging the time zone support built into Rails makes it reasonably simple to update a number of timestamps with a migration.  The example below is ugly, but seems to do the trick for a User model&#8230;</p>
<pre>
User.find(:all).each do |u|

  created_at, last_logged_in_at, last_appointment_at = '','',''

  %w[created_at last_logged_in_at last_assigned_at].each do |t|
    eval("#{t} = !u.#{t}.blank? ? (u.#{t}.utc - u.#{t}.in_time_zone('UTC').in_time_zone('Eastern Time (US &amp; Canada)').utc_offset) : u.#{t}")
  end

  u.update_attributes(
    :last_lead_assigned_at =&gt; last_lead_assigned_at,
    :created_at =&gt; created_at,
    :last_appointment_at =&gt; last_appointment_at
  ) 

end
</pre>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/bilsonrails.wordpress.com/29/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/bilsonrails.wordpress.com/29/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bilsonrails.wordpress.com/29/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bilsonrails.wordpress.com/29/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bilsonrails.wordpress.com/29/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bilsonrails.wordpress.com/29/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bilsonrails.wordpress.com/29/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bilsonrails.wordpress.com/29/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bilsonrails.wordpress.com/29/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bilsonrails.wordpress.com/29/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bilsonrails.wordpress.com/29/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bilsonrails.wordpress.com/29/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bilsonrails.wordpress.com/29/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bilsonrails.wordpress.com/29/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bilsonrails.wordpress.com/29/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bilsonrails.wordpress.com/29/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bilsonrails.wordpress.com&amp;blog=3510979&amp;post=29&amp;subd=bilsonrails&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bilsonrails.wordpress.com/2008/08/04/migrate-to-utc-in-rails-21/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/54b55c47f36e7b7153a404a70d97c59e?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">bilsonrails</media:title>
		</media:content>
	</item>
		<item>
		<title>Step FORWARD with Rails Migrations</title>
		<link>http://bilsonrails.wordpress.com/2008/08/01/add-a-step-up-task-to-rails-migrations/</link>
		<comments>http://bilsonrails.wordpress.com/2008/08/01/add-a-step-up-task-to-rails-migrations/#comments</comments>
		<pubDate>Fri, 01 Aug 2008 20:38:12 +0000</pubDate>
		<dc:creator>bilsonrails</dc:creator>
				<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://bilsonrails.wordpress.com/?p=18</guid>
		<description><![CDATA[The db:rollback rake task is a great way to step back through migrations one by one. It also allows specification of the number of requested migrations to rollback with the STEP variable. Perhaps I am just not seeing it, but &#8230; <a href="http://bilsonrails.wordpress.com/2008/08/01/add-a-step-up-task-to-rails-migrations/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bilsonrails.wordpress.com&amp;blog=3510979&amp;post=18&amp;subd=bilsonrails&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>The db:rollback rake task is a great way to step back through migrations one by one.  It also allows specification of the number of requested migrations to rollback with the STEP variable.  Perhaps I am just not seeing it, but why is a forward version of this functionality not included?  Sure I can do db:migrate:up VERSION=3987937298798947, but who wants to type in a huge timestamp?  A simple hack of ActiveRecord and the Rails source code will get you there:</p>
<p>Add this task to the :db namespace in <em>rails/railties/lib/tasks/database.rake</em></p>
<pre>
desc 'Pushes the schema to the next version. Specify the number of steps with STEP=n'
task :forward =&gt; :environment do
  step = ENV['STEP'] ? ENV['STEP'].to_i : 1
  ActiveRecord::Migrator.forward('db/migrate/', step)
  Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
end
</pre>
<p>Then add this method to the Migrator class in <em>rails/activerecord/lib/active_record/migration.rb</em></p>
<pre>
def forward(migrations_path, steps=1)
  migrator = self.new(:up, migrations_path)
  start_index = migrator.migrations.index(migrator.current_migration)

  return unless start_index

  finish = migrator.migrations[start_index + steps]
  up(migrations_path, finish ? finish.version : 0)
end
</pre>
<p>Now to step forward through your migrations simply run:<br />
Step forward 1 migration</p>
<pre>
rake db:forward
</pre>
<p>Or&#8230;step forward 7 migrations</p>
<pre>
rake db:forward STEP=7
</pre>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/bilsonrails.wordpress.com/18/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/bilsonrails.wordpress.com/18/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bilsonrails.wordpress.com/18/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bilsonrails.wordpress.com/18/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bilsonrails.wordpress.com/18/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bilsonrails.wordpress.com/18/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bilsonrails.wordpress.com/18/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bilsonrails.wordpress.com/18/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bilsonrails.wordpress.com/18/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bilsonrails.wordpress.com/18/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bilsonrails.wordpress.com/18/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bilsonrails.wordpress.com/18/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bilsonrails.wordpress.com/18/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bilsonrails.wordpress.com/18/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bilsonrails.wordpress.com/18/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bilsonrails.wordpress.com/18/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bilsonrails.wordpress.com&amp;blog=3510979&amp;post=18&amp;subd=bilsonrails&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bilsonrails.wordpress.com/2008/08/01/add-a-step-up-task-to-rails-migrations/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/54b55c47f36e7b7153a404a70d97c59e?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">bilsonrails</media:title>
		</media:content>
	</item>
		<item>
		<title>Conman &#8211; Fine-Grained Ruby on Rails Content Management Control</title>
		<link>http://bilsonrails.wordpress.com/2008/06/03/conman-fine-grained-ruby-on-rails-content-management-control/</link>
		<comments>http://bilsonrails.wordpress.com/2008/06/03/conman-fine-grained-ruby-on-rails-content-management-control/#comments</comments>
		<pubDate>Tue, 03 Jun 2008 06:42:10 +0000</pubDate>
		<dc:creator>bilsonrails</dc:creator>
				<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://bilsonrails.wordpress.com/?p=9</guid>
		<description><![CDATA[UPDATE ( 7/13/2008 ) There is now a simple demo application located here&#8230; http://baldwindev.com/conman_demo/pages Also, you can grab the Git repo for this demo with: git clone git://github.com/bilson/conman_demo.git It&#8217;s always an exciting moment on release day of a new website. &#8230; <a href="http://bilsonrails.wordpress.com/2008/06/03/conman-fine-grained-ruby-on-rails-content-management-control/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bilsonrails.wordpress.com&amp;blog=3510979&amp;post=9&amp;subd=bilsonrails&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><strong>UPDATE ( 7/13/2008 )</strong><br />
There is now a simple demo application located here&#8230; <a href="http://baldwindev.com/conman_demo/pages">http://baldwindev.com/conman_demo/pages</a><br />
Also, you can grab the Git repo for this demo with:</p>
<pre>
git clone git://github.com/bilson/conman_demo.git
</pre>
<hr />
<br />
It&#8217;s always an exciting moment on release day of a new website.  You&#8217;ve been working with the client through the final stages and tweaks and the site is now in that pristine shape and ready to face the world.  The client is happy and looking forward to the future as they will no longer have to pay additional monies for updates because you&#8217;ve also included a slick and powerful content management system.  And this content management system allows them to have the power to control just about everything on the site.  </p>
<p>You release the site and it looks perfect&#8230;for the first two weeks.  Then the client starts to add and revise content.  You&#8217;ve given them carte blanche to add all kinds of content&#8230;headings, colors, underlines, strike-throughs, images, etc.  Before long the site looks like it has been designed in 1995 or on some hallucinogenic drug.</p>
<p>You&#8217;ve given too much control and power to the client.  In practice, this usually results in one of three outcomes:</p>
<ol>
<li>You have given the client so many options that they are completely confused about how to use any of them.  Therefore, they don&#8217;t use them and see little value in the work you have completed for them.  And they aren&#8217;t all that pleased with you.</li>
<li>You have given the client so many options that they are completely confused about how to use any of them.  Yet they push forward and make changes, butchering the site and code and getting frustrated each time they want to make a change.  And they aren&#8217;t all that pleased with you.</li>
<li>Your client is ecstatic about the plethora of options you have given them.  They make constant changes to the site and even send you congratulatory emails about the changes they have made.  They also have no design sense and think that &#8220;rainbow&#8221; is a clean and powerful color scheme.  Your client loves you!</li>
</ol>
<p>Now I am assuming that a major factor in your client shelling out the dough for you to design this website was&#8230;for you to design this website.  It wasn&#8217;t for you to design a pretty shell and for them to trample it.  You need to take back control of your designs.  The more you can strictly define what your client can and cannot do, the better chance that your client&#8217;s brand will stay intact and convey the intended message.  If the site starts to look shoddy, the client is damaged.  And you&#8217;re damaged too.  You have one less site to display in your portfolio and one bad example of your work for all to see.</p>
<p>So how do you take back control while still allowing the client to update content?  First, limits need to be set.  Anything that is going to damage the design structure of the site just can&#8217;t be updated.  Sorry.  Second, there needs to be a way to update specific pieces of a page without disrupting said design structure.  </p>
<p>Enter ConMan.  Wow, was that ever a long and overly-dramatic lead-in.  Anyway, ConMan is a Rails generator that allows you to do exactly what I have mentioned and to do it fairly easily.  The system is broken into parts that are familiar to you if you are using Rails.  They consist of&#8230;</p>
<p><strong>Layouts</strong> &#8211; These are exactly what you think they are.  You set up a basic layout for different page types and enter defaults for stylesheets, javascripts, keywords, descriptions, etc.  You just place a placeholder named {content} in the layout wherever you want the unique page content to show up.</p>
<p><strong>Stylesheets &amp; Javascripts</strong> &#8211; You can manage your stylesheets and javascripts directly in the browser and call them out in your page layout.</p>
<p><strong>Pages</strong> &#8211; These are simply set up by choosing a layout and entering your unique content.  Meta info can be overriden, additional code appended to the  area, the  tag rewritten, etc.  These pages will pull from the database, but they don&#8217;t have to.  You can also choose to make the page refer to a page that is hard-coded into your application.  This allows you to setup the page title, meta info and layout in the database and then simply refer to it in the controller of your application.  That way all of your pages, from the database or not, are using the same page layout.</p>
<p><strong>Snippets</strong> &#8211; You&#8217;ve seen snippets before.  They are just reusable pieces of HTML that can be used in layouts and pages.  However, these snippets are, dare I say, more flexible than what you may be imagining.  There are a few different kinds of snippets:</p>
<ol>
<li><strong>Static Shareable Snippets:</strong> A basic static snippet that is reusable in any layout or page.  Suppose we make a snippet that is just the Navigation portion of the website.  It is the same in every layout.  We just give this snippet a placeholder name&#8230;let&#8217;s called it &#8220;nav&#8221;.  Then you can call this out anywhere with {snippet-nav}.</li>
<li><strong>Dynamic Shareable Snippets:</strong> These are essentially the same as their static brethren.  The only difference being that you can enter the {content} tag into any snippet and it suddenly becomes dynamic.  This allows you to, from any layout or page, to add an instance of this snippet with unique content that will appear in place of that {content} tag.  The instance will automatically be named with the ID of the record and will be something like {snippet-23}.  Perhaps you have a sidebar structure that is used throughout the site that appears in various layouts, with very minor changes to the content within.  This might be a good candidate for dynamic shareable snippets.  Honestly, in practice, I haven&#8217;t found these to be overly useful.</li>
<li><strong>Unshared Snippets:</strong>  Lastly are the snippets that I find to be most useful in achieving the goal of limiting what clients can update on their site.  An unshared snippet is basically just a snippet that is tied to a specific page on the site.  These snippets are also automatically named by ID&#8230;{snippet-47}.  You just call them out with the tag name in your page.</li>
</ol>
<p>The upshot of #2 and #3 is that you can now have a snippet as small as a single letter and tie it to a specific page.  And these snippets can be called out from a database or hard-coded page.  In a hard-coded page you would simply use the &#8220;include_snippet&#8221; helper (ex. include_snippet(&#8216;snippet-34&#8242;)).  That way all of your snippets are managed online without having to touch the hard-coded page.</p>
<p>All of this is well and good, but this may sound slightly convoluted and trying to explain how to manage this to a client would likely be an exercise in futility.  And, lest we forget, we are hired to make our clients lives slightly better and easier, not slightly worse and more complex.  So we need to limit what the client sees.  Luckily the structure we have built with the snippets allows us to do just that.</p>
<p>And the solution is a surprisingly simple one to implement.  Since all of the snippets run through the same basic method before being written to the page, we can wrap this content with whatever we so choose. This creates an easy way to flip the site into &#8220;Edit Mode&#8221; by wrapping each dynamic or unshared snippet with a div with an id of &#8220;edit_mode&#8221; and a button at the top linking to the page to edit that specific snippet.  The end result is that the client can look at their regular website and see 6 different updateable snippets called out right within the page and click on them to make an update.  It might only be an update to a few words.  Or it might be more.  You have the option to set each snippet to be a simple text area or an FckEditor text area.  The text area is usually the best option as it allows for the most control and least chance of the client messing it up.</p>
<h2>Installing ConMan</h2>
<p>Installation of ConMan is quite simple.  It is really just a generator that will create the following models/tables:</p>
<ul>
<li>page_layouts</li>
<li>pages</li>
<li>snippets</li>
<li>snippet_owners</li>
<li>styles</li>
<li>jscripts</li>
</ul>
<p><em>Note: I will likely prefix these tables with a &#8220;cm_&#8221; in the future, as &#8220;pages&#8221; could easily collide with a table already existing in your application.</em></p>
<p>Git it:</p>
<pre>
git submodule add git@github.com:bilson/conman.git vendor/plugins/conman
</pre>
<p>Also, note that you will need Haml installed in your application for this to work<br />
Get it here&#8230;<br />
<a href="http://haml.hamptoncatlin.com/download/">http://haml.hamptoncatlin.com/download/</a>      </p>
<p>Also, highly recommended (unless you don&#8217;t want to allow any fckeditor instances)<br />
fckeditor plugin &#8211; svn://rubyforge.org//var/svn/fckeditorp/trunk/fckeditor   </p>
<p>Note: If you are using the role_requirement and restful_authentication plugins there is some basic code commented out for your use in each of the controllers.  There is also some example authorization code commented out in lib/conman.rb that limits who can view the site in &#8220;Edit Mode&#8221;. </p>
<p><strong>STEP 1 </strong> </p>
<pre>
script/generate conman
</pre>
<p><strong>STEP 2 </strong><br />
Add these routes to your routes.rb:    </p>
<pre>
map.resources :pages, :collection =&gt; {:hardcoded_example =&gt; :get}
map.resources :page_layouts
map.resources :styles
map.resources :jscripts
map.resources :snippets
map.resources :snippet_owners, :collection =&gt; {:unshared_management =&gt; :get, :edit_single =&gt; :get}
</pre>
<p><strong>STEP 3  </strong></p>
<pre>
rake db:migrate
</pre>
<p><strong>STEP 4 </strong><br />
Add this to app/controllers/application.rb&#8230;    </p>
<pre>
include Conman
before_filter :edit_mode
</pre>
<h2>Usage</h2>
<p>You should now be able to navigate to the pages controller and see a sample layout, a database page example, a hard-coded example, various sample snippets and some stylesheets created for you.</p>
<p>ConMan is meant to fully integrate with the rest of your site rather than sitting out on an island by itself.  I use it as the basis of my sites and build on top of both the administrative area and the public facing area.  These two areas use layouts located within the app/views/layouts/conman folder.  Any administrative areas can use the &#8220;conman&#8221; layout by entering the following into the controller&#8230;</p>
<pre>
layout "conman/conman"
</pre>
<p>The pages that will make up the public-facing portion of your website will use the following layout&#8230;</p>
<pre>
layout "conman/show_pages"
</pre>
<p>You can, of course, call this layout for specific actions with&#8230;</p>
<pre>
render :layout =&gt; 'conman/show_pages'
</pre>
<p>An action can reference a page from the database by simply calling out the specific id of the page.  Here is the hardcoded_example action that will be automatically generated when running db:migrate&#8230;</p>
<pre>
def hardcoded_example
  @page = Page.find(2)
  render :layout =&gt; 'conman/show_pages'
end
</pre>
<p>Or, if the id is present in the URL, just call it like so&#8230;</p>
<pre>
def show
  @page = Page.find(params[:id])
  render :layout =&gt; 'conman/show_pages'
end
</pre>
<p>The main target of ConMan is to manage the content of a site with fine-grained control.  However, given that it is meant to blend in with the rest of your application, one could easily only use some of the layout features, build on top and leave the rest.  I will likely add additional features in the future, but will try to stay away from adding things that would force the developer to &#8220;buy-in&#8221; to a certain way to build their app.</p>
<p>Give it a run and give me some feedback&#8230;good or bad or really bad.  Regardless, let your clients manage the content, not the design, of their site.  Your client&#8217;s clients will thank you for it.</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/bilsonrails.wordpress.com/9/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/bilsonrails.wordpress.com/9/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bilsonrails.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bilsonrails.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bilsonrails.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bilsonrails.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bilsonrails.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bilsonrails.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bilsonrails.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bilsonrails.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bilsonrails.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bilsonrails.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bilsonrails.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bilsonrails.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bilsonrails.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bilsonrails.wordpress.com/9/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bilsonrails.wordpress.com&amp;blog=3510979&amp;post=9&amp;subd=bilsonrails&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bilsonrails.wordpress.com/2008/06/03/conman-fine-grained-ruby-on-rails-content-management-control/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/54b55c47f36e7b7153a404a70d97c59e?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">bilsonrails</media:title>
		</media:content>
	</item>
		<item>
		<title>Why OpenID is only sort of awesome.</title>
		<link>http://bilsonrails.wordpress.com/2008/05/22/why-openid-is-only-sort-of-awesome/</link>
		<comments>http://bilsonrails.wordpress.com/2008/05/22/why-openid-is-only-sort-of-awesome/#comments</comments>
		<pubDate>Fri, 23 May 2008 02:20:24 +0000</pubDate>
		<dc:creator>bilsonrails</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://bilsonrails.wordpress.com/?p=5</guid>
		<description><![CDATA[I finally got around to starting my own blog because it&#8217;s what all the &#8220;cool kids&#8221; started doing five years ago. After 5 or 10 minutes of in-depth and intense research I decided to go with WordPress. And it&#8217;s really &#8230; <a href="http://bilsonrails.wordpress.com/2008/05/22/why-openid-is-only-sort-of-awesome/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bilsonrails.wordpress.com&amp;blog=3510979&amp;post=5&amp;subd=bilsonrails&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I finally got around to starting my own blog because it&#8217;s what all the &#8220;cool kids&#8221; started doing five years ago. After 5 or 10 minutes of in-depth and intense research I decided to go with WordPress.  And it&#8217;s really outstanding so I can&#8217;t complain.  Which leads to my complaint:</p>
<p>Another cool kid technology is OpenID.  OpenID allows someone to create an account with an OpenID provider such as myopenid.com and then use that same login across multiple sites.  After creating your account you will be provided with a unique ID.  I happen to have an account with MyOpenID and my address is bilson.myopenid.com.  Basically all I have to do to make use of this ID is to:</p>
<ol>
<li>Login to myopenid.com with my username and password.</li>
<li>Login to any site that supports OpenID with just my OpenID username&#8230; bilson.myopenid.com.</li>
</ol>
<p>Thus, in a future perfect world I could potentially login to myopenid.com when I get to work and then log into every other website I want to without ever having to enter a different username.  And I wouldn&#8217;t have to enter a password for any of the sites.  Sweet, magical technology.</p>
<p>Unfortunately, competition between the major web outposts are already starting to suck the productivity out of this technology.  And WordPress is complicit in this sucking.  See WordPress is very technologically advanced and, as such, they have also become an OpenID provider.  In fact, by simply setting up a blog on WordPress you are automatically provided an OpenID ID.  Mine happens to be bilsonrails.wordpress.com.</p>
<p>This is very nice of them and I appreciate their generosity.  However, what if I already have an ID elsewhere (I do.) and I don&#8217;t want to accept their ID? (I don&#8217;t.  Or I do&#8230;double negatives confuse me).  Actually accepting or not accepting is not a problem.  The problem is that I want to use my MyOpenID ID to login to WordPress and every other site.  Unfortunately, WordPress does not itself allow OpenID logins.  What?!  They probably lack the technological know-how to support such functionality, right?  Not hardly.  They are simply being smart business people.  Get everyone to use WordPress as their OpenID Provider and they have a reason to login to the site every day of their lives.  Brilliant.</p>
<p>The problem that I see is that many large web players (see AOL, Blogger, Flickr, LiveJournal, Technorati, Yahoo) are also now OpenID Providers.  And just like WordPress, they don&#8217;t &#8220;support&#8221; OpenID login on their own sites.</p>
<p>The eventual outcome of this is that OpenID becomes a technology for all the sites that nobody actually uses.  But what about all of the sites you actually use?  Sorry, you&#8217;ll need to enter your various usernames and passwords to enter those sites, but you can use one of your 47 OpenID&#8217;s to login into www.someboringuselesssite.com that you visit every 8 months.</p>
<p>Truthfully, I can&#8217;t fault any of these companies for this scheme.  It is a flaw with OpenID as I see it.  Ironic that decentralization is the culprit behind one major flaw of a technology aimed at centralization.  This leads me to my one issue with my new favorite technology, Git.  That is for another day though.</p>
<p>Thanks for nothing, WordPress!  Well, other than the great blogging software that allows me to bash you.</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/bilsonrails.wordpress.com/5/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/bilsonrails.wordpress.com/5/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bilsonrails.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bilsonrails.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bilsonrails.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bilsonrails.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bilsonrails.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bilsonrails.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bilsonrails.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bilsonrails.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bilsonrails.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bilsonrails.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bilsonrails.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bilsonrails.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bilsonrails.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bilsonrails.wordpress.com/5/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bilsonrails.wordpress.com&amp;blog=3510979&amp;post=5&amp;subd=bilsonrails&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bilsonrails.wordpress.com/2008/05/22/why-openid-is-only-sort-of-awesome/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/54b55c47f36e7b7153a404a70d97c59e?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">bilsonrails</media:title>
		</media:content>
	</item>
		<item>
		<title>Adding an Auto Increment field to a table with existing data in MySQL</title>
		<link>http://bilsonrails.wordpress.com/2008/05/22/adding-an-auto-increment-field-to-a-table-with-existing-data-in-mysql/</link>
		<comments>http://bilsonrails.wordpress.com/2008/05/22/adding-an-auto-increment-field-to-a-table-with-existing-data-in-mysql/#comments</comments>
		<pubDate>Thu, 22 May 2008 03:56:14 +0000</pubDate>
		<dc:creator>bilsonrails</dc:creator>
				<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://bilsonrails.wordpress.com/?p=3</guid>
		<description><![CDATA[I recently (like a few minutes ago) attempted to integrate a number of existing legacy MySQL tables into a Rails project. Thus, for the first time I have had to dig into migrations a bit further. Migrations make iterative database &#8230; <a href="http://bilsonrails.wordpress.com/2008/05/22/adding-an-auto-increment-field-to-a-table-with-existing-data-in-mysql/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bilsonrails.wordpress.com&amp;blog=3510979&amp;post=3&amp;subd=bilsonrails&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I recently (like a few minutes ago) attempted to integrate a number of existing legacy MySQL tables into a Rails project.  Thus, for the first time I have had to dig into migrations a bit further.  Migrations make iterative database development fairly pleasant, but I did run into a problem with a few pesky tables that didn&#8217;t already have a primary key.  These were tables that didn&#8217;t necessarily need primary keys in their past lives, but I have found that there is just no point in not &#8220;going with the flow&#8221; of Rails conventions.  So they needed primary keys.</p>
<p>Initially, I thought the following might do the trick&#8230;</p>
<pre>add_column :my_table, :id, :integer, :null =&gt; false, :auto_increment =&gt; true
</pre>
<p>However, I quickly found that the auto_increment option is not actually an option to add_column after all.  Consequently, my :id column was being created, but the value for each record was set to 0.</p>
<p>So it looks as though my only option was to resort to plain old SQL.  The following seems to have worked nicely&#8230;</p>
<pre>
def self.up
  execute "ALTER TABLE `my_table`
              ADD COLUMN `id` INT(11) AUTO_INCREMENT NOT NULL FIRST,
              ADD PRIMARY KEY(`id`)"
end
</pre>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/bilsonrails.wordpress.com/3/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/bilsonrails.wordpress.com/3/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/bilsonrails.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/bilsonrails.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/bilsonrails.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/bilsonrails.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/bilsonrails.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/bilsonrails.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/bilsonrails.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/bilsonrails.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/bilsonrails.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/bilsonrails.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/bilsonrails.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/bilsonrails.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/bilsonrails.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/bilsonrails.wordpress.com/3/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=bilsonrails.wordpress.com&amp;blog=3510979&amp;post=3&amp;subd=bilsonrails&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://bilsonrails.wordpress.com/2008/05/22/adding-an-auto-increment-field-to-a-table-with-existing-data-in-mysql/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/54b55c47f36e7b7153a404a70d97c59e?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">bilsonrails</media:title>
		</media:content>
	</item>
	</channel>
</rss>
