<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
 
  <title>Scott Motte</title>
  <subtitle>codes a lot</subtitle>
  
  <link href="http://scottmotte.com/" />
  <updated>2009-10-03T19:03:22-07:00</updated>
  <author>
    <name>Scott Motte</name>
    <email>scott@scottmotte.com</email>
  </author>
  <id>http://scottmotte.com/</id>
  
  <link rel="self" href="http://feeds.feedburner.com/scottmotte" type="application/atom+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry>
    <title>I am moving this blog to SpitfireSky.com/blog</title>
    <link href="http://feedproxy.google.com/~r/scottmotte/~3/gvF80wKWkxI/221.html" />
    <id>tag:scottmotte.com,2009-08-29 15:23:36:2009</id>
    <updated>2009-08-29 15:23:36</updated>
    <content type="html">&lt;h2&gt;I am moving this blog to SpitfireSky.com/blog&lt;/h2&gt;
&lt;p&gt;Yep, &lt;strong&gt;I&amp;#8217;ve decided to move this blog&lt;/strong&gt;. Please visit &lt;a href="http://spitfiresky.com/blog"&gt;http://spitfiresky.com/blog&lt;/a&gt; or subscribe to &lt;a href="http://feeds.feedburner.com/spitfiresky"&gt;http://feeds.feedburner.com/spitfiresky&lt;/a&gt; to receive my latest posts.&lt;/p&gt;
&lt;p&gt;I have a couple good posts on my new blog already &amp;#8211; &lt;a href="http://spitfiresky.com/blog/recap-of-my-sdruby-presentation-on-mongodb.html"&gt;Recap of my presentation on mongodb&lt;/a&gt;, and &lt;a href="http://spitfiresky.com/blog/my-server-setup.html"&gt;my server setup&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Please consider subscribing to my new blog and thank you for being a reader.&lt;/p&gt;
&lt;p&gt;Best,&lt;br /&gt;
Scott Motte&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/scottmotte/~4/gvF80wKWkxI" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://scottmotte.com/archives/221.html</feedburner:origLink></entry>
  
  <entry>
    <title>Couchrest Couchdb thumbnail generation with Mini_Magick and Merb (or Rails)</title>
    <link href="http://feedproxy.google.com/~r/scottmotte/~3/eOg7-7Fx_jw/220.html" />
    <id>tag:scottmotte.com,2009-05-31 16:04:53:2009</id>
    <updated>2009-05-31 16:04:53</updated>
    <content type="html">&lt;h2&gt;Couchrest Couchdb thumbnail generation with Mini_Magick and Merb (or Rails)&lt;/h2&gt;
&lt;p&gt;Thumbnails &amp;#8211; or avatars &amp;#8211; are a standard part of many web apps. Paperclip has made things super easy for active record and datamapper. Here is how I accomplished similar &amp;#8211; but basic &amp;#8211; thumbnail generation for couchdb. The end solution is RESTful, good for my needs, and hopefully good for your needs too.&lt;/p&gt;
&lt;p&gt;You should know that couchdb supports inline attachments and I opted for that route rather than store the images in a file folder like paperclip does. I felt this was more inline with the couchdb way of doing things.&lt;/p&gt;
&lt;h3&gt;Dependencies&lt;/h3&gt;
&lt;p&gt;Begin by installing mini_magick&lt;br /&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;&lt;span class="no"&gt;1&lt;/span&gt; sudo gem install mini_magick&lt;br /&gt;
&lt;div class="CodeRay"&gt;&lt;br /&gt;
&lt;pre&gt;&lt;span class="no"&gt;1&lt;/span&gt; sudo gem install mini_magick&lt;/pre&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;Or add mini_magick to dependencies.rb &lt;br /&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;&lt;span class="no"&gt;1&lt;/span&gt; dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;mini_magick&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;1.2.5&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div class="CodeRay"&gt;&lt;br /&gt;
&lt;pre&gt;&lt;span class="no"&gt;1&lt;/span&gt; dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;mini_magick&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;1.2.5&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/notextile&gt;&lt;br /&gt;
&lt;small&gt;I&amp;#8217;m using Merb. The setup for rails would be to use config.gem mini_magick I believe.&lt;/small&gt;&lt;/p&gt;
&lt;h3&gt;Setup the view&lt;/h3&gt;
&lt;p&gt;Place the avatar uploading mechanism in it&amp;#8217;s own form. Use the /users/update_avatar POST action to process the thumbnails.&lt;/p&gt;
&lt;script src="http://gist.github.com/121965.js"&gt;&lt;/script&gt;&lt;h3&gt;Setup the users.rb update_avatar POST action and route&lt;/h3&gt;
&lt;p&gt;The update_avatar action will process the &amp;#8216;avatar&amp;#8217; image file using the custom &amp;#8216;update_avatar_images&amp;#8217; method. If you are on rails, you will have to pass params[:avatar] here.&lt;/p&gt;
&lt;p&gt;Additionally, the avatar route/action is defined in users.rb also. This will allow us to display the thumbnails restfully via /user/scottmotte/avatar &amp;amp; /user/scottmotte/avatar?style=mini&lt;/p&gt;
&lt;p&gt;Furthermore, you will see that my validation is not in the model as it ideally should be. I haven&amp;#8217;t figured out how to tackle this yet based on how the couchdb attachments work inline as an array.&lt;/p&gt;
&lt;script src="http://gist.github.com/121962.js"&gt;&lt;/script&gt;&lt;h3&gt;Setup the user.rb model to process the thumbnails&lt;/h3&gt;
&lt;p&gt;Rather than pick out the little pieces of the user.rb model that are related to the update_avatar action in users.rb I&amp;#8217;m just posting the entire model.&lt;/p&gt;
&lt;p&gt;The key method to examine is the update_avatar_images and it&amp;#8217;s cousin resize_and_crop &amp;#8211; which resizes the uploaded avatar to a square.&lt;/p&gt;
&lt;p&gt;The strange AppConfig array I am using there is from my config/app_config/settings.yml file from merbjedi&amp;#8217;s &lt;a href="http://github.com/merbjedi/app_config/tree/master"&gt;merb_app_config&lt;/a&gt;. It looks like this the following but you could just as easily define your own array or list each upload separately.&lt;/p&gt;
&lt;p&gt;The put_attachment method is from couchrest and puts the images to the couchdb user document.&lt;/p&gt;
&lt;script src="http://gist.github.com/121979.js"&gt;&lt;/script&gt;&lt;p&gt;Now when a user uploads an avatar image, it creates an inline original.png, thumb.png, and mini.png. And the are accessible via /users/scottmotte/avatar?style=mini&lt;/p&gt;
&lt;p&gt;That&amp;#8217;s how I did things. Let me know if you have a better way. A gem would be ideal. Maybe I&amp;#8217;ll morph this into a gem if I find myself repeating it enough.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/scottmotte/~4/eOg7-7Fx_jw" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://scottmotte.com/archives/220.html</feedburner:origLink></entry>
  
  <entry>
    <title>Add custom methods to Spreedly gem</title>
    <link href="http://feedproxy.google.com/~r/scottmotte/~3/RAIS6G1y0js/219.html" />
    <id>tag:scottmotte.com,2009-04-20 21:54:2009</id>
    <updated>2009-04-20 21:54</updated>
    <content type="html">&lt;h2&gt;Add custom methods to Spreedly gem&lt;/h2&gt;
&lt;p&gt;I am using the spreedly gem again rather than my own custom Subscriber.rb model. I figured out how I could tack on extra methods to the Spreedly::Subscriber class. You just create a model/class called Spreedly::Subscriber. This is probably rudimentary knowledge for many, but for me it wasn&amp;#8217;t. Sometimes it sucks to have a business background. =)&lt;/p&gt;
&lt;p&gt;I needed to add the activate_free_trial method for the mocking portion of the spreedly gem. I did it by creating a model named spreedly_subscriber.rb and added the following code.&lt;/p&gt;
&lt;script src="http://gist.github.com/102593.js"&gt;&lt;/script&gt;&lt;img src="http://feeds.feedburner.com/~r/scottmotte/~4/RAIS6G1y0js" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://scottmotte.com/archives/219.html</feedburner:origLink></entry>
  
  <entry>
    <title>Using Spreedly with Merb via HTTParty</title>
    <link href="http://feedproxy.google.com/~r/scottmotte/~3/1j2OOxY1hio/218.html" />
    <id>tag:scottmotte.com,2009-04-20 21:50:55:2009</id>
    <updated>2009-04-20 21:50:55</updated>
    <content type="html">&lt;h2&gt;Using Spreedly with Merb via HTTParty&lt;/h2&gt;
&lt;p&gt;This is almost completely stolen from the spreedly gem, but I added some custom methods and didn&amp;#8217;t want to be a slave to the gem. It allows you to do things like Subscriber.create!(id, email=nil, screen_name=nil) &amp;amp; Subscriber.activate_free_trial. I was using &lt;a href="http://scottmotte.com/archives/206.html"&gt;active resource with merb&lt;/a&gt; previously but Nathaniel&amp;#8217;s spreedly gem convinced me to use &lt;a href="http://github.com/jnunemaker/httparty/tree/master"&gt;HTTParty&lt;/a&gt; instead.&lt;/p&gt;
&lt;p&gt;To use, create a file in app/models/subscriber.rb and paste the following in. I am using &lt;a href="http://github.com/merbjedi/app_config/tree/master"&gt;AppConfig&lt;/a&gt; for the settings. (sudo gem install merb_app_config).&lt;/p&gt;
&lt;script src="http://gist.github.com/98752.js"&gt;&lt;/script&gt;&lt;p&gt;Here&amp;#8217;s some example usage.&lt;/p&gt;
&lt;script src="http://gist.github.com/98754.js"&gt;&lt;/script&gt;&lt;img src="http://feeds.feedburner.com/~r/scottmotte/~4/1j2OOxY1hio" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://scottmotte.com/archives/218.html</feedburner:origLink></entry>
  
  <entry>
    <title>Unobtrusive Ajax with Merb, Datamapper, and jQuery</title>
    <link href="http://feedproxy.google.com/~r/scottmotte/~3/SpM5XUtusdY/217.html" />
    <id>tag:scottmotte.com,2009-04-20 21:00:54:2009</id>
    <updated>2009-04-20 21:00:54</updated>
    <content type="html">&lt;h2&gt;Unobtrusive Ajax with Merb, Datamapper, and jQuery&lt;/h2&gt;
&lt;p&gt;This article describes how to add ajax to your merb &amp;amp; datamapper application using jquery. It uses an example from my own project investapp to create a &amp;#8216;more&amp;#8217; link similar to twitter&amp;#8217;s.&lt;/p&gt;
&lt;p&gt;First, install the agnostic branch of will_paginate. This isn&amp;#8217;t available as a public gem yet, but &lt;a href="http://holmwood.id.au/~lindsay/"&gt;auxesis&lt;/a&gt; maintains a working fork of &lt;a href="http://github.com/auxesis/will_paginate/tree/master"&gt;will_paginate agnostic&lt;/a&gt;. Add the following to dependencies.rb&lt;br /&gt;
&lt;script src="http://gist.github.com/98757.js"&gt;&lt;/script&gt;&lt;br /&gt;
&lt;script src="http://gist.github.com/98758.js"&gt;&lt;/script&gt;&lt;/p&gt;
&lt;p&gt;Use will_paginate just like you do in rails applications. Here I&amp;#8217;m paginating the messages. I&amp;#8217;m also providing .js to the @display messages. Rails does this with the respond_to block.&lt;br /&gt;
&lt;script src="http://gist.github.com/98759.js"&gt;&lt;/script&gt;&lt;/p&gt;
&lt;p&gt;Add the will_paginate helper links to your view.&lt;br /&gt;
&lt;script src="http://gist.github.com/98760.js"&gt;&lt;/script&gt;&lt;/p&gt;
&lt;p&gt;Now for the jQuery. First and foremost make sure you are including jquery in your view.&lt;br /&gt;
&lt;script src="http://gist.github.com/98761.js"&gt;&lt;/script&gt;&lt;/p&gt;
&lt;p&gt;Setup the ajax using jquery. There is a decent amount going on here.&lt;/p&gt;
&lt;p&gt;Firstly, create a getWithAjax jquery method. Thanks goes to &lt;a href="http://railscasts.com/episodes/136-jquery"&gt;Ryan Bates jQuery episode&lt;/a&gt; for this. This basically tells merb to use the index.js.erb file instead of the index.html.erb file.&lt;/p&gt;
&lt;p&gt;Secondly, inside the document ready is code that takes the default will_paginate helper html code and hides all the Prev, 1,2,3,4, Next links, replaces, them with the text &amp;#8216;More&amp;#8217; like on twitter, and makes them ajaxifiable via a class=&amp;#8216;more-entries&amp;#8217; attribute.&lt;/p&gt;
&lt;p&gt;Thirdly, the $(&amp;#8220;div.pagination a[rel=&amp;#8216;next&amp;#8217;]&amp;#8221;).not(&amp;#8216;.next_page&amp;#8217;).show(); makes sure only the next page link is viewable.&lt;br /&gt;
&lt;script src="http://gist.github.com/98762.js"&gt;&lt;/script&gt;&lt;/p&gt;
&lt;p&gt;Finally, we just have to tell merb what to do once the link is clicked and goes to index.js.erb.&lt;/p&gt;
&lt;p&gt;Our messages/index action just got hit and returned us @messages. The first //append the partials section appends the next batch of 15 messages below the previous 15 messages &amp;#8211; just how twitter does.&lt;/p&gt;
&lt;p&gt;The next line shows the next &amp;#8216;next_page&amp;#8217; link so we will be able to click next again.&lt;/p&gt;
&lt;p&gt;And the final line, hides the link we just clicked.&lt;br /&gt;
&lt;script src="http://gist.github.com/98763.js"&gt;&lt;/script&gt;&lt;/p&gt;
&lt;p&gt;The end.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/scottmotte/~4/SpM5XUtusdY" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://scottmotte.com/archives/217.html</feedburner:origLink></entry>
  
  <entry>
    <title>Merb and Datamapper Single Table Inheritance</title>
    <link href="http://feedproxy.google.com/~r/scottmotte/~3/Gg9TePKHd1A/216.html" />
    <id>tag:scottmotte.com,2009-04-09 14:43:02:2009</id>
    <updated>2009-04-09 14:43:02</updated>
    <content type="html">&lt;h2&gt;Merb and Datamapper Single Table Inheritance&lt;/h2&gt;
&lt;p&gt;To begin add the Discriminator property to your model. I will be using User as my main model, and there will be an administrator and member model to inherit from it.&lt;/p&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;&lt;span class="c"&gt;# app/models/user.rb&lt;/span&gt;
&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;User&lt;/span&gt;
        include &lt;span class="co"&gt;DataMapper&lt;/span&gt;::&lt;span class="co"&gt;Resource&lt;/span&gt;
         ..
        property &lt;span class="sy"&gt;:type&lt;/span&gt;, &lt;span class="co"&gt;Discriminator&lt;/span&gt;
&lt;span class="r"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;rake db:automigrate&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Next, add your additional models based that will use the single table inheritance. You could create a separate models/model_name.rb for these, but I just lump them in with models/user.rb&lt;/p&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;&lt;span class="c"&gt;# app/models/user.rb&lt;/span&gt;
&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;User&lt;/span&gt;
        include &lt;span class="co"&gt;DataMapper&lt;/span&gt;::&lt;span class="co"&gt;Resource&lt;/span&gt;
        ..
        property &lt;span class="sy"&gt;:type&lt;/span&gt;, &lt;span class="co"&gt;Discriminator&lt;/span&gt;
        ..
&lt;span class="r"&gt;end&lt;/span&gt;

&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;Editor&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;User&lt;/span&gt;; &lt;span class="r"&gt;end&lt;/span&gt;
&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;Administrator&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;Editor&lt;/span&gt;; &lt;span class="r"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now you can run commands like User.all, Administrator. all, and Editor.all. And to create a user with an Administrator role do something like the following.&lt;/p&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;&lt;span class="co"&gt;User&lt;/span&gt;.create(&lt;span class="sy"&gt;:login&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;scottmotte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:password&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:password_confirmation&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:email&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;scott@scottmotte.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:type&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;Administrator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Finally, you need to add routes for the Editor and Administrator otherwise resource(user) will give you serious generation errors.&lt;/p&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;&lt;span class="c"&gt;# router.rb&lt;/span&gt;
resources &lt;span class="sy"&gt;:users&lt;/span&gt;
resources &lt;span class="sy"&gt;:administrators&lt;/span&gt;, &lt;span class="sy"&gt;:controller&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:users&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/scottmotte/~4/Gg9TePKHd1A" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://scottmotte.com/archives/216.html</feedburner:origLink></entry>
  
  <entry>
    <title>How to remove sources from your gem list</title>
    <link href="http://feedproxy.google.com/~r/scottmotte/~3/tGdhUhogH28/215.html" />
    <id>tag:scottmotte.com,2009-03-30 13:23:52:2009</id>
    <updated>2009-03-30 13:23:52</updated>
    <content type="html">&lt;h2&gt;How to remove sources from your gem list&lt;/h2&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;&lt;span class="no"&gt;1&lt;/span&gt; gem sources -r http&lt;span class="sy"&gt;:/&lt;/span&gt;/example.com
&lt;/pre&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/scottmotte/~4/tGdhUhogH28" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://scottmotte.com/archives/215.html</feedburner:origLink></entry>
  
  <entry>
    <title>Create a merb slice with jeweler</title>
    <link href="http://feedproxy.google.com/~r/scottmotte/~3/s8aii7QlXmc/214.html" />
    <id>tag:scottmotte.com,2009-03-27 15:16:38:2009</id>
    <updated>2009-03-27 15:16:38</updated>
    <content type="html">&lt;h2&gt;Create a merb slice with jeweler&lt;/h2&gt;
&lt;p&gt;A slice is just a gem so we can create and manage our slice by starting with &lt;a href="http://technicalpickles.github.com/posts/craft-the-perfect-gem-with-jeweler.html"&gt;jeweler&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Jeweler&lt;/h3&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;gem sources -a http://gems.github.com
sudo gem install technicalpickles-jeweler
git config --global user.email johndoe@example.com
git config --global user.name 'John Doe'
git config --global github.user johndoe
git config --global github.token 55555555555555

jeweler --create-repo --summary &amp;quot;Sandy Koufax Slice&amp;quot; sandy_koufax_slice
&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Slice&lt;/h3&gt;
&lt;p&gt;Because jeweler is a bit opinionated and creates a structure for us, create your slice in a tmp directory and then copy the app, config, spec, etc files over to our sand_koufax_slice jeweler structure. Yep, a bit sloppy, and there is a more elegant way, but for now copy and paste worked well for me.&lt;/p&gt;
&lt;p&gt;Be careful with the Rakefile. It should look something like this:&lt;br /&gt;
&lt;script src="http://gist.github.com/88052.js"&gt;&lt;/script&gt;&lt;/p&gt;
&lt;p&gt;Once you&amp;#8217;ve got standard files copied over let&amp;#8217;s start creating the slice. To do so, we first need to set the slice up to work in development mode (this bit of hackery will eventually go away in Merb 1.2 with embeddable apps. I&amp;#8217;m excited for that.).&lt;/p&gt;
&lt;p&gt;1. Add the following to config/init.rb&lt;/p&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;require &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;config/dependencies.rb&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;
 
use_orm &lt;span class="sy"&gt;:datamapper&lt;/span&gt;
use_test &lt;span class="sy"&gt;:rspec&lt;/span&gt;
use_template_engine &lt;span class="sy"&gt;:erb&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;2. Create config/dependencies.rb&lt;/p&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;&lt;span class="c"&gt;# dependencies are generated using a strict version, don't forget to edit the dependency versions when upgrading.&lt;/span&gt;
merb_gems_version = &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;1.0.10&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
dm_gems_version   = &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;0.9.10&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
do_gems_version   = &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;0.9.11&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class="c"&gt;# For more information about each component, please read http://wiki.merbivore.com/faqs/merb_components&lt;/span&gt;
dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;merb-core&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, merb_gems_version 
dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;merb-action-args&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, merb_gems_version
dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;merb-assets&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, merb_gems_version  
dependency(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;merb-cache&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, merb_gems_version) &lt;span class="r"&gt;do&lt;/span&gt;
  &lt;span class="co"&gt;Merb&lt;/span&gt;::&lt;span class="co"&gt;Cache&lt;/span&gt;.setup &lt;span class="r"&gt;do&lt;/span&gt;
    register(&lt;span class="co"&gt;Merb&lt;/span&gt;::&lt;span class="co"&gt;Cache&lt;/span&gt;::&lt;span class="co"&gt;FileStore&lt;/span&gt;) &lt;span class="r"&gt;unless&lt;/span&gt; &lt;span class="co"&gt;Merb&lt;/span&gt;.cache
  &lt;span class="r"&gt;end&lt;/span&gt;
&lt;span class="r"&gt;end&lt;/span&gt;
dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;merb-helpers&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, merb_gems_version 
dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;merb-mailer&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, merb_gems_version  
dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;merb-slices&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, merb_gems_version  
dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;merb-auth-core&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, merb_gems_version
dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;merb-auth-more&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, merb_gems_version
dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;merb-auth-slice-password&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, merb_gems_version
dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;merb-param-protection&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, merb_gems_version
dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;merb-exceptions&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, merb_gems_version

dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;data_objects&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, do_gems_version
dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;do_mysql&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, do_gems_version &lt;span class="c"&gt;# If using another database, replace this&lt;/span&gt;
dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;dm-core&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, dm_gems_version         
dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;dm-aggregates&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, dm_gems_version   
dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;dm-migrations&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, dm_gems_version   
dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;dm-timestamps&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, dm_gems_version   
dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;dm-types&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, dm_gems_version        
dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;dm-validations&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, dm_gems_version  
dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;dm-serializer&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, dm_gems_version   

dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;merb_datamapper&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, merb_gems_version
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strike&gt;3. Bundle the dependencies&lt;/strike&gt;&lt;/p&gt;
&lt;p&gt;This turned out to be a big headache when it came to installing the gem. Just use the gems on your machine and install with sudo gem install merb as necessary.&lt;/p&gt;
&lt;p&gt;&lt;strike&gt;Bundling our dependencies makes development easier &amp;#8211; especially if we want someone else to work on our slice. But the only way to bundle is to get thor in our slice, and it is not there by default like in a merb app. So let&amp;#8217;s add it.&lt;/p&gt;
&lt;p&gt;To get the thor tasks go into a tmp directory and generate a fresh merb application, then just use copy and paste to move /tasks folder and its contents into your slice. It should look something like this:&lt;br /&gt;
- tasks/&lt;br /&gt;
	doc.thor&lt;br /&gt;
	merb.thor/&lt;br /&gt;
		app_script.rb&lt;br /&gt;
		common.rb&lt;br /&gt;
		gem_ext.rb&lt;br /&gt;
		main.thor&lt;br /&gt;
		ops.rb&lt;br /&gt;
		utils.rb&lt;/p&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;thor merb:gem:install
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now you should be able to run bin/slice and bin/rake to run and test your slice.&lt;br /&gt;
&lt;/strike&gt;&lt;/p&gt;
&lt;p&gt;4. Development and Test Database&lt;/p&gt;
&lt;p&gt;Create config/database.yml and put in the following content&lt;br /&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;development:
  adapter:  sqlite3
  database: sample_development.db
test:
  adapter:  sqlite3
  database: sample_test.db
production:
  adapter:  sqlite3
  database: production.db
&lt;br /&gt;
&lt;div class="CodeRay"&gt;&lt;br /&gt;
&lt;pre&gt;development:&lt;br /&gt;
  adapter:  sqlite3&lt;br /&gt;
  database: sample_development.db&lt;br /&gt;
test:&lt;br /&gt;
  adapter:  sqlite3&lt;br /&gt;
  database: sample_test.db&lt;br /&gt;
production:&lt;br /&gt;
  adapter:  sqlite3&lt;br /&gt;
  database: production.db&lt;br /&gt;
&lt;/pre&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;Create a model and then rake the database&lt;br /&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;slice -i
DataMapper.auto_migrate!
&lt;br /&gt;
&lt;div class="CodeRay"&gt;&lt;br /&gt;
&lt;pre&gt;slice -i&lt;br /&gt;
DataMapper.auto_migrate!&lt;br /&gt;
&lt;/pre&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;In spec_helper.rb add the before(:all) auto_migrate line for datamapper&lt;br /&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;&lt;span class="co"&gt;Spec&lt;/span&gt;::&lt;span class="co"&gt;Runner&lt;/span&gt;.configure &lt;span class="r"&gt;do&lt;/span&gt; |config|
  config.include(&lt;span class="co"&gt;Merb&lt;/span&gt;::&lt;span class="co"&gt;Test&lt;/span&gt;::&lt;span class="co"&gt;ViewHelper&lt;/span&gt;)
  config.include(&lt;span class="co"&gt;Merb&lt;/span&gt;::&lt;span class="co"&gt;Test&lt;/span&gt;::&lt;span class="co"&gt;RouteHelper&lt;/span&gt;)
  config.include(&lt;span class="co"&gt;Merb&lt;/span&gt;::&lt;span class="co"&gt;Test&lt;/span&gt;::&lt;span class="co"&gt;ControllerHelper&lt;/span&gt;)
  config.include(&lt;span class="co"&gt;Merb&lt;/span&gt;::&lt;span class="co"&gt;Test&lt;/span&gt;::&lt;span class="co"&gt;SliceHelper&lt;br /&gt;
&lt;div class="CodeRay"&gt;&lt;br /&gt;
&lt;pre&gt;&lt;span class="co"&gt;Spec&lt;/span&gt;::&lt;span class="co"&gt;Runner&lt;/span&gt;.configure &lt;span class="r"&gt;do&lt;/span&gt; |config|&lt;br /&gt;
  config.include(&lt;span class="co"&gt;Merb&lt;/span&gt;::&lt;span class="co"&gt;Test&lt;/span&gt;::&lt;span class="co"&gt;ViewHelper&lt;/span&gt;)&lt;br /&gt;
  config.include(&lt;span class="co"&gt;Merb&lt;/span&gt;::&lt;span class="co"&gt;Test&lt;/span&gt;::&lt;span class="co"&gt;RouteHelper&lt;/span&gt;)&lt;br /&gt;
  config.include(&lt;span class="co"&gt;Merb&lt;/span&gt;::&lt;span class="co"&gt;Test&lt;/span&gt;::&lt;span class="co"&gt;ControllerHelper&lt;/span&gt;)&lt;br /&gt;
  config.include(&lt;span class="co"&gt;Merb&lt;/span&gt;::&lt;span class="co"&gt;Test&lt;/span&gt;::&lt;span class="co"&gt;SliceHelper&lt;/span&gt;)&lt;/p&gt;
config.before(&lt;span class="sy"&gt;:all&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt;
&lt;span class="co"&gt;DataMapper&lt;/span&gt;.auto_migrate! &lt;span class="r"&gt;if&lt;/span&gt; &lt;span class="co"&gt;Merb&lt;/span&gt;.orm == &lt;span class="sy"&gt;:datamapper&lt;/span&gt;
&lt;span class="r"&gt;end&lt;/span&gt;
&lt;p&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;br /&gt;
&lt;/pre&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;Then you just have to start building your slice &amp;#8211; which is tricky. That&amp;#8217;s all I&amp;#8217;ve got for now.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/scottmotte/~4/s8aii7QlXmc" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://scottmotte.com/archives/214.html</feedburner:origLink></entry>
  
  <entry>
    <title>How to test for subdomains in Merb</title>
    <link href="http://feedproxy.google.com/~r/scottmotte/~3/HNfVS-CxJfA/213.html" />
    <id>tag:scottmotte.com,2009-03-26 13:45:16:2009</id>
    <updated>2009-03-26 13:45:16</updated>
    <content type="html">&lt;h2&gt;How to test for subdomains in Merb&lt;/h2&gt;
&lt;p&gt;I&amp;#8217;ve done a couple subdomain applications now in merb. One of the things that continually bothered me was that I was unable to figure out how to test for subdomains. Thanks to &lt;a href="http://groups.google.com/group/merb/browse_thread/thread/36a814d9da9d9341/7d036fb538b6c758?lnk=gst&amp;q=atmos#7d036fb538b6c758"&gt;Shalon Wood in the Merb google group&lt;/a&gt;, I now am able to do so. I don&amp;#8217;t think Rails can even do this.&lt;/p&gt;
&lt;p&gt;requests/payment_spec.rb&lt;br /&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;require &lt;span class="co"&gt;File&lt;/span&gt;.join(&lt;span class="co"&gt;File&lt;/span&gt;.dirname(&lt;span class="pc"&gt;__FILE__&lt;/span&gt;), &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;..&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;spec_helper.rb&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)
describe &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Authenticated user logged in&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:given&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;authenticated user&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;
  describe &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;/payment&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:given&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;current_site&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;
          before(&lt;span class="sy"&gt;:each&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt;
            &lt;span class="iv"&gt;@response&lt;/span&gt; = request(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;http://&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;valid_site_attributes[&lt;span class="sy"&gt;:subdomain&lt;/span&gt;]&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;.example.org/payment&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
          &lt;span class="r"&gt;end&lt;/span&gt;
    it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;should respond successfully&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;
      &lt;span class="iv"&gt;@response&lt;/span&gt;.should be_successful
    &lt;span class="r"&gt;end&lt;/span&gt;
  &lt;span class="r"&gt;end&lt;/span&gt;
&lt;span class="r"&gt;end&lt;/span&gt;
&lt;br /&gt;
&lt;div class="CodeRay"&gt;&lt;br /&gt;
&lt;pre&gt;require &lt;span class="co"&gt;File&lt;/span&gt;.join(&lt;span class="co"&gt;File&lt;/span&gt;.dirname(&lt;span class="pc"&gt;&lt;i&gt;FILE&lt;/i&gt;&lt;/span&gt;), &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;#8216;&lt;/span&gt;&lt;span class="k"&gt;..&lt;/span&gt;&lt;span class="dl"&gt;&amp;#8217;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;#8216;&lt;/span&gt;&lt;span class="k"&gt;spec_helper.rb&lt;/span&gt;&lt;span class="dl"&gt;&amp;#8217;&lt;/span&gt;&lt;/span&gt;)&lt;br /&gt;
describe &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Authenticated user logged in&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:given&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;authenticated user&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;br /&gt;
  describe &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;/payment&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:given&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;#8216;&lt;/span&gt;&lt;span class="k"&gt;current_site&lt;/span&gt;&lt;span class="dl"&gt;&amp;#8217;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;br /&gt;
          before(&lt;span class="sy"&gt;:each&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt;&lt;br /&gt;
            &lt;span class="iv"&gt;&lt;code&gt;response&amp;lt;/span&amp;gt; = request(&amp;lt;span class="s"&amp;gt;&amp;lt;span class="dl"&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span class="k"&amp;gt;http://&amp;lt;/span&amp;gt;&amp;lt;span class="il"&amp;gt;&amp;lt;span class="idl"&amp;gt;#{&amp;lt;/span&amp;gt;valid_site_attributes[&amp;lt;span class="sy"&amp;gt;:subdomain&amp;lt;/span&amp;gt;]&amp;lt;span class="idl"&amp;gt;}&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class="k"&amp;gt;.example.org/payment&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;)
          &amp;lt;span class="r"&amp;gt;end&amp;lt;/span&amp;gt;
    it &amp;lt;span class="s"&amp;gt;&amp;lt;span class="dl"&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span class="k"&amp;gt;should respond successfully&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;&amp;amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt; &amp;lt;span class="r"&amp;gt;do&amp;lt;/span&amp;gt;
      &amp;lt;span class="iv"&amp;gt;&lt;/code&gt;response&lt;/span&gt;.should be_successful&lt;br /&gt;
    &lt;span class="r"&gt;end&lt;/span&gt;&lt;br /&gt;
  &lt;span class="r"&gt;end&lt;/span&gt;&lt;br /&gt;
&lt;span class="r"&gt;end&lt;/span&gt;&lt;br /&gt;
&lt;/pre&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;spec_helper.rb&lt;br /&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;valid_site_attributes&lt;/span&gt;(options = {})
  {
    &lt;span class="sy"&gt;:domain&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;http://www.example.org&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;,
    &lt;span class="sy"&gt;:folder&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;exampleorg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;,
    &lt;span class="sy"&gt;:subdomain&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;example&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;,
    &lt;span class="sy"&gt;:active&lt;/span&gt; =&amp;gt; &lt;span class="pc"&gt;true&lt;/span&gt;,
    &lt;span class="sy"&gt;:id&lt;/span&gt; =&amp;gt; &lt;span class="i"&gt;1&lt;/span&gt;
  }.merge(options)
&lt;span class="r"&gt;end&lt;/span&gt;
given &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;current_site&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;
  &lt;span class="co"&gt;Site&lt;/span&gt;.all.destroy!
  &lt;span class="iv"&gt;@current_site&lt;/span&gt; = &lt;span class="co"&gt;Site&lt;/span&gt;.create(valid_site_attributes)
&lt;span class="r"&gt;end&lt;/span&gt;
&lt;br /&gt;
&lt;div class="CodeRay"&gt;&lt;br /&gt;
&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;valid_site_attributes&lt;/span&gt;(options = {})&lt;br /&gt;
  {&lt;br /&gt;
    &lt;span class="sy"&gt;:domain&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;#8216;&lt;/span&gt;&lt;span class="k"&gt;http://www.example.org&lt;/span&gt;&lt;span class="dl"&gt;&amp;#8217;&lt;/span&gt;&lt;/span&gt;,&lt;br /&gt;
    &lt;span class="sy"&gt;:folder&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;#8216;&lt;/span&gt;&lt;span class="k"&gt;exampleorg&lt;/span&gt;&lt;span class="dl"&gt;&amp;#8217;&lt;/span&gt;&lt;/span&gt;,&lt;br /&gt;
    &lt;span class="sy"&gt;:subdomain&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;#8216;&lt;/span&gt;&lt;span class="k"&gt;example&lt;/span&gt;&lt;span class="dl"&gt;&amp;#8217;&lt;/span&gt;&lt;/span&gt;,&lt;br /&gt;
    &lt;span class="sy"&gt;:active&lt;/span&gt; =&amp;gt; &lt;span class="pc"&gt;true&lt;/span&gt;,&lt;br /&gt;
    &lt;span class="sy"&gt;:id&lt;/span&gt; =&amp;gt; &lt;span class="i"&gt;1&lt;/span&gt;&lt;br /&gt;
  }.merge(options)&lt;br /&gt;
&lt;span class="r"&gt;end&lt;/span&gt;&lt;br /&gt;
given &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;current_site&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;br /&gt;
  &lt;span class="co"&gt;Site&lt;/span&gt;.all.destroy!&lt;br /&gt;
  &lt;span class="iv"&gt;@current_site&lt;/span&gt; = &lt;span class="co"&gt;Site&lt;/span&gt;.create(valid_site_attributes)&lt;br /&gt;
&lt;span class="r"&gt;end&lt;/span&gt;&lt;br /&gt;
&lt;/pre&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;app/controllers/application.rb&lt;br /&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;get_site&lt;/span&gt;
  &lt;span class="c"&gt;# uses @current_site to create pages under appropriate site like @current_site.pages.new&lt;/span&gt;
  &lt;span class="iv"&gt;@current_site&lt;/span&gt; = &lt;span class="co"&gt;Site&lt;/span&gt;.first(&lt;span class="sy"&gt;:subdomain&lt;/span&gt; =&amp;gt; request.first_subdomain)
  raise &lt;span class="co"&gt;NotFound&lt;/span&gt; &lt;span class="r"&gt;unless&lt;/span&gt; &lt;span class="iv"&gt;@current_site&lt;/span&gt;
&lt;span class="r"&gt;end&lt;/span&gt;
&lt;br /&gt;
&lt;div class="CodeRay"&gt;&lt;br /&gt;
&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;get_site&lt;/span&gt;&lt;br /&gt;
  &lt;span class="c"&gt;# uses &lt;code&gt;current_site to create pages under appropriate site like @current_site.pages.new&amp;lt;/span&amp;gt;
  &amp;lt;span class="iv"&amp;gt;&lt;/code&gt;current_site&lt;/span&gt; = &lt;span class="co"&gt;Site&lt;/span&gt;.first(&lt;span class="sy"&gt;:subdomain&lt;/span&gt; =&amp;gt; request.first_subdomain)&lt;br /&gt;
  raise &lt;span class="co"&gt;NotFound&lt;/span&gt; &lt;span class="r"&gt;unless&lt;/span&gt; &lt;span class="iv"&gt;@current_site&lt;/span&gt;&lt;br /&gt;
&lt;span class="r"&gt;end&lt;/span&gt;&lt;br /&gt;
&lt;/pre&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/notextile&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/scottmotte/~4/HNfVS-CxJfA" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://scottmotte.com/archives/213.html</feedburner:origLink></entry>
  
  <entry>
    <title>PDF Generation in Merb using HTMLDOC</title>
    <link href="http://feedproxy.google.com/~r/scottmotte/~3/OQVvgYcbI40/212.html" />
    <id>tag:scottmotte.com,2009-03-25 17:01:37:2009</id>
    <updated>2009-03-25 17:01:37</updated>
    <content type="html">&lt;h2&gt;PDF Generation in Merb using HTMLDOC&lt;/h2&gt;
&lt;p&gt;A good part of this is thanks to &lt;a href="http://blog.adsdevshop.com/2007/11/20/easy-pdf-generation-with-ruby-rails-and-htmldoc/"&gt;this tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Installation&lt;/h3&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;# Download HTMLDoc from &amp;lt;a href=&amp;quot;http://www.htmldoc.org/software.php?VERSION=1.9.x-r1586&amp;amp;FILE=htmldoc/snapshots/htmldoc-1.9.x-r1586.tar.gz&amp;quot;&amp;gt;here&amp;lt;/a&amp;gt;
tar zxvf htmldoc-1.9.x-r1586.tar.gz
cd htmldoc-1.9.x-r1586
./configure --prefix=/usr/local
make
sudo make install
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Install gem&lt;br /&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;sudo gem install htmldoc&lt;br /&gt;
&lt;div class="CodeRay"&gt;&lt;br /&gt;
&lt;pre&gt;sudo gem install htmldoc&lt;/pre&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;h3&gt;Configure merb app&lt;/h3&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;&lt;span class="c"&gt;# dependencies.rb&lt;/span&gt;
dependency &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;htmldoc&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;0.2.1&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;&lt;span class="c"&gt;# init.rb&lt;/span&gt;
&lt;span class="co"&gt;Merb&lt;/span&gt;::&lt;span class="co"&gt;BootLoader&lt;/span&gt;.after_app_loads &lt;span class="r"&gt;do&lt;/span&gt;
        &lt;span class="c"&gt;# This will get executed after your app's classes have been loaded.&lt;/span&gt;
        &lt;span class="co"&gt;Merb&lt;/span&gt;.add_mime_type(&lt;span class="sy"&gt;:pdf&lt;/span&gt;, &lt;span class="sy"&gt;:to_pdf&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;%w[&lt;/span&gt;&lt;span class="k"&gt;application/pdf&lt;/span&gt;&lt;span class="dl"&gt;]&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Content-Encoding&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;gzip&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class="r"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Create an action for the pdf generation&lt;/h3&gt;
&lt;p&gt;(there must be a way to just put this in the show action instead of a separate action but i had trouble)&lt;br /&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;&lt;span class="c"&gt;# router.rb&lt;/span&gt;
resources &lt;span class="sy"&gt;:proposals&lt;/span&gt;, &lt;span class="sy"&gt;:collection&lt;/span&gt; =&amp;gt; { &lt;span class="sy"&gt;:generate&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:get&lt;/span&gt; }
&lt;br /&gt;
&lt;div class="CodeRay"&gt;&lt;br /&gt;
&lt;pre&gt;&lt;span class="c"&gt;# router.rb&lt;/span&gt;&lt;br /&gt;
resources &lt;span class="sy"&gt;:proposals&lt;/span&gt;, &lt;span class="sy"&gt;:collection&lt;/span&gt; =&amp;gt; { &lt;span class="sy"&gt;:generate&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:get&lt;/span&gt; }&lt;br /&gt;
&lt;/pre&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;&lt;span class="c"&gt;# proposals.rb controller&lt;/span&gt;
&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;generate&lt;/span&gt;(id)
        only_provides &lt;span class="sy"&gt;:pdf&lt;/span&gt;
        pdf = &lt;span class="co"&gt;PDF&lt;/span&gt;::&lt;span class="co"&gt;HTMLDoc&lt;/span&gt;.new
        pdf.set_option &lt;span class="sy"&gt;:bodycolor&lt;/span&gt;, &lt;span class="sy"&gt;:white&lt;/span&gt;
        pdf.set_option &lt;span class="sy"&gt;:toc&lt;/span&gt;, &lt;span class="pc"&gt;false&lt;/span&gt;
        pdf.set_option &lt;span class="sy"&gt;:portrait&lt;/span&gt;, &lt;span class="pc"&gt;true&lt;/span&gt;
        pdf.set_option &lt;span class="sy"&gt;:links&lt;/span&gt;, &lt;span class="pc"&gt;true&lt;/span&gt;
        pdf.set_option &lt;span class="sy"&gt;:webpage&lt;/span&gt;, &lt;span class="pc"&gt;true&lt;/span&gt;
        pdf.set_option &lt;span class="sy"&gt;:left&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;2cm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;
        pdf.set_option &lt;span class="sy"&gt;:right&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;2cm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;
        pdf.set_option &lt;span class="sy"&gt;:header&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Header here!&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
        pdf &amp;lt;&amp;lt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;&amp;lt;h1&amp;gt;Title&amp;lt;/h1&amp;gt; &amp;lt;p&amp;gt;This is some &amp;lt;strong&amp;gt;bold&amp;lt;/strong&amp;gt; text.&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
        pdf.footer &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;.t.&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
        send_data pdf.generate
&lt;span class="r"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Then just put a link_to in your view&lt;br /&gt;
&lt;div class="CodeRay"&gt;
&lt;pre&gt;&amp;lt;&lt;span class="s"&gt;&lt;span class="dl"&gt;%=&lt;/span&gt;&lt;span class="k"&gt; link_to &amp;quot;Generate PDF&amp;quot;, &amp;quot;/proposals/generate/&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;&lt;span class="iv"&gt;@proposal&lt;/span&gt;.id&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;.pdf&amp;quot; %&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div class="CodeRay"&gt;&lt;br /&gt;
&lt;pre&gt;&amp;lt;&lt;span class="s"&gt;&lt;span class="dl"&gt;%=&lt;/span&gt;&lt;span class="k"&gt; link_to &amp;quot;Generate PDF&amp;quot;, &amp;quot;/proposals/generate/&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="idl"&gt;#{&lt;/span&gt;&lt;span class="iv"&gt;@proposal&lt;/span&gt;.id&lt;span class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;.pdf&amp;quot; %&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;Warning: I was never able to get background images to work. I don&amp;#8217;t know if this was a limitation with the htmldoc ruby gem, whether it was something with my htmldoc install, or whether it was a stupid coding mistake on my end.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/scottmotte/~4/OQVvgYcbI40" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://scottmotte.com/archives/212.html</feedburner:origLink></entry>
  
</feed>
