<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.integralimpressions.com/~d/styles/rss2full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.integralimpressions.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><rss xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:media="http://search.yahoo.com/mrss" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
<channel>
<title>Integral Thoughts</title>
<link>http://feeds.integralimpressions.com/integralthoughts/behind-the-scenes</link>
<description />
<ttl>60</ttl>
<generator>http://www.sporkmonger.com/projects/feedtools/</generator>
<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.integralimpressions.com/integralthoughts/code" type="application/rss+xml" /><item>
<title>Initial Thoughts on Google App Engine</title>
<link>http://feeds.integralimpressions.com/~r/integralthoughts/code/~3/266369635/initial-thoughts-on-google-app-engine</link>
<content:encoded><![CDATA[
<p>It&#8217;s real, <a href="http://code.google.com/appengine">Google App Engine</a> has been released. I&#8217;ve downloaded the <span class="caps">SDK</span> and worked my way though the <em>Getting Started</em> guide, and I&#8217;m excited. Very excited. <span class="caps">GAE</span> isn&#8217;t just <a href="http://aws.amazon.com/ec2">a virtual server to deploy your application on</a>, it&#8217;s an entire <em>platform</em>. <span class="caps">GAE</span> includes a <a href="http://code.google.com/appengine/docs/datastore/">DataStore <span class="caps">API</span></a> that makes <a href="http://www.amazon.com/SimpleDB-AWS-Service-Pricing/b/ref=sc_fe_l_2?ie=UTF8&#38;node=342335011&#38;no=3440661&#38;me=A36L942TSJ2AJA">SimpleDB</a> look like a hobby project, <a href="http://code.google.com/appengine/docs/users/">Users <span class="caps">API</span></a> (Google&#8217;s answer to OpenID) and more.</p>
<p><span class="caps">GAE</span> comes complete with auto-app-versioning, your choice of runtime environment (Python only for now, but they say there&#8217;s more coming) and automatic scaling. In fact, <span class="caps">GAE</span> lets us forget all about scaling and reliability: it just works. And that&#8217;s the future: complete platforms, not ad-hoc components. Google has definitely hit the nail on the head with <span class="caps">GAE</span> and I can&#8217;t wait until it&#8217;s out of beta. Stay tuned for more on <span class="caps">GAE</span> soon.</p>
<img src="http://feeds.integralimpressions.com/~r/integralthoughts/code/~4/266369635" height="1" width="1"/>]]></content:encoded>
<pubDate>Tue, 08 Apr 2008 05:52:00 -0700</pubDate>
<guid isPermaLink="false">http://integralimpressions.com/blog/initial-thoughts-on-google-app-engine</guid>
<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=integralthoughts/code&amp;itemurl=http%3A%2F%2Fintegralimpressions.com%2Fblog%2Finitial-thoughts-on-google-app-engine</feedburner:awareness><feedburner:origLink>http://integralimpressions.com/blog/initial-thoughts-on-google-app-engine</feedburner:origLink></item>
<item>
<title>OpenVZ: When It Makes More Sense</title>
<link>http://feeds.integralimpressions.com/~r/integralthoughts/code/~3/197824402/openvz-when-it-makes-more-sense</link>
<content:encoded><![CDATA[
<p>I&#8217;ve used Xen a lot in the past, and I really like it. It&#8217;s about as close as you can come to having a pseudo-dedicated server: your own kernel, complete isolation, guaranteed non over-committed resources. And, it&#8217;s probably the best choice if you&#8217;re running an unmanaged hosting environment full of strangers. At <a href="http://www.integralimpressions.com">Integral Impressions</a> we evaluated both Xen and <a href="http://openvz.org/">OpenVZ</a> for our <a href="http://integralimpressions.com/services/managed-rails-hosting">managed hosting solution</a>. Hands down, <a href="http://openvz.org/">OpenVZ</a> made the most sense for us. Here&#8217;s a few reasons why:</p>
<ul>
<li><strong>Negligible overhead.</strong> All <a href="http://openvz.org/">OpenVZ</a> virtual servers share the same kernel. This makes for such little overhead that it goes unnoticed.</li>
<li><strong>Flexible resource allocation.</strong> We can share resources among our virtual servers much more flexibly than we could with Xen. For example, our <a href="http://integralimpressions.com/services/managed-rails-hosting">Level 3</a> hosting plan has 1GB <span class="caps">RAM</span>. But we don&#8217;t really cap it at 1GB, that&#8217;s just what we guarantee. In reality, we&#8217;re fine with a customer&#8217;s virtual server temporarily using more than that. If it becomes permanent, we&#8217;ll just ask them to upgrade. Our servers have a ton of <span class="caps">RAM</span>, and there&#8217;s always GBs to spare, so no sense in letting them go to waste. If we were using Xen, we&#8217;d have to cap the customer at 1GB and they&#8217;d need to upgrade to increase that, even if only temporarily. The same deal applies to <span class="caps">CPU</span> and disk space.</li>
<li><strong>Extremely quick upgrades and downgrades.</strong> We can upgrade or downgrade a customer&#8217;s resources in a matter of <em>seconds</em> and usually with <em>zero</em> downtime. How&#8217;s that for cool. Even disk quota&#8217;s can be altered in seconds &#8211; something that&#8217;s usually a painful operation with Xen.</li>
<li><strong>Stability.</strong> <a href="http://openvz.org/">OpenVZ</a> is the core of a commercial product, <a href="http://www.swsoft.com/products/virtuozzo/">Virtuozzo</a>. <a href="http://www.swsoft.com/products/virtuozzo/">Virtuozzo</a> has been through several years of production usage, and it&#8217;s rock-solid. We&#8217;ve not had a single problem with <a href="http://www.openvz.org">OpenVZ</a>. What&#8217;s more, should we ever need commercial support we can always contact <a href="http://www.swsoft.com/products/virtuozzo/">Virtuozzo</a>.</li>
<li><strong>Performance.</strong> I can&#8217;t provide you with any benchmarks right now, but compared to some of the Xen solutions we&#8217;ve used in the past, <a href="http://openvz.org/">OpenVZ</a> seems a <em>lot</em> faster. Read into that what you will, but that&#8217;s our experience.</li>
</ul>
<p>If you&#8217;ve also used both OpenVZ and Xen, I&#8217;d love to hear your experiences. What made the most sense for you? Why?</p>
<img src="http://feeds.integralimpressions.com/~r/integralthoughts/code/~4/197824402" height="1" width="1"/>]]></content:encoded>
<pubDate>Sun, 09 Dec 2007 18:20:00 -0800</pubDate>
<guid isPermaLink="false">http://integralimpressions.com/blog/openvz-when-it-makes-more-sense</guid>
<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=integralthoughts/code&amp;itemurl=http%3A%2F%2Fintegralimpressions.com%2Fblog%2Fopenvz-when-it-makes-more-sense</feedburner:awareness><feedburner:origLink>http://integralimpressions.com/blog/openvz-when-it-makes-more-sense</feedburner:origLink></item>
<item>
<title>New Feature: Bayesian Spam Filter for Ticketish</title>
<link>http://feeds.integralimpressions.com/~r/integralthoughts/code/~3/194920008/new-feature-bayesian-spam-filter-for-ticketish</link>
<content:encoded><![CDATA[
<p>Some time ago we implemented a basic spam filter for <a href="http://ticketi.sh">Ticketish</a>. Nevertheless, those pesky spammers continued to push through their mail. No more. We&#8217;ve implemented a full-blown <a href="http://en.wikipedia.org/wiki/Bayesian_spam_filtering">bayesian spam filter</a> for all <a href="http://ticketi.sh">Ticketish</a> accounts. If you&#8217;ve never heard of bayesian filtering, a great place to start is Paul Graham&#8217;s article <a href="http://www.paulgraham.com/spam.html">A Plan for Spam</a>.</p>
<p>To get the most out of the filter you need to train it. When using <a href="http://ticketi.sh">Ticketish</a>, you&#8217;ll see some new items in the drop-down for managing multiple tickets: <em>Spam</em> and <em>Train Not Spam</em>. Start by selecting a whole group of tickets that aren&#8217;t spam, and train them so. Then, make sure you mark all spam tickets as spam instead of just deleting them. Over time, <a href="http://ticketi.sh">Ticketish</a> will become very accurate at determining what&#8217;s spam and what&#8217;s ham.</p>
<p>Every <a href="http://ticketi.sh">Ticketish</a> account is trained separately. This is important because what&#8217;s spam for some might be ham for others. All accounts start with a clean slate, so it&#8217;s up to you to train appropriately. We&#8217;ve developed the spam filter as a <span class="caps">RES</span>Tful web service, so expect to see it pop up in our other applications as well.</p>
<img src="http://feeds.integralimpressions.com/~r/integralthoughts/code/~4/194920008" height="1" width="1"/>]]></content:encoded>
<pubDate>Tue, 04 Dec 2007 04:00:00 -0800</pubDate>
<guid isPermaLink="false">http://integralimpressions.com/blog/new-feature-bayesian-spam-filter-for-ticketish</guid>
<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=integralthoughts/code&amp;itemurl=http%3A%2F%2Fintegralimpressions.com%2Fblog%2Fnew-feature-bayesian-spam-filter-for-ticketish</feedburner:awareness><feedburner:origLink>http://integralimpressions.com/blog/new-feature-bayesian-spam-filter-for-ticketish</feedburner:origLink></item>
<item>
<title>Hallelujah!</title>
<link>http://feeds.integralimpressions.com/~r/integralthoughts/code/~3/188750266/hallelujah</link>
<content:encoded><![CDATA[
<p>Anyone that reads blogs from the Rails community has probably already heard about <a href="http://god.rubyforge.org/">God</a>. No, not the deity in the sky, but an excellent monitoring application that watches your processes and keeps them running. I&#8217;ve mostly seen it used for taming mongrel but it can be used to monitor any process.</p>
<p>We&#8217;re running God for all our <a href="http://integralimpressions.com/services/managed-rails-hosting">managed hosting</a> clients to make sure their mongrels don&#8217;t pass out from exhaustion. Here&#8217;s our init script and a sample global config for your enjoyment.</p>
<ul>
<li><a href="http://pastie.caboo.se/110483">/etc/init.d/god</a></li>
<li><a href="http://pastie.caboo.se/110408">/etc/god.conf</a></li>
</ul>
<p>The God configuration file should be self explanatory. It&#8217;s just Ruby code, nothing magic going on there. I&#8217;ve just wrapped the core God.watch code around some loops to enable support for monitoring an unlimited number of applications. One small note about the init.d script: it first launches God, and then loads the config file via the &#8216;god load&#8217; command. I&#8217;m aware that you can send god the -c parameter when launching it, but I&#8217;ve found that sometimes (seemingly randomly) that won&#8217;t load the config.</p>
<p>The init.d script should work fine on any <span class="caps">RHEL</span>/CentOS system. Once you add the file to /etc/init.d/god just do:</p>
<code lang="ruby">
chmod +x /etc/init.d/god
chkconfig --add god
chkconfig --level 345 god on
/etc/init.d/god start
</code>
<p>Now you&#8217;re good to go. Let those misbehaving K-9 devils do their best &#8211; they&#8217;re no match for God.</p>
<img src="http://feeds.integralimpressions.com/~r/integralthoughts/code/~4/188750266" height="1" width="1"/>]]></content:encoded>
<pubDate>Wed, 24 Oct 2007 08:06:00 -0700</pubDate>
<guid isPermaLink="false">http://integralimpressions.com/blog/hallelujah</guid>
<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=integralthoughts/code&amp;itemurl=http%3A%2F%2Fintegralimpressions.com%2Fblog%2Fhallelujah</feedburner:awareness><feedburner:origLink>http://integralimpressions.com/blog/hallelujah</feedburner:origLink></item>
<item>
<title>Ticketish Email Integration</title>
<link>http://feeds.integralimpressions.com/~r/integralthoughts/code/~3/188750267/ticketish-email-integration</link>
<content:encoded><![CDATA[
<p>One of the central features of <a href="http://www.ticketi.sh">Ticketish</a> is email integration. Users can create new tickets by email and add comments to tickets by replying to any email that has the ticket id in the subject. I&#8217;ll show how this integration is achieved, from setting up Postfix to writing the Ticket and Comment handlers.</p>
<p>Each project in <a href="http://www.ticketi.sh">Ticketish</a> receives its own email address. The email address is in the format &#8220;[project.permalink]@[account.subdomain].ticketi.sh&#8221;. Sending an email to the project&#8217;s email address creates a new ticket. Once a new ticket is created, a notification email is sent. Replying to the notification email (or any further emails regarding the ticket) adds a comment to the ticket. Further, the user can add attachments to any emails and have them show up as attachments to a comment.</p>
<p>So, how does it work? Let&#8217;s start with the big picture. The mail transfer agent Postfix runs on the same server as the <a href="http://www.ticketi.sh">Ticketish</a> mongrels. Postfix receives mail for all ticketi.sh subdomains. When Postfix receives a new message, it fires up script/runner for <a href="http://www.ticketi.sh">Ticketish</a> and passes the message in via <span class="caps">STDIN</span>. At this point we don&#8217;t care if the project exists or not, that&#8217;s for Rails to figure out. Postfix just needs to send any emails addressed to &#42;.ticketi.sh to script/runner.</p>
<p>Let&#8217;s dig a little deeper, and see how to accomplish this behavior with Postfix.</p>
<p>The first Postfix configuration file we&#8217;ll look at is main.cf. I won&#8217;t paste the whole file, just the interesting parts that differ from the default main.cf file Postfix comes with.</p>
<code><pre>
/etc/postfix/main.cf
myhostname = ticketi.sh
mydomain   = ticketi.sh
mydestination = $myhostname, localhost.$mydomain, localhost, regexp:/etc/postfix/mydestination
</pre></code>
<p>This is mostly straight-forward. We set the hostname and domain to &#8220;ticketi.sh&#8221;. The interesting part is that we&#8217;re using a regular expression lookup table with mydestination. The mydestination setting means &#8220;this is the final destination for the following domains&#8221;. Obviously, we want to be the final destination for all Ticketi.sh domains, so we use a regular expression.</p>
<code><pre>
/etc/postfix/mydestination
/.*\.ticketi\.sh/       OK
</pre></code>
<p>Pretty simple. You need to make sure you generate the database file from that lookup table by running postalias:</p>
<code><pre>
# postalias /etc/postfix/mydestination
# ls /etc/postfix/mydestination.db
/etc/postfix/mydestination.db
</pre></code>
<p>Now that Postfix knows to receive mail for &#42;.ticketi.sh, we need to tell it where to send that mail. First, we&#8217;ll create a wrapper around script/runner that can receive incoming emails from Postfix.</p>
<code><pre>
/etc/postfix/ticketish_agent.sh
#!/bin/bash
HOME=/home/lsws /usr/bin/ruby /home/lsws/apps/ticketish/current/script/runner 'data = STDIN.read; CommentHandler.receive(data) || TicketHandler.receive(data)' 2&gt;&gt; /home/lsws/ticketish_agent.log
</pre></code>
<p>The actual Rails code in runner is pretty simple. We assign the incoming email to the data variable, and then do &#8216;CommentHandler.receive(data) || TicketHandler.receive(data)&#8217;. This code tries to add the message as a comment first, but if the comment handler returns nil (as it will if the message isn&#8217;t a comment) it&#8217;ll create it as a new ticket instead.</p>
<p>Now we need to add a service to Postfix by adding a few lines at the bottom of master.cf.</p>
<code><pre>
/etc/postfix/master.cf
mailman   unix  -       n       n       -       -       pipe
flags= user=lsws argv=/etc/postfix/ticketish_agent.sh
</pre></code>
<p>We&#8217;ve just called the service &#8220;mailman&#8221; and it pipes the message through to the wrapper we just created. Note the user= field. As you might guess, this is the user the process runs as. Be sure to use the user your Rails application runs under.</p>
<p>Finally, we need to tell Postfix to deliver all local mail to this new service (all local mail, since Postfix is entirely dedicated to <a href="http://www.ticketi.sh">Ticketish</a>). We do this by defining the local_transport in main.cf.</p>
<code><pre>
/etc/postfix/main.cf
local_transport = mailman
</pre></code>
<p>Creating the CommentHandler and TicketHandler is pretty simple. We just use the following structure:</p>
<code><pre>
ticketish/app/models/comment_handler.rb
class CommentHandler &lt; ActionMailer::Base 
def receive(email)
# ...
end
end
</pre></code>
<p>You can do whatever you like once you have the email. For example, to extract the project name and domain name from the recipient address of the email:</p>
<code><pre>
project_name, domain_name = email.to.first.split("@")
</pre></code>
<p>So there you have it. Easy email integration with Postfix and Rails. If you haven&#8217;t already heard of <a href="http://www.ticketi.sh">Ticketish</a>, take a look. It&#8217;s our new simple ticketing application, currently in beta. We&#8217;re still sending out beta invites, so feel free to add your name.</p>
<img src="http://feeds.integralimpressions.com/~r/integralthoughts/code/~4/188750267" height="1" width="1"/>]]></content:encoded>
<pubDate>Fri, 22 Jun 2007 02:40:00 -0700</pubDate>
<guid isPermaLink="false">http://integralimpressions.com/blog/ticketish-email-integration</guid>
<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=integralthoughts/code&amp;itemurl=http%3A%2F%2Fintegralimpressions.com%2Fblog%2Fticketish-email-integration</feedburner:awareness><feedburner:origLink>http://integralimpressions.com/blog/ticketish-email-integration</feedburner:origLink></item>
<item>
<title>ActiveResource: Associations and Methods</title>
<link>http://feeds.integralimpressions.com/~r/integralthoughts/code/~3/188750268/activeresource-associations-methods</link>
<content:encoded><![CDATA[
<p>ActiveResource (ARes) has been much talked about, and is already quite usable. There&#8217;s a few getting started articles out there, but not much with any real depth. In this article I&#8217;ll take one step further and talk about associations and methods. Recommended reading for this article is listed at the end of the post.</p>
<p>After installing the ARes plugin, the first thing you want to do is create a parent class for your resources to inherit from. The parent class looks something like this:</p>
<p>billing_resource.rb:</p>
<code lang="ruby">
class BillingResource &lt; ActiveResource::Base
self.site = "http://127.0.0.1:4000" 
end
</code>
<p>Here, we&#8217;re simply creating a BillingResource that acts as a parent to our resources such as CreditCard, Invoice and Subscription. You set the location of the remote application in the self.site variable in this class, so that you don&#8217;t have to set it for every other resource. You can also add any other common methods here.</p>
<p>Now, let&#8217;s create a Subscription resource:</p>
<p>subscription.rb:</p>
<code lang="ruby">
class Subscription &lt; BillingResource
def free?
amount_in_cents.to_i == 0
end
def credit_card
@credit_card ||= CreditCard.find(credit_card_id) if credit_card_id
end
def invoices
@invoices ||= connection.get("/subscriptions/#{id}/invoices.xml").collect { |h| Invoice.find(h['id']) } rescue []
end
def generate_and_pay_next_invoice
resp = connection.post("/subscriptions/#{id}.xml;generate_and_pay_next_invoice")
!resp.to_hash['location'].nil?
end
end
</code>
<p>First off, you will notice our Subscription resource inherits from the parent BillingResource. You&#8217;ll also notice that we&#8217;re defining methods for the associations, such as credit_card and invoices. ActiveResource doesn&#8217;t automatically do this for you. It&#8217;s up to you to implement it.</p>
<p>ActiveResource provides a basic find() method for your resources. You can do Invoice.find(id) but you can&#8217;t do Invoice.find_all_by_subscription_id(x). If you try, you just get a NoMethodError:</p>
<code lang="ruby">
&gt;&gt; Invoice.find_by_subscription_id(1)
NoMethodError: undefined method `find_by_subscription_id' for Invoice:Class
</code>
<p>This isn&#8217;t a big deal. We can use the connection object to contact the remote resource at the correct <span class="caps">RES</span>Tful <span class="caps">URL</span> to retrieve the data we need. The relevant line from the code snippet above is:</p>
<code lang="ruby">
@invoices ||= connection.get("/subscriptions/#{id}/invoices.xml").collect { |h| Invoice.find(h['id']) } rescue []
</code>
<p>What&#8217;s happening here? We&#8217;re requesting, from the remote application, the <span class="caps">XML</span> version of the index action on the invoices controller for the subscription &#8216;id&#8217;. The <span class="caps">XML</span> version knows to just do a select => :id on the invoices, so the return payload is just a bunch of invoice id&#8217;s. In this example, I&#8217;m then iterating through each invoice id and loading the full invoice; you could do something more efficient if you need to. This all gets cached in the @invoices variable so that repeat hits to subscription.invoices don&#8217;t need to fetch the data again.</p>
<p>Your&#8217;re probably wondering what the invoices index action in the remote application looks like. It&#8217;s very simple:</p>
<code lang="ruby">
def index
@subscription = Subscription.find params[:subscription_id]
format.xml do
render :xml =&gt; @subscription.invoices.find(:all, :select =&gt; 'id').to_xml
end
end
</code>
<p>The credit_card method is a lot simpler than the invoices method, because it&#8217;s just a belongs_to relationship. We&#8217;ve already got the credit_card_id available, so we can just do a simple CreditCard.find(credit_card_id). Again, we&#8217;re caching it in the @credit_card variable to minimize repeat trips over the network.</p>
<p>Finally, you&#8217;ll notice the generate_and_pay_next_invoice method. This is actually a method on the Subscription model in the remote application, but because ARes doesn&#8217;t let you call methods remotely, we need to define it again. We won&#8217;t, however, repeat the logic of the method. Instead, we&#8217;ll do a connection.post to the generate_and_pay_next_invoice action in the remote subscriptions controller. The action in the remote application is pretty simple:</p>
<code lang="ruby">
def generate_and_pay_next_invoice
@subscription = Subscription.find(params[:id])
@invoice = @subscription.generate_and_pay_next_invoice
respond_to do |format|
if @invoice
format.xml { head :created, :location =&gt; subscription_invoice_url(@subscription, @invoice) }
else
format.xml { head :ok }
end
end
end
</code>
<p>If the remote action is successful, it will return the location of the new invoice resource. We can use that to make the method return true or false depending on its success:</p>
<code lang="ruby">
!resp.to_hash['location'].nil?
</code>
<p>I&#8217;m returning <em>head :ok</em> in this method instead of a 422 or 500 error status. That&#8217;s because it&#8217;s not supposed to raise any exceptions if there&#8217;s nothing for generate_and_pay_next_invoice to do. You could, however, easily return an error status:</p>
<code lang="ruby">
format.xml { render :text =&gt; "Failed", :status =&gt; 422 }
</code>
<p>In summary:</p>
<ul>
<li>ARes does not let you call remote methods directly, you need to implement them.</li>
<li>ARes does not provide methods for associations, you need to implement them.</li>
</ul>
<p>If you keep these points in mind, working with ARes becomes a lot more straight-forward.</p>
<p>There may be better ways to implement some of these items. The above has worked well for me, but if you know of better practices please leave a comment and I&#8217;ll keep the post alive by integrating the new information.</p>
<h3>Recommended Reading</h3>
<ul>
<li><a href="http://ryandaigle.com/articles/2006/06/30/whats-new-in-edge-rails-activeresource-is-here">http://ryandaigle.com/articles/2006/06/30/whats-new-in-edge-rails-activeresource-is-here</a></li>
<li><a href="http://blog.mauricecodik.com/2006/06/instant-rest-on-rails-activeresource.html">http://blog.mauricecodik.com/2006/06/instant-rest-on-rails-activeresource.html</a></li>
<li><a href="http://www.eribium.org/?p=71">http://www.eribium.org/?p=71</a></li>
</ul>
<img src="http://feeds.integralimpressions.com/~r/integralthoughts/code/~4/188750268" height="1" width="1"/>]]></content:encoded>
<pubDate>Tue, 17 Apr 2007 22:47:00 -0700</pubDate>
<guid isPermaLink="false">http://integralimpressions.com/blog/activeresource-associations-methods</guid>
<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=integralthoughts/code&amp;itemurl=http%3A%2F%2Fintegralimpressions.com%2Fblog%2Factiveresource-associations-methods</feedburner:awareness><feedburner:origLink>http://integralimpressions.com/blog/activeresource-associations-methods</feedburner:origLink></item>
<item>
<title>New Plugin: current_resource</title>
<link>http://feeds.integralimpressions.com/~r/integralthoughts/code/~3/188750269/current_resource</link>
<content:encoded><![CDATA[
<p>One of the nice things about <a href="http://www.rubyonrails.org/">Ruby on Rails</a> is it&#8217;s use of convention over configuration. The idea is that if you follow common conventions, everything just kind of falls into place for you. We adopted many <a href="http://www.loudthinking.com/arc/000593.html">RESTful conventions</a> a while ago, and have been reaping the benefits ever since. However, one thing we, and many others, have noticed with our shiny new <span class="caps">RES</span>Tful-style controllers is that they begin to look a little repetitive. This leaves us with a great opportunity to begin extracting these repetitive bits to help <span class="caps">DRY</span> up our code.</p>
<p><a href="http://svn.integralserver.com/plugins/current_resource/">CurrentResource</a> is a Ruby on Rails plugin which creates some nice convenience methods to access the current resource being referenced in the request <span class="caps">URI</span> when you follow common <span class="caps">RES</span>Tful conventions.</p>
<h2>So What&#8217;s It Do?</h2>
<p>Let&#8217;s get the basics out of the way first. Make sure you install the plugin and restart your application:</p>
<code lang="shell">
./script/plugin install http://svn.integralserver.com/plugins/current_resource
</code>
<p>The easiest way to explain this is with an example. Let&#8217;s use the ever-so-popular example of a blog:</p>
<code lang="ruby">
# URI: /articles/1
current_article #=&gt; Article.find(1)
</code>
<h2>What About Nested Resources?</h2>
<p>The main reason why I wrote this plugin was to create an easy way to access the parent resource being referenced with nested resources. This is what I mean:</p>
<code lang="ruby">
# Nested route in config/routes.rb
map.resources :articles do |article|
article.resources :comments
end  
# URI: /articles/2/comments/1
current_article #=&gt; Article.find(2)
current_comment #=&gt; Comment.find(1)
</code>
<h2>Use of method_missing</h2>
<p>One important item to note is that CurrentResource utilizes method_missing to dynamically add the current_resource method. What this means is that if methods with this format already exist, those will take precedence. For example, if you have a current_user method defined as part of your <a href="http://svn.techno-weenie.net/projects/plugins/restful_authentication/">authentication system</a>, that is the method that will called.</p>
<p>If you liked this article, feel free to <a href="http://digg.com/programming/New_Ruby_on_Rails_Plugin_CurrentResource">digg it</a></p>
<img src="http://feeds.integralimpressions.com/~r/integralthoughts/code/~4/188750269" height="1" width="1"/>]]></content:encoded>
<pubDate>Sun, 11 Mar 2007 22:14:00 -0700</pubDate>
<guid isPermaLink="false">http://integralimpressions.com/blog/current_resource</guid>
<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=integralthoughts/code&amp;itemurl=http%3A%2F%2Fintegralimpressions.com%2Fblog%2Fcurrent_resource</feedburner:awareness><feedburner:origLink>http://integralimpressions.com/blog/current_resource</feedburner:origLink></item>
<item>
<title>Goodbye RMagick. Hello ImageScience.</title>
<link>http://feeds.integralimpressions.com/~r/integralthoughts/code/~3/188750270/goodbye_rmagick_hello_imagescience</link>
<content:encoded><![CDATA[
<p>I&#8217;ve always known RMagick was a memory hog, but never realised just how bad it is. I&#8217;m not sure if the problem&#8217;s RMagick or ImageMagick, but either way, it&#8217;s a problem. Here&#8217;s the story.</p>
<p>Recently, I setup some generous memory limits on our servers to catch any out of control applications from gobbling up the servers memory and bringing everything down. I thought 200MB per Rails process was quite generous, and for the most part it has been.</p>
<p>Today I found out that one of our client&#8217;s was having some trouble uploading images in their application. I quickly found the culprit:</p>
<code class="ruby">
Magick::ImageMagickError (Out of Memory! `'):
</code>
<p>Huh? These weren&#8217;t big images the client was uploading. Just tiny, less than 100KB <span class="caps">PNG</span>&#8217;s. But something must have went terribly wrong to hit that memory limit. To find out just how bad it was I removed the memory limit and watched the Rails process in top. Within a few seconds it was over 400MB and growing. Needless to say, I quickly killed it.</p>
<p>Since we&#8217;re already using <a href="http://svn.techno-weenie.net/projects/plugins/attachment_fu/">attachment_fu</a> I solved the problem without changing a single line of code. I headed over to the <a href="http://seattlerb.rubyforge.org/ImageScience.html">ImageScience</a> website, followed the instructions to install and restarted the application. Uploading now works perfectly, and memory usage barely moves.</p>
<p>Unfortunately (or maybe fortunately), ImageScience is pretty slim on what it can do. It generates thumbnails. What we need now is something with the power of RMagick+ImageMagick that&#8217;s quick, light on memory and relatively bug-free. Any ideas?</p>
<img src="http://feeds.integralimpressions.com/~r/integralthoughts/code/~4/188750270" height="1" width="1"/>]]></content:encoded>
<pubDate>Sat, 10 Feb 2007 16:14:00 -0800</pubDate>
<guid isPermaLink="false">http://integralimpressions.com/blog/goodbye_rmagick_hello_imagescience</guid>
<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=integralthoughts/code&amp;itemurl=http%3A%2F%2Fintegralimpressions.com%2Fblog%2Fgoodbye_rmagick_hello_imagescience</feedburner:awareness><feedburner:origLink>http://integralimpressions.com/blog/goodbye_rmagick_hello_imagescience</feedburner:origLink></item>
<item>
<title>How about some HAML for lunch?</title>
<link>http://feeds.integralimpressions.com/~r/integralthoughts/code/~3/188750271/how_about_some_haml_for_lunch</link>
<content:encoded><![CDATA[
<p>I wanted to see what all the fuss was about, so I decided to give <a href="http://haml.hamptoncatlin.com/">HAML</a> a try. <span class="caps">HAML </span>(HTML Abstraction Markup Language) is a replacement for your <span class="caps">RHTML</span> view templates in a Rails application. The goal of <span class="caps">HAML</span> is to provide a very simple and <span class="caps">DRY</span> way to produce properly structured <span class="caps">XHTML</span>.</p>
<p>Rails gives us a few pieces of magic which really help us cut down on our code. Both migrations and <span class="caps">RJS</span> templates are perfect examples of this. They help you to write boring, repetitive code in a fun and easy syntax. As a designer, I particularly feel there are two area that have received the short end of the &#8220;innovation stick&#8221;: <span class="caps">XHTML</span> and <span class="caps">CSS</span>. HAML looks to bring the <span class="caps">XHTML</span> side of things up to speed.</p>
<h1>The Good</h1>
<p>Overall, I have to say I&#8217;ve been thoroughly impressed with <span class="caps">HAML</span>. The syntax took a whole 10 minutes to pick up (although, I am very familiar with <span class="caps">CSS</span>, which probably helped). I decided to take one of our applications and convert all the views to <span class="caps">HAML</span> and it went of without a hitch.</p>
<h2>Minimalist Syntax</h2>
<p>The syntax is about as minimalist as you can get. To convert an <span class="caps">RHTML</span> template to <span class="caps">HAML</span>, you pretty much delete every repetitive or unnecessary character in your <span class="caps">RHTML</span> template, and there you go! Now you have <span class="caps">HAML</span>. Here&#8217;s a sample:</p>
<code lang="ruby">
&lt;table class="data"&gt;
&lt;tr&gt;
&lt;th class="left"&gt;Campaign&lt;/th&gt;
&lt;th&gt;Visitors&lt;/th&gt;
&lt;th&gt;Leads&lt;/th&gt;
&lt;th class="right"&gt;Conversion Rate&lt;/th&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;/tr&gt;
&lt;%= render :partial =&gt; 'campaign', :collection =&gt; @campaigns %&gt;
&lt;/table&gt;
</code>
<p>Here&#8217;s the same snippet in <span class="caps">HAML</span>:</p>
<code>
%table.data
%tr
%th.left Campaign
%th Visitors
%th Leads
%th.right Conversion Rate
%th &amp;nbsp;
= render :partial =&gt; 'campaign', :collection =&gt; @campaigns
</code>
<h2>Whitespace Active</h2>
<p><span class="caps">HAML</span> is &#8220;whitespace active.&#8221; This enables you to cut down on a significant portion of your code because you don&#8217;t have to close your tags. <span class="caps">HAML</span> closes your tags for you based on your indentation.</p>
<h2>Beautiful <span class="caps">XHTML</span></h2>
<p>This has got to be one of my favorite part about <span class="caps">HAML</span>. The final output of your <span class="caps">XHTML</span> is always perfectly formatted with proper indentation, even across your partials! Aside from appeasing the <span class="caps">OCD</span> in us all, this makes it much easier when you&#8217;re scanning through your source trying to find a particular section. <span class="caps">HAML</span> is even smart enough to automatically lines at 50 characters for the ultimate in <span class="caps">XHTML</span>-viewing pleasure.</p>
<h1>The Not-So-Good</h1>
<p>Maybe I just haven&#8217;t put enough miles on <span class="caps">HAML</span> yet, but it was difficult to find negatives to using it. Nonetheless, there were a few.</p>
<h2>Inline Tags</h2>
<p><span class="caps">HAML</span> doesn&#8217;t really have great support for code with a lot of inline tags such as <code>&lt;em&gt;</code> or <code>&lt;strong&gt;</code>. Let&#8217;s say you want to generate this code:</p>
<code lang="html">
&lt;p&gt;
This is &lt;strong&gt;strong&lt;/strong&gt; text, and this is &lt;em&gt;emphsized&lt;/em&gt; text.
&lt;/p&gt;
</code>
<p>You can either type out the html tags, or do this:</p>
<code lang="haml">
%p
This is
%strong strong
text, and this is
%em emphasized
text
</code>
<p>Not really ideal. On a positive note, <span class="caps">HAML</span> will soon enable &#8220;filters.&#8221; This feature is currently available in trunk. Using the textile filter, you could do this:</p>
<code lang="haml">
:textile
This is *strong* text, and this is _emphasized_ text.
</code>
<h2>Whitespace Active</h2>
<p>There&#8217;s also a slight negative to the whitespace active aspect of <span class="caps">HAML</span>. It&#8217;s because this will probably be the biggest change for most Rails developers. None of the languages currently used in Rails utilize the whitespace. Just be careful, that&#8217;s all. Be sure to set your editor up properly (soft tabs, 2 spaces). Showing invisibles helps a lot to make sure you don&#8217;t have any &#8220;tabs&#8221; sneaking in there.</p>
<h1>Conclusion</h1>
<p>I&#8217;m probably only 3-4 hours into my <span class="caps">HAML</span> experience so far (not including writing this blog post), but I don&#8217;t see myself turning back. If you want to give it a shot, just install the plugin into your Rails application:</p>
<code lang="shell">
./script/plugin install svn://hamptoncatlin.com/haml/tags/stable
</code>
<p>The great thing about it is you can mix your <span class="caps">HAML</span> templates and your <span class="caps">RHTML</span> templates, so just start off with one <span class="caps">RHTML</span> view template and convert it to <span class="caps">HAML</span>. Happy coding!</p>
<img src="http://feeds.integralimpressions.com/~r/integralthoughts/code/~4/188750271" height="1" width="1"/>]]></content:encoded>
<pubDate>Sat, 10 Feb 2007 16:11:00 -0800</pubDate>
<guid isPermaLink="false">http://integralimpressions.com/blog/how_about_some_haml_for_lunch</guid>
<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=integralthoughts/code&amp;itemurl=http%3A%2F%2Fintegralimpressions.com%2Fblog%2Fhow_about_some_haml_for_lunch</feedburner:awareness><feedburner:origLink>http://integralimpressions.com/blog/how_about_some_haml_for_lunch</feedburner:origLink></item>
<item>
<title>nginx: the front end solution for rails deployment?</title>
<link>http://feeds.integralimpressions.com/~r/integralthoughts/code/~3/188750272/nginx</link>
<content:encoded><![CDATA[
<p>This article is a simple tutorial for getting nginx and mongrel_clusters up and running for your rails applications. It&#8217;s based off the great intro article by <a href="http://brainspl.at/">Ezra Zygmuntowicz</a>. I used his installation steps and configuration file. Please take a look at his articles for further details.</p>
<p><a href="http://sysoev.ru/nginx/">nginx</a> (pronounced: &#8220;engine x&#8221;) is an <span class="caps">HTTP</span>-server that is under active development by <a href="http://sysoev.ru/en/">Igor Sysoev</a>. It runs on any nix platform, including <span class="caps">OSX </span>(which we&#8217;ll be using in this tutorial), Solaris, Linux, and FreeBSD. For Rails applications, it&#8217;s meant to be used to serve your static and cached files inside your rails application. The rest is handled by a mongrel_cluster. Think of it as a replacement for either of the two current popular solutions, Apache 2.2 w/mod_proxy_balancer, or Lighttpd. Both sit in front of that mongrel_cluster and serve static content.</p>
<p><strong>Setup:</strong></p>
<p>Install mongrel:<br /><code lang="ruby">
sudo gem install mongrel
</code><br />Install mongrel_cluster:<br /><code lang="ruby">
sudo gem install mongrel_cluster
</code><br />Install nginx:<br /><code lang="ruby">
curl -O http://sysoev.ru/nginx/nginx-0.3.60.tar.gz
tar -xzvf nginx-0.3.60.tar.gz
cd nginx-0.3.60
./configure --sbin-path=/usr/local/sbin --with-http_ssl_module
make
sudo make install
sudo chmod +x /usr/local/sbin/nginx
</code><br />Nginx will install to /usr/local/nginx and in there you will find the conf directory containing the nginx.conf file, the logs directory with the error and access logs, as well as the <span class="caps">PID</span> for the nginx process.</p>
<p>Once you&#8217;ve got everything installed, create a new Rails application wherever you&#8217;d like.<br /><code lang="ruby">
rails demo
</code><br />Then, create a mongrel_cluster for your application. I&#8217;m going to use ports 8000 &#38; 8001, but you can use whatever you&#8217;d like. I&#8217;ve also set the environment to production, but again, you can set that to whatever you&#8217;d like. This will create a config file located at demo/config/mongrel_cluster.yml. You can create as many mongrel instances as you would like.</p>
<code lang="ruby">
mongrel_rails cluster::configure -p 8000 -e production -a 127.0.0.1
</code>
<p>Start the mongrel cluster</p>
<code lang="ruby">
mongrel_rails cluster::start
</code>
<p>This can be stopped or restarted just as easily by typing:</p>
<code lang="ruby">
mongrel_rails cluster::stop
mongrel_rails cluster::restart
</code>
<p>So now your app should have it&#8217;s mongrel cluster running fine. You can test by loading up either http://localhost:8000/ or http://localhost:8001/.</p>
<p>Now go ahead and open up the nginx.conf file located at /usr/local/nginx/conf/nginx.conf in TextMate or your favorite editor. There is a default conf file there, but it wouldn&#8217;t hurt to back up the old one.</p>
<p>Paste in the following code or download a .conf file with the same info <a href="http://integralimpressions.com/code/nginx.conf">here</a>:<br /><code lang="ruby">
worker_processes  2;
error_log  logs/error.log notice;
pid        logs/nginx.pid;
events {
worker_connections  1024;
}
http {
include       conf/mime.types;
default_type  application/octet-stream;
# no sendfile on OSX uncomment 
#this if your on linux or bsd
#sendfile        on;
tcp_nopush     on;
keepalive_timeout  65;
tcp_nodelay        on;
upstream mongrel {
server 127.0.0.1:8000;
server 127.0.0.1:8001;
}
gzip on;
gzip_min_length  1100;
gzip_buffers     4 8k;
gzip_types       text/plain;
server {
listen       80;
#server_name  localhost;
root /path_to/rails/public;
access_log  off;
rewrite_log on;
# / -&gt; first search for local index.html then go to mongrel
location ~ ^/$ {
if (-f /index.html){
rewrite (.*) /index.html last;
}
proxy_pass  http://mongrel;
}
# rail caching: searching first for $action.html local pages
location / {
if (!-f $request_filename.html) {
proxy_pass  http://mongrel;
}
rewrite (.*) $1.html last;
}
# serve static files directly
location ~ .html {
root /path_to/rails/public;
}
location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|mov)$ {
root /path_to/rails/public;
}
# resend everything else to mongrel
location / {
proxy_pass  http://mongrel;
proxy_redirect     off;
proxy_set_header   Host             $host;
proxy_set_header   X-Real-IP        $remote_addr;
proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
}
}
}
</code><br />Set /path_to/rails/public to whatever the path to your rails app is.</p>
<p>Once you&#8217;ve gotten your nginx.conf file saved, fire up nginx and let it rip. You start nginx by calling that executable that was created when you built from source earlier. In the example above it would be:</p>
<code lang="ruby">
sudo nginx
</code>
<p><strong>Sidenote:</strong> make sure Apache is turned off, it&#8217;s most likely been turned on in Personal Web Sharing under System Preferences &rarr; Sharing. Load up http://localhost, and you should see a blank Rails app from there.</p>
<p>Nginx is managed by sending <span class="caps">UNIX</span> signals to that process, similar to apache. For more info on that, visit <a href="http://zh.stikipad.com/notes/show/nginx">Zhesto&#8217;s notes</a>.</p>
<p>Nginx has a lot of buzz right now about being a potential solution for being the lightweight front end for mongrel_clusters. Whether or not that happens remains to be seen, but hopefully now you can help make that decision.</p>
<p>All credit for this article goes to <a href="http://brainspl.at/">Ezra Zygmuntowicz</a> and <a href="http://blog.kovyrin.net/">Alexy Kovyrin</a> for posting enough info to get started, as well as <a href="http://fluxura.com/">Bradley Taylor</a> for the mongrel_cluster plugin. Please check out those blogs for more information.</p>
<img src="http://feeds.integralimpressions.com/~r/integralthoughts/code/~4/188750272" height="1" width="1"/>]]></content:encoded>
<pubDate>Mon, 01 Jan 2007 18:12:00 -0800</pubDate>
<guid isPermaLink="false">http://integralimpressions.com/blog/nginx</guid>
<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=integralthoughts/code&amp;itemurl=http%3A%2F%2Fintegralimpressions.com%2Fblog%2Fnginx</feedburner:awareness><feedburner:origLink>http://integralimpressions.com/blog/nginx</feedburner:origLink></item>
<item>
<title>Integral Mailer</title>
<link>http://feeds.integralimpressions.com/~r/integralthoughts/code/~3/188750273/integral_mailer</link>
<content:encoded><![CDATA[
<p>Integral Mailer is a Ruby on Rails plugin that lets you send email to remote hosts without the aid of<br />a full-blown <span class="caps">MTA</span> like Sendmail. It works by doing a lookup of the<br />MX server for the destination email and delivering the message directly<br />to that mail server.</p>
<strike>At the moment, you&#8217;ll require a unix environment with the &#8216;dig&#8217; command<br />available. Without this, the whole thing will fail miserably.</strike> Thanks to Dan Kubb we&#8217;re now using the resolv library to do our MX lookups, removing the dependency on the &#8216;dig&#8217; tool. This <em>should</em> make Integral Mailer cross-platform.
<p>Right now it&#8217;s experimental, and probably more useful in a<br />development environment. However, if you use it in production please<br />be sure to let me know of your success (or lack thereof).</p>
<h3>Installation</h3>
<code lang="ruby">
./script/plugin install http://svn.integralserver.com/plugins/integral_mailer
</code>
<h3>Configuration</h3>
<p>The goal was to keep the configuration as simple as possible. You<br />can start sending mail by adding one line to environment.rb:</p>
<code lang="ruby">
config.action_mailer.delivery_method = :integral_mailer
</code>
<p>However, you should probably also add a second line which sets<br />the value for the &#8220;HELO&#8221; command when connecting to the remote<br /><span class="caps">SMTP</span> host. The value should be your domain name.</p>
<code lang="ruby">
config.action_mailer.server_settings = { :helo =&gt; 'foo.com' }
</code>
<h3>Reverse <span class="caps">DNS</span></h3>
<p>This isn&#8217;t specific to Integral Mailer, but you should also make sure you have reverse <span class="caps">DNS</span> setup properly for the IP address you&#8217;re running this on. Otherwise, some mail servers will refuse to accept your mail (or give you a high spam score). Setting up reverse <span class="caps">DNS</span> usually involves sending an email request to your hosting provider.</p>
<img src="http://feeds.integralimpressions.com/~r/integralthoughts/code/~4/188750273" height="1" width="1"/>]]></content:encoded>
<pubDate>Sun, 10 Dec 2006 18:13:00 -0800</pubDate>
<guid isPermaLink="false">http://integralimpressions.com/blog/integral_mailer</guid>
<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=integralthoughts/code&amp;itemurl=http%3A%2F%2Fintegralimpressions.com%2Fblog%2Fintegral_mailer</feedburner:awareness><feedburner:origLink>http://integralimpressions.com/blog/integral_mailer</feedburner:origLink></item>
<item>
<title>Nginx Conf Update</title>
<link>http://feeds.integralimpressions.com/~r/integralthoughts/code/~3/188750274/nginx_conf_update</link>
<content:encoded><![CDATA[
<p>Ezra and company pounded out a new Nginx conf file with static file and rails caching support. Grab the file over at <a href="http://brainspl.at/articles/2006/09/12/new-nginx-conf-with-rails-caching">Ezra&#8217;s post</a></p>
<img src="http://feeds.integralimpressions.com/~r/integralthoughts/code/~4/188750274" height="1" width="1"/>]]></content:encoded>
<pubDate>Thu, 19 Oct 2006 18:12:00 -0700</pubDate>
<guid isPermaLink="false">http://integralimpressions.com/blog/nginx_conf_update</guid>
<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=integralthoughts/code&amp;itemurl=http%3A%2F%2Fintegralimpressions.com%2Fblog%2Fnginx_conf_update</feedburner:awareness><feedburner:origLink>http://integralimpressions.com/blog/nginx_conf_update</feedburner:origLink></item>
<item>
<title>Dynamically adding attributes to your model</title>
<link>http://feeds.integralimpressions.com/~r/integralthoughts/code/~3/188750275/dynamically_adding_attributes_to_your_model</link>
<content:encoded><![CDATA[
<h3>The Situation</h3>
<p>Let&#8217;s assume you have a form which collects data on people, but the questions you ask on the form are dynamic. The person who fills out the form is stored in one model, while the responses are stored out in another. Your migration might look something like this:</p>
<code lang="ruby">
class DynamicAttributesDemo &lt; ActiveRecord::Migration
def self.up
create_table :people do |t|
t.column :created_at, :datetime
end
create_table :responses do |t|
t.column :created_at, :datetime
t.column :question, :string
t.column :answer, :text
t.column :person_id, :integer
end
end
def self.down
drop_table :people
drop_table :responses
end
end
</code>
<p>So each person would have their responses stored in the <code>responses</code> table. Initially, your models would look something like this:</p>
<code lang="ruby">
class Person &lt; ActiveRecord::Base
has_many :forms
end
class Response &lt; ActiveRecord::Base
belongs_to :person
end
</code>
<h3>The Problem</h3>
<p>The issue here is we want to add any responses belonging to a <code>Person</code> to its attribute hash. Lets take our above example and decide we want to have a form which asks for<br />name, email, and phone number. Not only would you be able to do this:</p>
<code lang="ruby">
@person = Person.find(:first)
@person.name # Response to the name question
@person.email # Response to the email question
@person.phone_number # Response to the phone number question
</code>
<p>but the <code>name</code>, <code>email</code>, and <code>phone_number</code> attributes would actually show up in the <code>@person.attributes</code> hash.</p>
<h3>The Solution</h3>
<p>Here&#8217;s how I handled this problem. I created a method which would find all of a person&#8217;s responses. It would then add each response to the person&#8217;s attribute hash, using an underscored version of the question as the key, and the answer as the value. I then use the <code>after_find</code> callback to add in those attributes on the fly. Pretty simple right? Here&#8217;s the code:</p>
<code lang="ruby">
class Person &lt; ActiveRecord::Base
has_many :forms
protected
def after_find
responses_to_attributes
end
def responses_to_attributes
self.responses.each do |response|
self[response.question.underscore.to_sym] = response.answer
end
end
end
</code>
<h3>The Aftermath</h3>
<p>So there&#8217;s probably a few disclaimers I should throw in here. First of all, this obviously isn&#8217;t going to work very well for wordy questions. This isn&#8217;t very pretty:</p>
<code lang="ruby">
@person.whats_your_favorite_thing_about_using_the_rails_framework
</code>
<p>Another big disclaimer I&#8217;d like to throw out there, is you can take some significant performance hits using <code>after_find</code> coupled with ActiveRecord&#8217;s associations spitting out some messy <span class="caps">SQL</span> queries. Think of it this way: If ActiveRecord generates 20 <span class="caps">SQL</span> queries to find your responses that you want (not in the above example, but perhaps in an example with more complex associations), and you pull up a collection of 1,0000 ActiveRecord objects&#8230; well, you do the math. All I&#8217;m saying is you may get to the point where you need to just write a custom <span class="caps">SQL</span> statement for your <code>responses_to_attributes</code> method to try to minimize the pain.</p>
<h3>Why?</h3>
<p>So why go to all this trouble of pre-loading all these attributes. Why can&#8217;t we just call each attribute individually and load it at that time. It&#8217;d be a lot less stressful on the system, sure. Different people may have particular needs for the attributes hash specifically. In my case, the <a href="http://blog.integralimpressions.com/articles/2006/09/01/tocsv-plugin">ToCSV plugin</a> uses the attributes hash to generate a <span class="caps">CSV</span>. By loading these dynamic attributes onto the model object, I can easily export those custom questions along with their responses to a <span class="caps">CSV</span> file.</p>
<p>If you have any ideas of your own where you think this might be useful (or if you have a better way of doing this), be sure to let me know.</p>
<p><a href="http://digg.com/programming/Rails_Tutorial_Dynamically_adding_attributes_to_your_model">Digg this article</a></p>
<img src="http://feeds.integralimpressions.com/~r/integralthoughts/code/~4/188750275" height="1" width="1"/>]]></content:encoded>
<pubDate>Thu, 19 Oct 2006 18:12:00 -0700</pubDate>
<guid isPermaLink="false">http://integralimpressions.com/blog/dynamically_adding_attributes_to_your_model</guid>
<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=integralthoughts/code&amp;itemurl=http%3A%2F%2Fintegralimpressions.com%2Fblog%2Fdynamically_adding_attributes_to_your_model</feedburner:awareness><feedburner:origLink>http://integralimpressions.com/blog/dynamically_adding_attributes_to_your_model</feedburner:origLink></item>
<item>
<title>Authentication for your API or Feed</title>
<link>http://feeds.integralimpressions.com/~r/integralthoughts/code/~3/188750276/authentication_for_your_api_or_feed</link>
<content:encoded><![CDATA[
<p>Getting authentication for your your <span class="caps">API</span> or your <span class="caps">RSS</span>/Atom feed is a lot simpler than you might think. Long story short, <a href="http://svn.techno-weenie.net/projects/plugins/restful_authentication/">restful_authentication</a> will default to act like <span class="caps">HTTP </span>Basic Auth for xml requests. Its just a small step from there to get the same functionality for your <span class="caps">RSS</span> feeds.</p>
<p>I&#8217;ve always liked <a href="http://technoweenie.stikipad.com/plugins/show/Acts+as+Authenticated">acts_as_authenticated</a> for my authentication needs. restful_authentication is simply a more &#8220;RESTful&#8221; version of this plugin. When I realized I could continue using this same authentication system for <em>all</em> my authentication needs, I knew I had a winner.</p>
<p>Enough talking, let&#8217;s jump in! Start off by installing the simply_restful plugin:</p>
<code lang="ruby">
script/plugin install -x http://svn.techno-weenie.net/projects/plugins/restful_authentication
</code>
<p>Follow the <span class="caps">README</span> to get the plugin up and running. We&#8217;ll start off with an easy one. Let&#8217;s look at adding authentication to our <span class="caps">REST API</span>. Be sure to require authentication your controller:</p>
<code lang="ruby">
before_filter :login_required
</code>
<p>That&#8217;s more or less it. Here&#8217;s where the magic happens (you&#8217;ll find this in <code>lib/authenticated_system.rb</code>):</p>
<code lang="ruby">
def login_required
username, passwd = get_auth_data
self.current_user ||= User.authenticate(username, passwd, current_subdomain) || :false if username &#38;&#38; passwd
logged_in? &#38;&#38; authorized? ? true : access_denied
end
def get_auth_data
user, pass = nil, nil
# extract authorisation credentials 
if request.env.has_key? 'X-HTTP_AUTHORIZATION' 
# try to get it where mod_rewrite might have put it 
authdata = request.env['X-HTTP_AUTHORIZATION'].to_s.split 
elsif request.env.has_key? 'HTTP_AUTHORIZATION' 
# this is the regular location 
authdata = request.env['HTTP_AUTHORIZATION'].to_s.split  
end 
# at the moment we only support basic authentication 
if authdata &#38;&#38; authdata[0] == 'Basic' 
user, pass = Base64.decode64(authdata[1]).split(':')[0..1] 
end 
return [user, pass] 
end
def access_denied
respond_to do |accepts|
accepts.html do
store_location
redirect_to :controller =&gt; '/sessions', :action =&gt; 'new'
end
accepts.xml do
headers["Status"]           = "Unauthorized" 
headers["WWW-Authenticate"] = %(Basic realm="Outlandish API")
render :text =&gt; "Could't authenticate you", :status =&gt; '401 Unauthorized'
end
end
false
end
</code>
<p>What this does have your login_required before_filter re-grab your login/password if its available via <span class="caps">HTTP </span>Basic Auth. If you try to login through <span class="caps">XML</span> and you&#8217;re denied, it&#8217;ll return the proper <code>401 Unauthorized</code> status.</p>
<p>Adding the same authentication functionality to your <span class="caps">RSS</span> feeds is pretty simple. The only change you need to make is to make sure that the proper status is returned for your <span class="caps">RSS</span> requests if the login fails. Just modify the access_denied method:</p>
<code lang="ruby">
def access_denied
respond_to do |accepts|
accepts.html do
store_location
redirect_to :controller =&gt; '/sessions', :action =&gt; 'new'
end
accepts.xml do
headers["Status"]           = "Unauthorized" 
headers["WWW-Authenticate"] = %(Basic realm="Outlandish API")
render :text =&gt; "Could't authenticate you", :status =&gt; '401 Unauthorized'
end
accepts.rss do
headers["Status"]           = "Unauthorized" 
headers["WWW-Authenticate"] = %(Basic realm="Outlandish RSS Feed")
render :text =&gt; "Could't authenticate you", :status =&gt; '401 Unauthorized'
end
end
false
end
</code>
<p>There you go, that takes care of it. Simple Basic <span class="caps">HTTP </span>Auth for your <span class="caps">API</span> and feed, all mixed in with the authentication goodness the rest of your app gets with restful_authentication.</p>
<img src="http://feeds.integralimpressions.com/~r/integralthoughts/code/~4/188750276" height="1" width="1"/>]]></content:encoded>
<pubDate>Thu, 19 Oct 2006 18:12:00 -0700</pubDate>
<guid isPermaLink="false">http://integralimpressions.com/blog/authentication_for_your_api_or_feed</guid>
<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=integralthoughts/code&amp;itemurl=http%3A%2F%2Fintegralimpressions.com%2Fblog%2Fauthentication_for_your_api_or_feed</feedburner:awareness><feedburner:origLink>http://integralimpressions.com/blog/authentication_for_your_api_or_feed</feedburner:origLink></item>
<item>
<title>SimpleRCSS Plugin</title>
<link>http://feeds.integralimpressions.com/~r/integralthoughts/code/~3/188750277/simplercss_plugin</link>
<content:encoded><![CDATA[
<p>I needed a way to embed ruby into my stylesheets. I primarily wanted the ability to develop helper methods to save myself typing on some of the repetitive <span class="caps">CSS</span> techniques. <a href="http://blog.hasmanythrough.com/articles/2006/03/23/dirt-simple-rcss-templates">Josh Susser</a> came up with a very easy way to accomplish this. I took this idea a step further and turned it into a plugin so I could re-use it for other  project. I figured I&#8217;d make it available to the public in case others found it useful. Feel free to provide feedback on how to improve this plugin.</p>
<h3>Installation</h3>
<p>Really simple. First install the plugin:</p>
<p><code>./script/plugin install -x http://svn.integralserver.com/plugins/simple_rcss</code></p>
<p>Then, just add this to your <code>config/routes.rb</code>:</p>
<p><code>map.rcss 'stylesheets/:rcss.css', :controller =&gt; 'stylesheets', :action =&gt; 'rcss'</code></p>
<h3>Usage</h3>
<p><span class="caps">RCSS</span> files are placed in:</p>
<pre>
$app_root
views/
stylesheets/
stylesheet_1.rcss
stylesheet_2.rcss
</pre>
<p>While in production mode, this plugin will automatically cache your stylesheets into <code>public/stylesheets</code>. If you would like to pre-cache your stylesheets, you can do so with the included rake task:<br /><code>rake rcss:create_cache</code></p>
<p>There are a few other rake tasks available to you as well:</p>
<pre>
rcss:remove_cache
rcss:update_cache
</pre>
<p>If you have any files in <code>public/stylesheets/</code> which do not originate from <code>app/views/stylesheets</code>, you will lose them if you use <code>rcss_remove_cache</code> and <code>rcss_update_cache</code>. The safest thing to do is manage all your stylesheets in <code>app/views/stylesheets</code>. You can migrate over existing stylesheets using:</p>
<p><code>rake rcss:from_css</code></p>
<p>There is also a generator task to generate stylesheets for you:<br /><code>./script/generate stylesheet Application</code></p>
<p>which will create:</p>
<pre>
$app_root
app/
views/
stylesheets/
application.rcss
</pre>
<p>You can also call certain stylesheets using :defaults from within the stylesheet_link_tag helper:<br /><code>stylesheet_link_tag :defaults</code><br />This will automatically include an <code>application.rcss</code> as well as <code>#{controller.controller_name}.rcss</code> if they exist.</p>
<p>That pretty much covers the basics. I&#8217;ve used this on a few projects so far and it&#8217;s been working out just fine. My next step is to begin to extract commonly used code from my stylesheets and make those available through helper methods. If you have any suggestions for these, feel free to send them my way.</p>
<img src="http://feeds.integralimpressions.com/~r/integralthoughts/code/~4/188750277" height="1" width="1"/>]]></content:encoded>
<pubDate>Thu, 19 Oct 2006 18:12:00 -0700</pubDate>
<guid isPermaLink="false">http://integralimpressions.com/blog/simplercss_plugin</guid>
<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=integralthoughts/code&amp;itemurl=http%3A%2F%2Fintegralimpressions.com%2Fblog%2Fsimplercss_plugin</feedburner:awareness><feedburner:origLink>http://integralimpressions.com/blog/simplercss_plugin</feedburner:origLink></item>
<item>
<title>SSL with Rails and Lighttpd behind Apache</title>
<link>http://feeds.integralimpressions.com/~r/integralthoughts/code/~3/188750278/ssl_with_rails_and_lighttpd_behind_apache</link>
<content:encoded><![CDATA[
<p>Here&#8217;s another one for the books. I was using the <a href="http://dev.rubyonrails.org/svn/rails/plugins/ssl_requirement">ssl_requirement</a> plugin for for the order section of the <a href="http://out.landi.sh">Outlandish</a> product site. The concept is pretty simple. This pretty much sums it up:</p>
<code lang="ruby">
def ensure_proper_protocol
return true if ssl_allowed?
if ssl_required? &#38;&#38; !request.ssl?
redirect_to "https://" + request.host + request.request_uri
return false
elsif request.ssl? &#38;&#38; !ssl_required?
redirect_to "http://" + request.host + request.request_uri
return false
end
end
</code>
<p>The problem I was having is it would redirect to the <code>https://</code> protocol, but be received as <code>http://</code> in the logs. This would cause an infinite loop of redirects until it finally got tired and broke.</p>
<h3>SSL on Apache vs. Lighttpd</h3>
<p>When you have Apache set up as a proxy to lighttpd, you have 2 options for <span class="caps">SSL</span>. You can either set up <span class="caps">SSL</span> on Apache, or Lighttpd. <a href="http://help.textdrive.com/index.php?pg=kb.page&#38;id=290">Others</a> have already done a good job of explaining this, so I won&#8217;t get into it. Just know that our <span class="caps">SSL</span> is setup on Apache.</p>
<p>The problem is that in this scenario, lighttpd is completely unaware of the <span class="caps">SSL</span> request and handles everything as a standard request with the <code>http://</code> protocol.</p>
<h3>The Solution</h3>
<p>What I needed was a way for Apache somehow tell Rails that the request was indeed an <span class="caps">SSL</span> request. Turns out that&#8217;s very easy to do. All you have to do is add the following line to Apache&#8217;s vhost entry:</p>
<p><code>RequestHeader set X_FORWARDED_PROTO 'https'</code></p>
<p>That&#8217;s it! The magic happens automatically (as I&#8217;m finding to be common with Rails) thanks to this little snippet in <code>request.rb</code>:</p>
<code lang="ruby">
def ssl?
@env['HTTPS']  'on' || @env['HTTP_X_FORWARDED_PROTO']  &#8216;https&#8217;<br />end<br /></code>
<img src="http://feeds.integralimpressions.com/~r/integralthoughts/code/~4/188750278" height="1" width="1"/>]]></content:encoded>
<pubDate>Thu, 19 Oct 2006 18:11:00 -0700</pubDate>
<guid isPermaLink="false">http://integralimpressions.com/blog/ssl_with_rails_and_lighttpd_behind_apache</guid>
<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=integralthoughts/code&amp;itemurl=http%3A%2F%2Fintegralimpressions.com%2Fblog%2Fssl_with_rails_and_lighttpd_behind_apache</feedburner:awareness><feedburner:origLink>http://integralimpressions.com/blog/ssl_with_rails_and_lighttpd_behind_apache</feedburner:origLink></item>
<item>
<title>Changes to Spawner in Edge Rails</title>
<link>http://feeds.integralimpressions.com/~r/integralthoughts/code/~3/188750279/changes_to_spawner_in_edge_rails</link>
<content:encoded><![CDATA[
<p>I recently switched one of my apps over to edge rails and was thrown for a bit of a loop when I went to go deploy it on our production server. A quick Google search didn&#8217;t turn up much help, so I figured I&#8217;d post my findings here.</p>
<p>First of all, it seems like spawner/reaper are now using pid files found in tmp/pids to reference the fcgi/mongrel (yes mongrel too, more on that in a bit&#8230;) processes.</p>
<p>While I prefer this, things get a little tricky when using <a href="http://manuals.rubyonrails.com/read/book/17">Capistrano</a>. The challenge is that you want your <span class="caps">PID</span> files to persist accross releases. The trick is to setup the <span class="caps">PID</span>&#8217;s as a shared resource across all releases. Add these tasks to your Capistrano deploy recipe:</p>
<code lang="ruby">
desc "Share PIDs accross releases" 
task :after_setup do
run "mkdir -p -m 755 #{shared_path}/tmp/pids" 
end
desc "Link to shared PIDs" 
task :after_update_code do
run &lt;&lt;-CMD
rm -rf #{release_path}/tmp/pids
ln -nfs #{deploy_to}/#{shared_dir}/tmp/pids #{release_path}/tmp/pids
CMD
end
</code>
<p>The next issue that I ran into was when Capistrano went to restart my app, it tried to start a <a href="http://mongrel.rubyforge.org/">Mongrel</a> process rather than my normal <span class="caps">FCGI</span> process. According to the <a href="http://dev.rubyonrails.org/changeset/4570">changelog</a>, spawner now prefers Mongrel by default.</p>
<p>I have yet to switch over to Mongrel like all the <a href="http://weblog.rubyonrails.org/2006/6/11/rails-system-back-on-track">cool kids</a>, so I had to figure out a way to get spawner back to <span class="caps">FCGI</span>. Here are the examples straight from the documentation:</p>
<code lang="ruby">
spawner               # starts instances on 8000, 8001, and 8002 using Mongrel if available 
spawner fcgi          # starts instances on 8000, 8001, and 8002 using FCGI 
spawner mongrel -i 5  # starts instances on 8000, 8001, 8002, 8003, and 8004 using Mongrel 
spawner -p 9100 -i 10 # starts 10 instances counting from 9100 to 9109 using Mongrel if available 
spawner -p 9100 -r 5  # starts 3 instances counting from 9100 to 9102 and attempts start them every 5 seconds
</code>
<p>That pretty much wraps it up. Once I figured out what was going on, and made a few slight adjustments, everything was back up and running as it should be.</p>
<img src="http://feeds.integralimpressions.com/~r/integralthoughts/code/~4/188750279" height="1" width="1"/>]]></content:encoded>
<pubDate>Thu, 19 Oct 2006 18:06:00 -0700</pubDate>
<guid isPermaLink="false">http://integralimpressions.com/blog/changes_to_spawner_in_edge_rails</guid>
<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=integralthoughts/code&amp;itemurl=http%3A%2F%2Fintegralimpressions.com%2Fblog%2Fchanges_to_spawner_in_edge_rails</feedburner:awareness><feedburner:origLink>http://integralimpressions.com/blog/changes_to_spawner_in_edge_rails</feedburner:origLink></item>
<item>
<title>ToCSV Plugin</title>
<link>http://feeds.integralimpressions.com/~r/integralthoughts/code/~3/188750280/tocsv_plugin</link>
<content:encoded><![CDATA[
<p>I had a need to do a very simple <span class="caps">CSV</span> of a collection of ActiveRecord objects. Very similar to doing a <span class="caps">CSV</span> export of a MySQL table through phpMyAdmin or something like that. I really liked the cleanliness of the to_xml method, and wanted somthing similar&#8230; so I wrote a plugin for it. This plugin provides support for responding to the <span class="caps">CSV</span> format, as well as exporting a collection of ActiveRecord objects to <span class="caps">CSV</span>.</p>
<h3>Installation</h3>
<code lang="ruby">
./script/plugin install -x http://svn.integralserver.com/plugins/to_csv
</code>
<h3>Usage</h3>
<p>You can simply take a collection of ActiveRecord objects and apply the to_csv method to them:</p>
<code lang="ruby">
@users = User.find(:all)
@users.to_csv
</code>
<p>Here are some different options:</p>
<code lang="ruby">
# Don't put a header row into the CSV file
@users.to_csv(:header =&gt; false)
# Exclude the id and created_at columns
@users.to_csv(:except =&gt; ['id','created_at'])
# Only include the login and password columns
@users.to_csv(:only =&gt; ['login','password'])
</code>
<p>For a more <span class="caps">RES</span>Tful way of exporting a <span class="caps">CSV</span>, do something like this in your controller:</p>
<code lang="ruby">
respond_to do |wants|
wants.csv do
render :text =&gt; @users.to_csv
response.headers['Content-Type'] = 'text/csv; charset=iso-8859-1; header=present'
response.headers['Content-Disposition'] = "attachment; filename=users_#{Time.now.strftime("%m-%d-%Y")}.csv" 
end
end
</code>
<h3>Go forth</h3>
<p>That wasn&#8217;t too difficult now was it? I wrote this plugin for a very specific purpose and it fits my needs just fine. However, feel free to make suggestions. I&#8217;m open to adding additional functionality where its both reasonable and appropriate.</p>
<p><a href="http://digg.com/programming/New_Rails_Plugin_to_csv">Digg this article</a></p>
<img src="http://feeds.integralimpressions.com/~r/integralthoughts/code/~4/188750280" height="1" width="1"/>]]></content:encoded>
<pubDate>Fri, 01 Sep 2006 18:12:00 -0700</pubDate>
<guid isPermaLink="false">http://integralimpressions.com/blog/tocsv_plugin</guid>
<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetItemData?uri=integralthoughts/code&amp;itemurl=http%3A%2F%2Fintegralimpressions.com%2Fblog%2Ftocsv_plugin</feedburner:awareness><feedburner:origLink>http://integralimpressions.com/blog/tocsv_plugin</feedburner:origLink></item>
<feedburner:awareness>http://api.feedburner.com/awareness/1.0/GetFeedData?uri=integralthoughts/code</feedburner:awareness></channel>
</rss>
