<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
<channel>
	<title>Terra Firma Design &amp; Consulting Blog Posts</title>
	<description>Blog posts by the staff of Terra Firma Design &amp; Consulting, an Internet design, marketing and consulting firm located in Newport, Oregon.</description>
	<copyright>Copyright Mon Nov 16 03:59:14 +0000 2009</copyright>
	<link>http://terra-firma-design.com/blog</link>
	<language>en-us</language>
	<managingEditor>contact@terra-firma-design.com (Terra Firma Design &amp; Consulting)</managingEditor>
	<webMaster>brian@terra-firma-design.com (Brian Getting)</webMaster>
	<pubDate>Wed, 04 Nov 2009 05:45:52 GMT</pubDate>
	<category>Internet Design &amp; Consulting</category>
	<lastBuildDate>Wed, 04 Nov 2009 06:34:29 GMT</lastBuildDate>
	

	<meta xmlns="http://pipes.yahoo.com" name="pipes" content="noprocess" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/tfdc" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
		<title>Chimpified = Mailchimp + Shopify</title>
		<link>http://feedproxy.google.com/~r/tfdc/~3/px5yxL2H4Mk/24-Chimpified-Mailchimp-Shopify</link>
		<description>&lt;p&gt;&lt;img alt="Brian Getting" class="avatar" height="30" src="http://gravatar.com/avatar/dc4db9c897f84b607c4c16bbbe3e60e7.png?d=http%3A%2F%2Fterra-firma-design.com%2Fimages%2Fadmin%2Favatar.png&amp;amp;r=PG&amp;amp;s=30" width="30" /&gt; &lt;p&gt;Tonight we have &lt;strong&gt;launched a new service&lt;/strong&gt; called &lt;a href="http://chimpified.com"&gt;Chimpified&lt;/a&gt; for beta testing. &lt;a href="http://chimpified.com"&gt;Chimpified&lt;/a&gt; connects a &lt;a href="http://www.shopify.com/?ref=tfdc"&gt;Shopify&lt;/a&gt; store to a &lt;a href="http://eepurl.com/ew8J"&gt;Mailchimp&lt;/a&gt; account, so that when an order is placed in the store (&lt;em&gt;and the customer has agreed to receive marketing materials&lt;/em&gt;), their email address will automatically be added to the mailing list(s) that the store owner chooses at &lt;a href="http://eepurl.com/ew8J"&gt;Mailchimp&lt;/a&gt;. There is &lt;strong&gt;no coding involved&lt;/strong&gt;, and it takes &lt;strong&gt;less than a minute&lt;/strong&gt; to set up.&lt;/p&gt;
&lt;h2&gt;Installing Chimpified&lt;/h2&gt;
&lt;p&gt;To connect your &lt;a href="http://www.shopify.com/?ref=tfdc"&gt;Shopify&lt;/a&gt; store with your &lt;a href="http://eepurl.com/ew8J"&gt;Mailchimp&lt;/a&gt; account, first visit &lt;a href="http://chimpified.com"&gt;chimpified.com&lt;/a&gt; and enter the &lt;span class="caps"&gt;URL&lt;/span&gt; of your &lt;a href="http://www.shopify.com/?ref=tfdc"&gt;Shopify&lt;/a&gt; store to sign in. The first time you sign in, you will be asked if you want to &lt;strong&gt;install Chimpified&lt;/strong&gt; to your store. After agreeing, you will be prompted to enter in your &lt;a href="http://eepurl.com/ew8J"&gt;Mailchimp&lt;/a&gt; &lt;span class="caps"&gt;API&lt;/span&gt; key for the account you want to connect your store to. Once your &lt;a href="http://eepurl.com/ew8J"&gt;Mailchimp&lt;/a&gt; &lt;span class="caps"&gt;API&lt;/span&gt; key is accepted, you will be able to select the list(s) in your &lt;a href="http://eepurl.com/ew8J"&gt;Mailchimp&lt;/a&gt; account that you want your customers added to. Finally, you&amp;#8217;ll need to set up an order notification in your &lt;a href="http://www.shopify.com/?ref=tfdc"&gt;Shopify&lt;/a&gt; store admin to notify Chimpified of new orders. That&amp;#8217;s it.&lt;/p&gt;
&lt;p&gt;There are &lt;strong&gt;instructional movies available&lt;/strong&gt; to help you with installing &lt;a href="http://chimpified.com"&gt;Chimpified&lt;/a&gt; and finding your &lt;a href="http://eepurl.com/ew8J"&gt;Mailchimp&lt;/a&gt; &lt;span class="caps"&gt;API&lt;/span&gt; key at &lt;a href="http://chimpified.com"&gt;chimpified.com&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Beta Release&lt;/h2&gt;
&lt;p&gt;For now, the &lt;strong&gt;service is free&lt;/strong&gt; since we are testing it out and getting through any bugs that we find. For the &lt;strong&gt;official release&lt;/strong&gt;, which will probably be sometime in early 2010, &lt;a href="http://chimpified.com"&gt;Chimpified&lt;/a&gt; will be available in the &lt;a href="http://apps.shopify.com"&gt;Shopify App Store&lt;/a&gt;. There will be some &lt;strong&gt;additional features&lt;/strong&gt; added as well, though nothing is set in stone, but some ideas are:&lt;/p&gt;
&lt;p&gt;- &lt;strong&gt;Update Shopify&lt;/strong&gt; if a customer unsubscribes from the emails. (Targeted for beta release)&lt;br /&gt;
- &lt;strong&gt;Add &amp;#8220;Email with Mailchimp&amp;#8221;&lt;/strong&gt; link to product pages in the Shopify admin.&lt;br /&gt;
- &lt;strong&gt;Add &amp;#8220;Email with Mailchimp&amp;#8221;&lt;/strong&gt; link to collections pages in the Shopify admin.&lt;br /&gt;
- &lt;strong&gt;&lt;span class="caps"&gt;SSL&lt;/span&gt; security&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Since the app requires resources, there will probably be &lt;strong&gt;low monthly fee&lt;/strong&gt; (&lt;em&gt;$5-10&lt;/em&gt;) once the official release launches.&lt;/p&gt;
&lt;h2&gt;Your Feedback Is Appreciated&lt;/h2&gt;
&lt;p&gt;We &lt;a href="http://chimpified.com/contact"&gt;welcome any ideas&lt;/a&gt; that our users have to offer, since they using &lt;a href="http://eepurl.com/ew8J"&gt;Mailchimp&lt;/a&gt; and &lt;a href="http://www.shopify.com/?ref=tfdc"&gt;Shopify&lt;/a&gt;, and it would be great to hear their opinions.&lt;/p&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/tfdc?a=px5yxL2H4Mk:4IcoalsOXxM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tfdc?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tfdc?a=px5yxL2H4Mk:4IcoalsOXxM:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tfdc?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
		<pubDate>Wed, 04 Nov 2009 05:45:52 GMT</pubDate>
		<dc:creator>Brian Getting</dc:creator>
		<category>Internet Design &amp; Consulting</category>
		<guid isPermaLink="false">http://terra-firma-design.com/blog/24-Chimpified-Mailchimp-Shopify</guid>
	<feedburner:origLink>http://terra-firma-design.com/blog/24-Chimpified-Mailchimp-Shopify</feedburner:origLink></item>
	<item>
		<title>Hominid Gem Version 2.0</title>
		<link>http://feedproxy.google.com/~r/tfdc/~3/Oz9KU0pz_TQ/23-Hominid-Gem-Version-2-0</link>
		<description>&lt;p&gt;&lt;img alt="Brian Getting" class="avatar" height="30" src="http://gravatar.com/avatar/dc4db9c897f84b607c4c16bbbe3e60e7.png?d=http%3A%2F%2Fterra-firma-design.com%2Fimages%2Fadmin%2Favatar.png&amp;amp;r=PG&amp;amp;s=30" width="30" /&gt; &lt;p class="intro"&gt;We&amp;#8217;ve finally gotten around to doing some updating on the Ruby gem that we maintain called &lt;a href="http://gemcutter.org/gems/hominid"&gt;Homind&lt;/a&gt;. Hominid provides a wrapper for the &lt;a href="http://www.mailchimp.com/api/1.2/"&gt;Mailchimp &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/a&gt;, allowing developers to easily integrate with Mailchimp&amp;#8217;s email marketing service. Along with updating the gem, we have also moved it to &lt;a href="http://gemcutter.org"&gt;Gemcutter&lt;/a&gt; since &lt;a href="http://github.com"&gt;Github&lt;/a&gt; is no longer hosting gems.&lt;/p&gt;
&lt;h2&gt;Installing Hominid&lt;/h2&gt;
&lt;p&gt;To install the Hominid gem, be sure that you have installed the &lt;strong&gt;Gemcutter gem,&lt;/strong&gt; or that &lt;strong&gt;Gemcutter&lt;/strong&gt; is available as one of your gem sources. The easiest way is to simply install the Gemcutter gem:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo gem install gemcutter
gem tumble&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will add Gemcutter to your list of &lt;strong&gt;gem sources&lt;/strong&gt;, and sets up to install gems from Gemcutter. To &lt;strong&gt;install the Hominid gem&lt;/strong&gt;, simply enter:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo gem install hominid&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The upgrade to version 2.0 is essentially a &lt;strong&gt;complete overhaul&lt;/strong&gt;, thanks to some fantastic help from &lt;a href="http://github.com/mikezter"&gt;Micheal Struder&lt;/a&gt;, and is no longer available as a &lt;strong&gt;Ruby on Rails plugin&lt;/strong&gt;. From here on out, &lt;strong&gt;Hominid&lt;/strong&gt; will just a pure &lt;strong&gt;Ruby gem&lt;/strong&gt;. &lt;a href="http://github.com/bgetting/hominid"&gt;Detailed documentation&lt;/a&gt; is available, but getting set up with your &lt;strong&gt;Rails application&lt;/strong&gt; requires that you set the &lt;strong&gt;gem dependency&lt;/strong&gt; in your &lt;code&gt;environment.rb&lt;/code&gt; file.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;config.gem "hominid", :version =&amp;gt; '&amp;gt;= 2.0.0', :source =&amp;gt; "http://gemcutter.org"&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It is also convenient to set up a &lt;strong&gt;configuration file&lt;/strong&gt; with your &lt;strong&gt;Mailchimp account information&lt;/strong&gt; at &lt;code&gt;config/hominid.yml&lt;/code&gt;. Refer to the Hominid documentation for more information on setting up that &lt;span class="caps"&gt;YAML&lt;/span&gt; file.&lt;/p&gt;
&lt;h2&gt;Simple Usage&lt;/h2&gt;
&lt;p&gt;There has been a &lt;strong&gt;lot of refactoring&lt;/strong&gt; with the gem, which makes usage a slight bit different than with previous versions. The gem has been changed from a &lt;strong&gt;single class&lt;/strong&gt; to a &lt;strong&gt;module&lt;/strong&gt;, and we have implemented the &lt;code&gt;Hominid::List&lt;/code&gt; class (for working with lists) and the &lt;code&gt;Hominid::Campaign&lt;/code&gt; class (for working with campaigns).&lt;/p&gt;
&lt;p&gt;To &lt;strong&gt;find a particular list&lt;/strong&gt; that you want to work with, simply use one of the &lt;strong&gt;finder methods&lt;/strong&gt; for the &lt;code&gt;List&lt;/code&gt; class:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;list = Hominid::List.find_by_name('mailing list name')&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once you&amp;#8217;ve found your list, let&amp;#8217;s say that you want to &lt;strong&gt;subscribe someone to your mailing list&lt;/strong&gt;. Use the &lt;code&gt;subscribe&lt;/code&gt; method in this instance:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;list.subscribe('my@emailaddress.com')&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or, perhaps you want to &lt;strong&gt;unsubscribe someone&lt;/strong&gt; from that email list, in which case you would use the &lt;code&gt;unsubscribe&lt;/code&gt; method:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;list.unsubscribe('my@emailaddress.com'&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, you may want to &lt;strong&gt;updated someone&amp;#8217;s information&lt;/strong&gt; in your mailing list, which is done using the @update_member) method:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;list.update_member('my@emailaddress.com', {:EMAIL =&amp;gt; 'another@emailaddress.com'}, 'html')&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can send &lt;strong&gt;other attributes&lt;/strong&gt; in the hash, such as &lt;code&gt;:FNAME&lt;/code&gt; to change other attributes of the persons subscription, aside from just their email address.&lt;/p&gt;
&lt;h2&gt;Documentation&lt;/h2&gt;
&lt;p&gt;We are doing the best that we can do document the usage of the &lt;strong&gt;Hominid gem&lt;/strong&gt;. Don&amp;#8217;t forget to visit the &lt;a href="http://github.com/bgetting/hominid"&gt;gem documentation&lt;/a&gt; to get a better idea of how to use the new gem. We are &lt;strong&gt;hoping&lt;/strong&gt; that &lt;strong&gt;more and more&lt;/strong&gt; people will get involved with helping us to improve this gem. There are quite a few &lt;strong&gt;&lt;span class="caps"&gt;API&lt;/span&gt; methods&lt;/strong&gt; that have not been implemented yet, primarily since we don&amp;#8217;t use them much. However, the gem is primed and ready to become a &lt;strong&gt;complete wrapper for the Mailchimp &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/strong&gt;, and any contributions are greatly appreciated.&lt;/p&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/tfdc?a=Oz9KU0pz_TQ:pRP_HBEsN7Y:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tfdc?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tfdc?a=Oz9KU0pz_TQ:pRP_HBEsN7Y:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tfdc?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
		<pubDate>Thu, 22 Oct 2009 18:24:14 GMT</pubDate>
		<dc:creator>Brian Getting</dc:creator>
		<category>Internet Design &amp; Consulting</category>
		<guid isPermaLink="false">http://terra-firma-design.com/blog/23-Hominid-Gem-Version-2-0</guid>
	<feedburner:origLink>http://terra-firma-design.com/blog/23-Hominid-Gem-Version-2-0</feedburner:origLink></item>
	<item>
		<title>PIV Oregon Goes Live</title>
		<link>http://feedproxy.google.com/~r/tfdc/~3/0CNRFTBXE2U/21-PIV-Oregon-Goes-Live</link>
		<description>&lt;p&gt;&lt;img alt="Brian Getting" class="avatar" height="30" src="http://gravatar.com/avatar/dc4db9c897f84b607c4c16bbbe3e60e7.png?d=http%3A%2F%2Fterra-firma-design.com%2Fimages%2Fadmin%2Favatar.png&amp;amp;r=PG&amp;amp;s=30" width="30" /&gt; &lt;p&gt;Over the weekend, in addition to enjoying the great weather here at the beach, we launched a new website for &lt;a href="http://piv-oregon.com" target="_blank" title="Public Information Verification, Oregon"&gt;Public Information Verification (&lt;span class="caps"&gt;PIV&lt;/span&gt;) Oregon&lt;/a&gt;. &lt;span class="caps"&gt;PIV&lt;/span&gt; provides background screening, pre-employment checks and other screening services. Some of the notable features of their new website are:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;b&gt;Secure Screening Submissions&lt;/b&gt; &amp;#8211; &lt;span class="caps"&gt;PIV&lt;/span&gt; deals almost exclusively with sensitive personal information, so security was on our minds during each phase of development. Every effort was made to ensure that all sensitive data is transmitted and stored securely. To communicate to their clients that their website can be trusted, we installed an Extended Validation &lt;span class="caps"&gt;SSL&lt;/span&gt; certificate, which provides 1024-bit encryption as well as triggering the &amp;#8220;green bar of trust&amp;#8221; in newer browsers.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;b&gt;Paypal Integration&lt;/b&gt; &amp;#8211; Looking for a background screening on yourself for a job or volunteer opportunity? Simply submit the request, review it for accuracy, and check out via Paypal and your request will be returned soon. It&amp;#8217;s simple. It&amp;#8217;s secure. It&amp;#8217;s being used a lot already.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;b&gt;Client Oriented&lt;/b&gt; &amp;#8211; By researching and understanding how PIV&amp;#8217;s corporate clients are using their website, we were able to design an incredibly intuitive interface to facilitate their needs. To accommodate these corporate clients, who submit many screening requests and are billed by invoice, we created an account management system that let&amp;#8217;s corporate clients upload spreadsheets of requests. Where in the past submitting 100 screening request meant filling out an online form 100 times, we&amp;#8217;ve made it so that submitting 100 or 1000 screening requests is as simple as submitting one request. So far, the response has been positive and &lt;span class="caps"&gt;PIV&lt;/span&gt; has gained a competitive edge over their competition.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;b&gt;Streamlined Administration&lt;/b&gt; &amp;#8211; Not only were we thinking about PIV&amp;#8217;s clients during development, but we thought it was important to also consider how we can make PIV&amp;#8217;s internal processes more streamlined. A simple interface allows &lt;span class="caps"&gt;PIV&lt;/span&gt; to easily find and organize screening requests, track the progress of requests, and conveniently export data for use in spreadsheets and reporting.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;b&gt;Analytics &amp;amp; Goal Tracking&lt;/b&gt; &amp;#8211; As with every website we build, PIV&amp;#8217;s new site includes an enterprise-level analytics solution that can help them understand how their clients are using their website, and make improvements. By measuring how clients are traversing through the site, and specifically tracking conversion goals, we are able to work with &lt;span class="caps"&gt;PIV&lt;/span&gt; on an on-going basis to evaluate and improve upon their website.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We are excited to see the new &lt;span class="caps"&gt;PIV&lt;/span&gt; site launched, and have been extremely impressed with the positive feedback we have received and the number of people that have been using it on the first week. We are looking forward to a long relationship in the future as we help &lt;span class="caps"&gt;PIV&lt;/span&gt; to streamline and improve their business.&lt;/p&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/tfdc?a=0CNRFTBXE2U:QaVmU0zUlR8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tfdc?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tfdc?a=0CNRFTBXE2U:QaVmU0zUlR8:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tfdc?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
		<pubDate>Thu, 23 Apr 2009 19:04:53 GMT</pubDate>
		<dc:creator>Brian Getting</dc:creator>
		<category>Internet Design &amp; Consulting</category>
		<guid isPermaLink="false">http://terra-firma-design.com/blog/21-PIV-Oregon-Goes-Live</guid>
	<feedburner:origLink>http://terra-firma-design.com/blog/21-PIV-Oregon-Goes-Live</feedburner:origLink></item>
	<item>
		<title>Installing an EV SSL Certificate on Nginx</title>
		<link>http://feedproxy.google.com/~r/tfdc/~3/_XL3a12vonI/20-Installing-an-EV-SSL-Certificate-on-Nginx</link>
		<description>&lt;p&gt;&lt;img alt="Brian Getting" class="avatar" height="30" src="http://gravatar.com/avatar/dc4db9c897f84b607c4c16bbbe3e60e7.png?d=http%3A%2F%2Fterra-firma-design.com%2Fimages%2Fadmin%2Favatar.png&amp;amp;r=PG&amp;amp;s=30" width="30" /&gt; &lt;p&gt;This is probably one of those things that everyone else knows, and I just didn&amp;#8217;t show up for class that day. I had some trouble installing an Extended Validation &lt;span class="caps"&gt;SSL&lt;/span&gt; certificate on a clients site this weekend, mostly due to my own lack of knowledge.&lt;/p&gt;
&lt;h3&gt;Generate the &lt;span class="caps"&gt;CSR&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;The goal of my task was to install an EV &lt;span class="caps"&gt;SSL&lt;/span&gt; certificate on an &lt;code&gt;nginx&lt;/code&gt; web server. I had done it before with self-signed and normal &lt;em&gt;(is that the right word?)&lt;/em&gt; certificates before. As with any &lt;span class="caps"&gt;SSL&lt;/span&gt;, the process started by generating a Certificate Signing Request (&lt;span class="caps"&gt;CSR&lt;/span&gt;) and a private key on the server. There is tons of documentation about how to do that, in my case it was accomplished using OpenSSL.&lt;/p&gt;
&lt;h3&gt;Get a Certificate from a Certifying Authority&lt;/h3&gt;
&lt;p&gt;The next step, which is common to all &lt;span class="caps"&gt;SSL&lt;/span&gt; certificates, was to send the &lt;span class="caps"&gt;CSR&lt;/span&gt; to a company that will issue a trusted &lt;span class="caps"&gt;SSL&lt;/span&gt; certificate. In my case, we chose Comodo since they had the best pricing. The process is pretty simple, and just involves verifying company information and uploading the &lt;span class="caps"&gt;CSR&lt;/span&gt; to them. However, &lt;b&gt;be sure that your company information is in order before ordering an EV &lt;span class="caps"&gt;SSL&lt;/span&gt; certificate&lt;/b&gt;- the process of getting approved is much more stringent for extended validation.&lt;/p&gt;
&lt;p&gt;I have had a few clients run into problems because their business registration didn&amp;#8217;t match their domain registration, or because their physical address differed from their registered address. All of this can be resolved with a letter from a lawyer or an accountant (be sure they are a registered &lt;span class="caps"&gt;CPA&lt;/span&gt;).&lt;/p&gt;
&lt;h3&gt;Concatenating Multiple &lt;span class="caps"&gt;CRT&lt;/span&gt; Files&lt;/h3&gt;
&lt;p&gt;What came back from Comodo, in my case, was a &lt;span class="caps"&gt;ZIP&lt;/span&gt; file containing about 5 &lt;span class="caps"&gt;CRT&lt;/span&gt; files. The next step is to put them all together into one file so that nginx can use them. This is easy enough, although it turns out that you should do it in a particular order. Comodo had sent me the following files:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;AddTrustExternalCARoot.crt&lt;/li&gt;
	&lt;li&gt;ComodoEVSGCCA.crt&lt;/li&gt;
	&lt;li&gt;ComodoUTNSGCCA.crt&lt;/li&gt;
	&lt;li&gt;UTNAddTrustSGCCA.crt&lt;/li&gt;
	&lt;li&gt;sample-domain-name_com.crt&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To put them all together into one file, you simply type the following into a terminal:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cat  AddTrustExternalCARoot.crt ComodoEVSGCCA.crt ComodoUTNSGCCA.crt UTNAddTrustSGCCA.crt sample-domain-name_com.crt &amp;gt;&amp;gt; ssl-bundle.crt&lt;/pre&gt;&lt;p&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Of course, you will have a different name for your domain &lt;span class="caps"&gt;CRT&lt;/span&gt; file, and will probably want to name the output file for your domain. So if your domain is &lt;code&gt;mysite.com&lt;/code&gt;, you would call the output file (the file name after the &amp;#8220;&amp;gt;&amp;gt;&amp;#8221;) &lt;code&gt;mysite_com.crt&lt;/code&gt;. It probably doesn&amp;#8217;t matter, but it seems like a good idea.&lt;/p&gt;
&lt;p&gt;The output file will basically just be a text file with all the certificates put together, so you could just copy and paste all the files (in the right order) into another file and save it with the right name. Whatever method you use, you&amp;#8217;ll want to open this file up and copy it&amp;#8217;s contents into a new file on the web server, probably at:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/etc/ssl/certs/ssl-bundle.crt&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You could also &lt;code&gt;scp&lt;/code&gt; the file into place, but for me it&amp;#8217;s just easier to copy and paste it. Save this file on the web server and we are almost ready.&lt;/p&gt;
&lt;h3&gt;Configuring Your Nginx Virtual Host&lt;/h3&gt;
&lt;p&gt;The last thing that we needed to do was to make some changes in our virtual host file. Basically, just like any other &lt;span class="caps"&gt;SSL&lt;/span&gt; on &lt;code&gt;nginx&lt;/code&gt;, you want to point to the file that contains all the certificates that we received from Comodo:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;server {
  listen  443;

  ssl  on;
  ssl_certificate  /etc/ssl/certs/mysite_com.crt;
  ssl_certificate_key  /etc/ssl/private/mysite.key;

  server_name mysite.com;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Obviously, you want to be sure that you put your key &lt;em&gt;(named &lt;code&gt;mysite.key&lt;/code&gt; in the above example)&lt;/em&gt; into the correct &lt;code&gt;private&lt;/code&gt; directory. From here, restart &lt;code&gt;nginx&lt;/code&gt; and the certificate should be fine.&lt;/p&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/tfdc?a=_XL3a12vonI:Kim-bmqhvyU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tfdc?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tfdc?a=_XL3a12vonI:Kim-bmqhvyU:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tfdc?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
		<pubDate>Mon, 20 Apr 2009 21:12:38 GMT</pubDate>
		<dc:creator>Brian Getting</dc:creator>
		<category>Internet Design &amp; Consulting</category>
		<guid isPermaLink="false">http://terra-firma-design.com/blog/20-Installing-an-EV-SSL-Certificate-on-Nginx</guid>
	<feedburner:origLink>http://terra-firma-design.com/blog/20-Installing-an-EV-SSL-Certificate-on-Nginx</feedburner:origLink></item>
	<item>
		<title>Real Estate on Rails (Working with RETS Data)</title>
		<link>http://feedproxy.google.com/~r/tfdc/~3/9c-0VtH-_WI/19-Real-Estate-on-Rails-Working-with-RETS-Data-</link>
		<description>&lt;p&gt;&lt;img alt="Brian Getting" class="avatar" height="30" src="http://gravatar.com/avatar/dc4db9c897f84b607c4c16bbbe3e60e7.png?d=http%3A%2F%2Fterra-firma-design.com%2Fimages%2Fadmin%2Favatar.png&amp;amp;r=PG&amp;amp;s=30" width="30" /&gt; &lt;p&gt;In the past, I have worked on a lot of real estate websites. After having taken a few year break from doing any realty-related web development, which was a welcome break, I have recently started working on another real estate site. My hope going into this was that working with Rails would make the job much easier, and that things had improved somewhat since my last experiences. I was right, and the combination of Rails and &lt;span class="caps"&gt;RETS&lt;/span&gt; data has actually made the process almost fun, relative to the past.&lt;/p&gt;
&lt;h3&gt;&lt;span class="caps"&gt;IDX&lt;/span&gt; or &lt;span class="caps"&gt;RETS&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;The first order of business was to figure out the best way to get at the &lt;span class="caps"&gt;MLS&lt;/span&gt; (Multiple Listing Service) data that I wanted. In the past I had used &lt;span class="caps"&gt;IDX&lt;/span&gt; feeds, which translates to &lt;span class="caps"&gt;FTP&lt;/span&gt; access to a whole bunch of property data and images. Each day, someone or something would need to access this &lt;span class="caps"&gt;FTP&lt;/span&gt; server, download all the new files and update the website. It always seemed like there was a better way, and it turns out that there is.&lt;/p&gt;
&lt;p&gt;Rather than an &lt;span class="caps"&gt;IDX&lt;/span&gt; feed, I have been working with &lt;span class="caps"&gt;RETS&lt;/span&gt; data, or Real Estate Transaction Standard data, which basically means that (finally) the &lt;span class="caps"&gt;MLS&lt;/span&gt; data is available as &lt;span class="caps"&gt;XML&lt;/span&gt; data via a web service. To me this is much more attractive, and seems to be a much more efficient way of updating &lt;span class="caps"&gt;MLS&lt;/span&gt; data.&lt;/p&gt;
&lt;h3&gt;&lt;span class="caps"&gt;RETS&lt;/span&gt; for Ruby Gem&lt;/h3&gt;
&lt;p&gt;Of course, the first thing I did was check to see if anyone had created a Ruby gem or Rails plugin for accessing and handling &lt;span class="caps"&gt;RETS&lt;/span&gt; data, and it turns out that someone has. The &lt;a href="http://rubyforge.org/projects/rets4r/"&gt;rets4r gem&lt;/a&gt; is what I have been experimenting with, and so far it has been extremely useful. I would be lying if I said I wasn&amp;#8217;t tempted to rewrite the thing, and probably will in the future sometime, however it provides me with the functionality that I need to access the &lt;span class="caps"&gt;RETS&lt;/span&gt; data that we have access to and deal with that data as Ruby objects, which is nice. Of course, a large part of working with &lt;span class="caps"&gt;RETS&lt;/span&gt; is understanding how the data is formated and developing a strategy for keeping your site updated. We&amp;#8217;ll start by requiring the &lt;code&gt;rets4r&lt;/code&gt; gem in our Rails application:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;config.gem "rets4r", :version =&amp;gt; '&amp;gt;=0.8.5'&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will go in your &lt;code&gt;config/environment.rb&lt;/code&gt; file.&lt;/p&gt;
&lt;h3&gt;The Daily Download&lt;/h3&gt;
&lt;p&gt;Even though &lt;span class="caps"&gt;RETS&lt;/span&gt; provides a web service that could probably be queried directly, it is still a much better idea to pull the &lt;span class="caps"&gt;MLS&lt;/span&gt; data down into a local database and go from there. That being said, I needed to come up with a strategy where all the properties that need to be displayed are pulled down originally (only once) and then each day check the &lt;span class="caps"&gt;RETS&lt;/span&gt; server for updates and deletions. These are essentially the same operations, in that the first time we pull down data we will be asking the &lt;span class="caps"&gt;RETS&lt;/span&gt; server for all properties that we have access to, and the daily updates will just ask for properties that have been updated since our last request. Let&amp;#8217;s take a look at how we do that using the &lt;code&gt;rets4r&lt;/code&gt; gem:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;client = RETS4R::Client.new('http://retsprovider.com/rets/')
client.login('username', 'password') do |success|
  if success
    client.search('Property', 'A', "(FIELD=#{24.hours.ago.strftime('%Y-%m-%dT%T')}+)", {'Format' =&amp;gt; 'COMPACT-DECODED'}) do |result|
      result.data.each do |row|
         property = Property.find_or_create_by_mls(row["MLS"])
         property.price = row["PRICE"]
         property.sqft = row["SQFT"]
         ...
         property.save
      end
   end
  client.logout
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this (very simplified) example, we are logging in to the &lt;span class="caps"&gt;RETS&lt;/span&gt; server, and running a search for all properties that have been modified in the last 24 hours. You will need to check your own &lt;span class="caps"&gt;MLS&lt;/span&gt; data provider to find out exactly what the various fields are, but I am using examples here. One thing to note is that I am searching the &lt;code&gt;Property&lt;/code&gt; resource on the &lt;span class="caps"&gt;RETS&lt;/span&gt; server, and within that resource I am specifically searching within the &lt;code&gt;A&lt;/code&gt; class of properties. In my case this happens to be residential properties, but you will want to do this for each resource class that you want to update (perfect place for a loop). Additionally, you will want to figure out what to replace &lt;code&gt;FIELD&lt;/code&gt; with so that you are querying the &lt;code&gt;last modified date&lt;/code&gt; field for your particular &lt;span class="caps"&gt;RETS&lt;/span&gt; server. Also, notice that I am adding the &lt;code&gt;Format&lt;/code&gt; option to my search, and asking for the results to be returned in &lt;code&gt;COMPACT-DECODED&lt;/code&gt; format. For my particular provider, this means that all lookup values for particular fields will be shown, rather than the obscure lookup codes that might otherwise be there. This is nice since dealing with lookup values is not really central to what I am trying to do, so that is handy. The rest is just about assigning the correct values to the correct attributes in my &lt;code&gt;Property&lt;/code&gt; model, and we are off.&lt;/p&gt;
&lt;p&gt;One thing that is worth mentioning is that not all the resource classes have the same fields. For example the field denoting the street surface type for a residential property might be called &lt;code&gt;FEAT00001&lt;/code&gt;. However, the same street surface type field for a commercial property might be &lt;code&gt;FEAT00003&lt;/code&gt;. It&amp;#8217;s important to track down each field that you want for each resource class. It is done this way to account for different values and flexibility between property types, but can be a pain. In my case, there are about 15 fields that I want data for in my &lt;code&gt;Property&lt;/code&gt; model that have to be mapped differently depending on the resource class. It&amp;#8217;s a fact of life.&lt;/p&gt;
&lt;h3&gt;Getting at Images&lt;/h3&gt;
&lt;p&gt;So the script above, if run daily, will check the &lt;span class="caps"&gt;RETS&lt;/span&gt; server for any properties that have been modified in the last 24 hours and pull them down to our local database. Not a bad start. The next thing we need this script to do is to download the images for each of the properties. Typically there will be a field for &lt;code&gt;photos_count&lt;/code&gt; or something along those lines so that you can tell for each property if it has associated photos. Using that field, we can add the following to our script, just before the &lt;code&gt;property.save&lt;/code&gt; line:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if row["PHOTOS_COUNT"].to_i &amp;gt; 0
  photo_index = 1
  row["PHOTOS_COUNT"].to_i.times do
    client.get_object('Property', 'Photo', "#{row["ID"]}:#{row_index}, 0) do |photo|
      handle_object(photo)
    end
    photo_index = photo_index + 1
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This one is pretty basic as well, and you will need to write your own &lt;code&gt;handle_object&lt;/code&gt; method depending on what you want to do with the images once they are downloaded. There is a way of pulling down all the images in a single request, although I could not coax the &lt;code&gt;rets4r&lt;/code&gt; gem to play nicely with that one.&lt;/p&gt;
&lt;h3&gt;Deleting properties&lt;/h3&gt;
&lt;p&gt;One thing that was interesting with the &lt;span class="caps"&gt;RETS&lt;/span&gt; feed I have access to is that the property status is not really used. In some cases it is there, but it cannot be used to see if a property has been deleted. Since our feed only spits out properties that we have access to (which does not include deleted records), we have to come up with some way to delete properties that have been removed.&lt;/p&gt;
&lt;p&gt;Interestingly enough, the company that provides my &lt;span class="caps"&gt;RETS&lt;/span&gt; feed has a solution, although I can&amp;#8217;t help but wonder if there isn&amp;#8217;t a cleaner way. They suggest that each day as part of the daily update, we query the &lt;span class="caps"&gt;RETS&lt;/span&gt; server for all the properties that we should be displaying,  grabbing only one field (like the &lt;code&gt;id&lt;/code&gt; or &lt;code&gt;mls&lt;/code&gt; number) to make the query more efficient. We then compare that to the contents of our local database, and any records that &lt;em&gt;we&lt;/em&gt; have but do not appear in the daily list need to be deleted. Backwards, huh? Here&amp;#8217;s what it looks like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;client.search('Property', 'A', "(FIELD=1950-01-01T00:00:00+)", {"Select" =&amp;gt; "MLS_NO"}) do |result|
  local_properties = Property.find(:all, :select =&amp;gt; 'mls')
  local_properties.each do |property|
    property.destroy unless result.data.index(property.mls)
    # Don't forget to delete all images too.
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Again, depending on how you are storing or managing your images, you will want to be sure and delete them when you delete an associated property. However, our loop simply grabs a list of all the &lt;code&gt;MLS&lt;/code&gt; numbers that we should have in our local database. Then we loop through all of our property records, deleting any that have &lt;span class="caps"&gt;MLS&lt;/span&gt; numbers that aren&amp;#8217;t in our list. Easy enough, although something about it seems ugly to me.&lt;/p&gt;
&lt;h3&gt;Development As Usual&lt;/h3&gt;
&lt;p&gt;Now that the challenging part is over, we can run our script and watch as properties fill our database and images come down as well. From here, developing a real estate site becomes like developing any other data-driven site. Rather than spending our time worrying about how to deal with &lt;span class="caps"&gt;MLS&lt;/span&gt; data, we can spend our time developing a great application.&lt;/p&gt;
&lt;p&gt;From my standpoint, the hassle of dealing with &lt;span class="caps"&gt;MLS&lt;/span&gt; providers, and the intimidation of daily &lt;span class="caps"&gt;MLS&lt;/span&gt; updates are now removed from the equation, which means that real estate sites are no longer something to be feared. Although, that is from a technical point of view. You still need to deal with realtors to build their sites, and I&amp;#8217;m not sure I&amp;#8217;ve overcome that one yet.&lt;/p&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/tfdc?a=9c-0VtH-_WI:buERmNU5leI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tfdc?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tfdc?a=9c-0VtH-_WI:buERmNU5leI:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tfdc?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
		<pubDate>Wed, 15 Apr 2009 16:30:23 GMT</pubDate>
		<dc:creator>Brian Getting</dc:creator>
		<category>Internet Design &amp; Consulting</category>
		<guid isPermaLink="false">http://terra-firma-design.com/blog/19-Real-Estate-on-Rails-Working-with-RETS-Data-</guid>
	<feedburner:origLink>http://terra-firma-design.com/blog/19-Real-Estate-on-Rails-Working-with-RETS-Data-</feedburner:origLink></item>
	<item>
		<title>Chuck Victory Goes Live!</title>
		<link>http://feedproxy.google.com/~r/tfdc/~3/iMvJI-ovK0g/18-Chuck-Victory-Goes-Live-</link>
		<description>&lt;p&gt;&lt;img alt="Brian Getting" class="avatar" height="30" src="http://gravatar.com/avatar/dc4db9c897f84b607c4c16bbbe3e60e7.png?d=http%3A%2F%2Fterra-firma-design.com%2Fimages%2Fadmin%2Favatar.png&amp;amp;r=PG&amp;amp;s=30" width="30" /&gt; &lt;p&gt;We&amp;#8217;ve just launched a new e-commerce website for &lt;a href="http://chuckvictory.com" title="Chuck Victory" target="_blank"&gt;Newport, Oregon photographic artist Chuck Victory&lt;/a&gt;. Chuck has a background in advertising and photography, and a serious interest in wine and art. While a simple website, there are a few features that we feel should be mentioned:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;b&gt;Content Management&lt;/b&gt; &amp;#8211; Chuck&amp;#8217;s website has one of our custom content management systems that allow Chuck to control the aspects of his website that he needs to, without jeopardizing the integrity of his site. Chuck can easily create new galleries and manage his photos. In addition, the website offers Chuck the ability to add any number of available sizes that he wants to make available. In fact, I intend to do a blog post here soon about how that was accomplished, as other developers might find such a system handy since so many products can be available in multiple sizes, or colors&amp;#8230;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;b&gt;Paypal Integration&lt;/b&gt;  &amp;#8211; As a newcomer to e-commerce, we worked with Chuck to determine that Paypal integration was the most economical way for him to start selling his photos online. In our case, Chuck&amp;#8217;s site uses Paypal for it&amp;#8217;s checkout process, and is securely integrated. Rather than simple posting variables to Paypal, the website encrypts all shopping cart data prior to being sent to Paypal, which prevents anyone from tampering with the order data.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;b&gt;Image Protection&lt;/b&gt; &amp;#8211; While there is no way to fully protect images on the web, we wanted to at least make it harder for someone to try and get at the images. Of course, nothing can stop a screenshot, or even someone familiar with &lt;span class="caps"&gt;HTML&lt;/span&gt; from grabbing images, as that is the nature of the web. However, we composed a solution that removes the ability to &amp;#8216;right-click&amp;#8217; on an image, or drag-and-drop it to your desktop to play with. Nothing groundbreaking here, but a feature worth noting.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We are excited that Chuck&amp;#8217;s site is completed and launched, and as the bugs are worked out will be excited to see the response. For our part, working with Chuck has been an absolute pleasure, as he is not only a creative fellow but one that understands what he wants. Visit his website, and check out his photographic art&amp;#8230;&lt;/p&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/tfdc?a=iMvJI-ovK0g:cen7WxIaLyA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tfdc?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tfdc?a=iMvJI-ovK0g:cen7WxIaLyA:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tfdc?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
		<pubDate>Mon, 13 Apr 2009 16:22:45 GMT</pubDate>
		<dc:creator>Brian Getting</dc:creator>
		<category>Internet Design &amp; Consulting</category>
		<guid isPermaLink="false">http://terra-firma-design.com/blog/18-Chuck-Victory-Goes-Live-</guid>
	<feedburner:origLink>http://terra-firma-design.com/blog/18-Chuck-Victory-Goes-Live-</feedburner:origLink></item>
	<item>
		<title>Ruby Gem and Rails Plugin for Mailchimp</title>
		<link>http://feedproxy.google.com/~r/tfdc/~3/FfX45Z5NXV0/17-Ruby-Gem-and-Rails-Plugin-for-Mailchimp</link>
		<description>&lt;p&gt;&lt;img alt="Brian Getting" class="avatar" height="30" src="http://gravatar.com/avatar/dc4db9c897f84b607c4c16bbbe3e60e7.png?d=http%3A%2F%2Fterra-firma-design.com%2Fimages%2Fadmin%2Favatar.png&amp;amp;r=PG&amp;amp;s=30" width="30" /&gt; &lt;p&gt;Recently, the limitations of the &lt;a href="http://github.com/bgetting/acts_as_mailchimp/tree/master"&gt;acts_as_mailchimp&lt;/a&gt; plugin that I threw together a while back have been staring me in the face. The more that I work with Mailchimp, and the more that they improve their &lt;span class="caps"&gt;API&lt;/span&gt;, the more I realized that it was time to do something about it.&lt;/p&gt;
&lt;h3&gt;The Hominid Gem&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://github.com/bgetting/hominid/tree/master"&gt;Hominid&lt;/a&gt; is a gem that wraps the &lt;a href="http://www.mailchimp.com/api/1.1/"&gt;Mailchimp &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/a&gt; so that you can easily work with it in Ruby or Rails. You can install Hominid as a plugin by typing:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;script/plugin install git://github.com/bgetting/hominid.git&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or, you can install it as a gem by including the following in your &lt;code&gt;environment.rb&lt;/code&gt; file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;config.gem "bgetting-hominid", :lib =&amp;gt; 'hominid', :source =&amp;gt; "http://gems.github.com"&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you use Hominid as a gem, be sure to create a &lt;span class="caps"&gt;YAML&lt;/span&gt; file at &lt;code&gt;config/hominid.yml&lt;/code&gt; to hold your Mailchimp login information for each environment. From there usage is pretty simple. For example, to add someone to a mailing list you might use:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
h = Hominid.new
list = h.lists.find {|list| list["name"] == "My Mailing List" }
h.subscribe(list["id"], 'bob@smith.com')
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We first create a new Hominid object, which will log in to Mailchimp using your account information from the &lt;code&gt;hominid.yml&lt;/code&gt; file. From there, we use the &lt;code&gt;lists&lt;/code&gt; method to return all the mailing lists at Mailchimp for this account, and pull out the one with the &lt;code&gt;name&lt;/code&gt; that we are looking for. We use that list&amp;#8217;s &lt;code&gt;id&lt;/code&gt; to subscribe someone to the list. Pretty simple.&lt;/p&gt;
&lt;p&gt;There are also methods for dealing with campaigns and other things. One particular method that is worth noting is the &lt;code&gt;convert_css_to_inline&lt;/code&gt; method, which uses the Mailchimp &lt;span class="caps"&gt;API&lt;/span&gt; to convert any &lt;span class="caps"&gt;CSS&lt;/span&gt; declarations in an &lt;span class="caps"&gt;HTML&lt;/span&gt; document into inline styles for use in emails. That thing comes in handy!&lt;/p&gt;
&lt;p&gt;I haven&amp;#8217;t yet had time to write tests for this gem. I would love any input that anyone has with regard to the best way to test this, and how to write the tests. Hopefully the lack of adequate tests doesn&amp;#8217;t wreck anyone&amp;#8217;s day.&lt;/p&gt;
&lt;h3&gt;Acts_As_Mailchimp Plugin&lt;/h3&gt;
&lt;p&gt;The &lt;a href="http://github.com/bgetting/acts_as_mailchimp/tree/master"&gt;Acts_As_Maichimp&lt;/a&gt; plugin then needed to be updated. I decided that since Hominid wraps nearly all the functionality of the plugin, I would just make it dependent on Hominid. So one you have Hominid installed, you can install &lt;code&gt;acts_as_mailchimp&lt;/code&gt; by typing:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;script/plugin install git://github.com/bgetting/acts_as_mailchimp.git&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now add the following to your model so that you can add, remove and update a member of a Mailchimp mailing list:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;acts_as_mailchimp&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For the most part, the plugin now just wraps the process of finding the list ID of the list you want to work with, and the connecting to Mailchimp using Hominid.&lt;/p&gt;
&lt;p&gt;Someone also pointed out the lack of tests on this plugin. Again, I apologize for not taking the time, and would welcome any suggestions for what would make effective tests for such a plugin.&lt;/p&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/tfdc?a=FfX45Z5NXV0:LFH1AsCyrps:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tfdc?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tfdc?a=FfX45Z5NXV0:LFH1AsCyrps:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tfdc?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
		<pubDate>Wed, 25 Mar 2009 20:02:32 GMT</pubDate>
		<dc:creator>Brian Getting</dc:creator>
		<category>Internet Design &amp; Consulting</category>
		<guid isPermaLink="false">http://terra-firma-design.com/blog/17-Ruby-Gem-and-Rails-Plugin-for-Mailchimp</guid>
	<feedburner:origLink>http://terra-firma-design.com/blog/17-Ruby-Gem-and-Rails-Plugin-for-Mailchimp</feedburner:origLink></item>
</channel>
</rss>
