<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>ducktyped - Home</title>
  <id>tag:ducktyped.com,2008:mephisto/</id>
  <generator uri="http://mephistoblog.com" version="0.7.3">Mephisto Noh-Varr</generator>
  <link href="http://ducktyped.com/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://ducktyped.com/" rel="alternate" type="text/html"/>
  <updated>2008-01-04T00:48:12Z</updated>
  <entry xml:base="http://ducktyped.com/">
    <author>
      <name>ben</name>
    </author>
    <id>tag:ducktyped.com,2008-01-04:8</id>
    <published>2008-01-04T00:11:00Z</published>
    <updated>2008-01-04T00:48:12Z</updated>
    <category term="ruby web frameworks"/>
    <link href="http://ducktyped.com/2008/1/4/the-great-ruby-web-framework-multi-app-challenge" rel="alternate" type="text/html"/>
    <title>The great Ruby web framework multi-app challenge</title>
<summary type="html">&lt;p&gt;Many websites are composed of several fairly independent apps that would still benefit from tighter integration than running them as separate apps. Here's a typical site: core site, forum, blog/cms (or photo management app, etc).&lt;/p&gt;

&lt;p&gt;The typical Rails response to multi-app integration is one of the following two: 1. &quot;Just run them as separate apps on different subdomains and share the database.&quot; or 2. &quot;Use the app as the base and add your own code to it.&quot; I have integrated several Rails apps, and it is dirty and inefficient, a real pain in the ass, especially compared to the joy of doing most other things with Ruby/Rails. The failure of multi-app Rails is documented by the plethora of hacks used to emulate multi-app behaviors: generators, engines, appable plugins, and the multi-app routing plugin.&lt;/p&gt;

&lt;p&gt;The point of this post is not to rip on rails, it's just what I'm primarily using, and I would love to see other Ruby web frameworks such as merb, ramaze, and the micro-frameworks think about multi-app while they can still make major changes. Ruby is powerful enough to elegantly enable multi-app configurations.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Many websites are composed of several fairly independent apps that would still benefit from tighter integration than running them as separate apps. Here's a typical site: core site, forum, blog/cms (or photo management app, etc).&lt;/p&gt;

&lt;p&gt;The typical Rails response to multi-app integration is one of the following two: 1. &quot;Just run them as separate apps on different subdomains and share the database.&quot; or 2. &quot;Use the app as the base and add your own code to it.&quot; I have integrated several Rails apps, and it is dirty and inefficient, a real pain in the ass, especially compared to the joy of doing most other things with Ruby/Rails. The failure of multi-app Rails is documented by the plethora of hacks used to emulate multi-app behaviors: generators, engines, appable plugins, and the multi-app routing plugin.&lt;/p&gt;

&lt;p&gt;The point of this post is not to rip on rails, it's just what I'm primarily using, and I would love to see other Ruby web frameworks such as merb, ramaze, and the micro-frameworks think about multi-app while they can still make major changes. Ruby is powerful enough to elegantly enable multi-app configurations.&lt;/p&gt;
&lt;h2&gt;What sucks about multi-app integration right now&lt;/h2&gt;

&lt;h3&gt;Redundant css and js&lt;/h3&gt;

&lt;p&gt;You send a new copy of prototype.js when switching between your core app, beast, and mephisto for example. You duplicate CSS as well. To avoid that you end up futzing around with deployment managers (capistrano) to make one app use the other's css and js in production.&lt;/p&gt;

&lt;h3&gt;Duplicate models&lt;/h3&gt;

&lt;p&gt;You have to duplicate models to access resources across the separate apps, or set up SCM, symlink hacks for versioning. Ugly, and suckage for dev / deployment differences.&lt;/p&gt;

&lt;h3&gt;Shitty routing&lt;/h3&gt;

&lt;p&gt;You end up using hacks and the web server instead of the app's router to resolve your routing. It's less powerful and in the wrong place. Now there is the multi-app routing plugin, which is just a hack to mitigate an underlying bigger problem. (It's cool for some use cases, sure, but still limited in capabilities)&lt;/p&gt;

&lt;h3&gt;Code scales poorly&lt;/h3&gt;

&lt;p&gt;Dumping all apps' M/V/Cs into one big app creates a cluttered project, and the project code doesn't scale. &lt;a href=&quot;http://www.caboo.se/articles/2007/10/17/multiple-apps-one-domain&quot;&gt;Here's a post by caboose's Courtenay&lt;/a&gt; hinting at that the rails directory structure struggles with large apps. Having &quot;eighty controllers&quot; should not be a reason for having to split a project into two completely separate projects, maintaining separate deployments, etc.&lt;/p&gt;

&lt;p&gt;In a way, the Rails folder structure is backwards, e.g. I can namespace my M/V/Cs but that means I have pieces of a semantically related structure (an app) in 3 places instead of one. When I work on code, I mostly work on a subcomponent of the app, and not just in M or V or C. &lt;/p&gt;

&lt;p&gt;What I want is:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/app1
  /model
  /view
  /controller
/app2
  /model
  /view
  /controller
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Not:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/model
  /app1
  /app2
/view
  /app1
  /app2
/controller
  /app1
  /app2
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Memory overhead&lt;/h3&gt;

&lt;p&gt;People on shared hosts and small VPSes don't have ram to throw around. Right now, with a rails site consisting of a core app, blog, and forum, I get 3 hefty rails processes, when I want just one. (I could then use two mongrels, save 1/3 ram and get better concurrency/basic load balancing (if one app gets hit much more than the other)).&lt;/p&gt;

&lt;h3&gt;Single sign-on and session/cookie sharing&lt;/h3&gt;

&lt;p&gt;This isn't too hard to solve in practice, but it's not necessary. There should be a auth/login app to drop in instead of the generator. Other apps then by convention use user and user_id as the hooks into the auth/login system, but they don't all duplicate it. The auth/login system can be whatever, as long as the interface to it is a user model and user_id as the hook. All that would be left to do to integrate it is to add associations and before_filters. This has been a big topic of debate in the beast forums, and frankly, it shouldn't be that integrating a rails app with beast (another rails app) is exactly as cumbersome as integrating it with a PHP forum engine.&lt;/p&gt;

&lt;h2&gt;Fighting objections - it's all about views&lt;/h2&gt;

&lt;h3&gt;Plugins already provide (80% of) this functionality&lt;/h3&gt;

&lt;p&gt;No they don't, and they shouldn't. Engines, appable plugins, and generators  are all trying to fix part but not the root of the multi-app problem.&lt;/p&gt;

&lt;p&gt;Most importantly, plugins have no views. Have your ever counted your LOC? Views make up &lt;em&gt;a lot of code&lt;/em&gt;, especially with ajax thrown in. For example, I want to be able to drop in a blog or comment system that includes ajax posting of comments by default, rather than me having to write all the views from scratch. Plugins are fantastic for what they're designed for, but multi-app is not their use case.&lt;/p&gt;

&lt;h3&gt;High level components don't work&lt;/h3&gt;

&lt;p&gt;DHH is a declared opponent of components (or at least was, given that the quoted statements are over 2 years old). (see &lt;a href=&quot;http://www.loudthinking.com/arc/000407.html&quot;&gt;here&lt;/a&gt; and &lt;a href=&quot;http://weblog.rubyonrails.com/2005/11/11/why-engines-and-components-are-not-evil-but-distracting/&quot;&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;His experience is based on a failing high level parameterized component architecture in java. But the components he's talking about are different from multi-app. I'm not saying that you can just drop in a bunch of components and wire them together with a few parameters. I'm saying, get canonical code (e.g. a basic blog engine) and adapt it to your needs in a way that's cleaner and more maintainable/reusable than a generator's output or nested plugin stuff like engines or appable plugins.&lt;/p&gt;

&lt;p&gt;Also, David's experience was based on working in a java shop, but Ruby is much more concise than Java, and modifying a forum engine in Ruby isn't too bad, especially if its code layout follows a canonical layout such as the standard rails app structure.&lt;/p&gt;

&lt;h3&gt;Ruby/Rails makes it so easy to write from scratch, why bother?&lt;/h3&gt;

&lt;p&gt;Why would you need this stuff, if Ruby/Rails make it so easy to create a blog engine from scratch. DHH did it in 10 minutes in his video, Akita in 20 minutes. Did they really?&lt;/p&gt;

&lt;p&gt;It's like saying &quot;I can write a digg clone in 20 minutes.&quot; You can write something that provides the most basic functionality, but it's not a digg clone. You know why? UI, UI, UI. User interface is 80% of the value of an app for the end user, and right now there is no reuse of great UI design, which is a shame, because UI design is hard, and a lot of people would benefit from leveraging great UIs. I'd rather drop a mephisto-lite into my project than rewrite it from scratch to &quot;meet my app specific needs&quot;. And I want to do it without mixing its code and my own apps code wildly all over the place (which just creates SCM headaches).&lt;/p&gt;

&lt;h2&gt;What could multi-app look like?&lt;/h2&gt;

&lt;p&gt;The one framework I found that gets multi-app mostly right is Python's &lt;a href=&quot;http://www.djangoproject.com/documentation/tutorial01/&quot;&gt;django&lt;/a&gt;. It's great to be able to drop in a basic blog or forum engine that includes views/ajax, etc.&lt;/p&gt;

&lt;p&gt;At the very least, it makes utter sense to have common routing, css, javascript for a collection of apps in a site.&lt;/p&gt;

&lt;h3&gt;DRY up the suckage described above&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;CSS, JS, models&lt;/li&gt;
&lt;li&gt;Sessions/cookies&lt;/li&gt;
&lt;li&gt;Routing&lt;/li&gt;
&lt;li&gt;(Single sign-on)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Rough idea for a project/app layout&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;/app_root
    /config (global configuration, affects all apps)
    /public
        /js (main app default)
        /css 
        /blog/js (blog specific)
        /blog/css
        /forum/js
        /forum/css
    # These are the apps that would be dropped into the application
    # Test and spec folders would be moved into the app folders, so
    # that each app can have its own test suite
    /app (The default main app)
    /blog (Full app with tests, etc., minus config, public)
    /forum (same thing)
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;How to adjust routing&lt;/h3&gt;

&lt;p&gt;Routing could simply add a an 'app' level :app/:controller/:action/:id =&gt; http://mysite.com/forum/post/view/1&lt;/p&gt;

&lt;h2&gt;Problems to address&lt;/h2&gt;

&lt;h3&gt;Layouts and css&lt;/h3&gt;

&lt;p&gt;How to avoid layout duplication, and where to put app-specific css. I would put css in public/css/#{app_name}/default.css, and then for deployment join the css files. This would also require some name-spacing conventions of css to avoid collisions/overrides. I haven't fully thought through how to do a DRY layout structure.&lt;/p&gt;

&lt;h3&gt;DB table name collisions&lt;/h3&gt;

&lt;p&gt;I like django's solution of prefixing tables with the app name, e.g. a posts model in a blog and a forum app would map to the following tables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;blog_posts&lt;/li&gt;
&lt;li&gt;forum_posts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This could be easily done by using the ORMs' table prefix methods, and could be automated, dealt with by convention.&lt;/p&gt;

&lt;h3&gt;Different apps being tied to different versions of the framework&lt;/h3&gt;

&lt;p&gt;What if my core app runs on edge, but my dropped-in mephisto-lite relies on Rails 1.2.x. Since I'm now running within the same process, this wouldn't be possible AFAIK, but the tradeoff is still worth it. Especially if you reuse a lot of your own internal apps. It might even lead to better maintained apps.&lt;/p&gt;

&lt;p&gt;I made the assumption of everything running in one process before, but that wouldn't necessarily have to be the case. Apps could run in their own processes with their own version of the framework, but I still have a smart wrapper around them for routing, etc.&lt;/p&gt;

&lt;h3&gt;Apps use different ORMs or databases&lt;/h3&gt;

&lt;p&gt;I haven't thought through this one too much, but it's even conceivable that apps could use different ORMs to talk to the database, or even use separate databases. I would probably have a global default db config, with possibilities for apps to override them. That might make the framework startup process overly complex, so I'd even be fine if all apps would have to use the same ORM/db. (Side note: Multi-db is still another unsolved challenge for most Ruby web frameworks).&lt;/p&gt;

&lt;h3&gt;Some folder locations might be contentious&lt;/h3&gt;

&lt;p&gt;Should /lib be global or per-app? Per-app keeps things more in one place and allows different apps to use different versions of the same library if necessary. Perhaps a structure of /lib/app_name would solve this in an elegant way.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;There is movement in the Ruby web framework space with new frameworks hitting the scene. &quot;The balls are in the air&quot;, and now is the time to bring up ideas for change. Rails has been and still is a fantastic yardstick by which to measure web frameworks, but Rails has warts too, and sometimes Rails is starting to feel a bit pudgy, like a &quot;Ruby Struts&quot; (which is amazing, because Rails is at least an order of magnitude better than Java Struts, it just shows how much progress is being made.)&lt;/p&gt;

&lt;p&gt;I talked about multi-app in this post based on my personal experience with Rails. Rails is fantastic, but I don't think they would incorporate a clean multi-app setup, but I'm hopeful that the new kids on the Ruby web framework block (like merb, ramaze, sinatra, et al.) will think hard about if and how to incorporate multi-app capabilities. Especially some of the micro-frameworks could scale very nicely (code management and deployment-wise) by clustering small, light apps together (like a bliki for example).&lt;/p&gt;

&lt;p&gt;I hope to stimulate a healthy, productive, and civilized discussion with this post. Hopefully, at least one framework will incorporate multi-app capabilities. Whichever Ruby web framework will end up with a clean multi-app setup will be the one I'll be using.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://ducktyped.com/">
    <author>
      <name>ben</name>
    </author>
    <id>tag:ducktyped.com,2007-12-10:7</id>
    <published>2007-12-10T11:55:00Z</published>
    <updated>2007-12-10T12:13:12Z</updated>
    <category term="merb"/>
    <link href="http://ducktyped.com/2007/12/10/merb-startup-problems-dies-after-compiling-routes" rel="alternate" type="text/html"/>
    <title>Merb startup problems: dies after "Compiling routes.."</title>
<content type="html">
            &lt;p&gt;I was so excited to play around with merb again. I just checked, and the first version of merb I used to prototype an app was 0.0.8 about a year ago. But I was so bummed out that after wanting to be all proper and upgrading all my gems, merb stopped working, no errors, no logs, no debug info, nothing.&lt;/p&gt;


	&lt;p&gt;After asking on &lt;span class=&quot;caps&quot;&gt;IRC&lt;/span&gt; (impossibly late at night) without any luck, I dove into the (beautifully clear and manageable) source and figured out that the &#8216;parsetree&#8217; gem was required, but not installed. So a quick &lt;code&gt;sudo gem install parsetree&lt;/code&gt;, was all that I needed, and I&#8217;m back in business.&lt;/p&gt;


	&lt;p&gt;After I realized that parsetree was to blame, a quick search brought up the same problem addressed and solved on the Ruby mailing list: &lt;a href=&quot;http://www.ruby-forum.com/topic/132766&quot;&gt;http://www.ruby-forum.com/topic/132766&lt;/a&gt;. But without knowing that the problem is parsetree related, how would you find this post. So again, for the crawlers &lt;b&gt;merb 0.4.1 stops after &#8220;Compiling routes..&#8221;&lt;/b&gt;&lt;/p&gt;


	&lt;p&gt;I can&#8217;t wait to get some real work done now. :)&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://ducktyped.com/">
    <author>
      <name>ben</name>
    </author>
    <id>tag:ducktyped.com,2007-07-02:6</id>
    <published>2007-07-02T10:57:00Z</published>
    <updated>2007-12-10T12:17:00Z</updated>
    <category term="coding environment"/>
    <link href="http://ducktyped.com/2007/7/2/set-up-ie-testing-on-localhost-using-parallels-on-os-x" rel="alternate" type="text/html"/>
    <title>Set up IE testing on localhost using Parallels on OS X</title>
<content type="html">
            &lt;p&gt;After an extensive hunt for a low-hassle solution for testing my local development rails applications in Internet Explorer using Parallels, I finally found &lt;a href=&quot;http://www.maintainablesoftware.com/articles/rails_internet_explorer_and_parallels&quot;&gt;this post&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;This is by far the most straightforward way and clearest writeup to get this development plumbing out of the way. It uses Bonjour for Windows so that you can access your rails apps with something like &lt;code&gt;mymachine.local:3000&lt;/code&gt;. Done! Now back to actual coding.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://ducktyped.com/">
    <author>
      <name>ben</name>
    </author>
    <id>tag:ducktyped.com,2007-06-16:2</id>
    <published>2007-06-16T10:54:00Z</published>
    <updated>2007-12-10T12:17:20Z</updated>
    <category term="coding environment"/>
    <link href="http://ducktyped.com/2007/6/16/get-svn-changesets-by-rss" rel="alternate" type="text/html"/>
    <title>Get SVN changesets by RSS for any public repository</title>
<content type="html">
            &lt;p&gt;&lt;a href=&quot;http://subtlety.errtheblog.com/&quot;&gt;Subtlety is a beautiful thing&lt;/a&gt;. Just enter the repository&#8217;s url and add the resulting subtlety link to your feed reader. I&#8217;ve never enjoyed reading changesets so much. I actually follow projects now without missing anything.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://ducktyped.com/">
    <author>
      <name>ben</name>
    </author>
    <id>tag:ducktyped.com,2007-06-12:1</id>
    <published>2007-06-12T08:09:00Z</published>
    <updated>2007-12-10T12:15:28Z</updated>
    <category term="rails"/>
    <link href="http://ducktyped.com/2007/6/12/how-to-change-databases-using-ruby-on-rails" rel="alternate" type="text/html"/>
    <title>How to change databases using Ruby on Rails</title>
<summary type="html">&lt;p&gt;I was running a mysql 4.1 db that kept screwing up my unicode, so I decided why not double version numbers and move to postgresql 8.2. Great idea in theory, but a pain in the ass in practice. The sql dumps of the different &lt;span class=&quot;caps&quot;&gt;DBMS&lt;/span&gt; are incompatible, especially booleans causing trouble. The scripts I found were pretty much useless, so I was stuck until I came across the idea of using rails to export the db to yaml and then re-import it into the new db.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;I was running a mysql 4.1 db that kept screwing up my unicode, so I decided why not double version numbers and move to postgresql 8.2. Great idea in theory, but a pain in the ass in practice. The sql dumps of the different &lt;span class=&quot;caps&quot;&gt;DBMS&lt;/span&gt; are incompatible, especially booleans causing trouble. The scripts I found were pretty much useless, so I was stuck until I came across the idea of using rails to export the db to yaml and then re-import it into the new db.&lt;/p&gt;
&lt;p&gt;This sounds very elegant in theory, but there are still a few pitfalls. &lt;a href=&quot;http://blog.leetsoft.com&quot;&gt;Tobias Luetke&lt;/a&gt; posted &lt;a href=&quot;http://blog.leetsoft.com/2006/5/29/easy-migration-between-databases&quot;&gt;how he did it&lt;/a&gt; and provided a very useful rake task that became the basis for my approach. For good measure I threw &lt;a href=&quot;http://drnicwilliams.com/&quot;&gt;Dr. Nic&#8217;s&lt;/a&gt; &lt;a href=&quot;http://magicmodels.rubyforge.org/magic_model_generator/&quot;&gt;magic model generator&lt;/a&gt; in the mix to allow for very powerful and flexible migrations, even if your application doesn&#8217;t define models for all tables, e.g. when you have several apps using the same db.&lt;/p&gt;


	&lt;p&gt;The following is my 10-step program for database migration bliss.&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Set up the basics
  &lt;pre&gt;&lt;code&gt;
  sudo gem install magic_model_generator
  rails db_migration_app
  cd db_migration_app
  &lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
		&lt;li&gt;Download the &lt;a href=&quot;http://thenakedbrain.com/assets/2007/6/12/backup.rake&quot;&gt;backup.rake&lt;/a&gt; task and copy it to lib/tasks/&lt;/li&gt;
		&lt;li&gt;Connect to your production db in config/database.yml. This is also a good time back up your db before you ruin things with jittery fingers and then blame me.&lt;/li&gt;
		&lt;li&gt;With the db set up properly, get the schema and magic models ready
  &lt;pre&gt;&lt;code&gt;
  RAILS_ENV=production rake db:schema:dump
  RAILS_ENV=production ./script/generate magic_model
  &lt;/code&gt;&lt;/pre&gt;
  (Just for kicks, you can inspect your entire db through the rails console via
  &lt;span class=&quot;caps&quot;&gt;RAILS&lt;/span&gt;_ENV=production ./script/console)&lt;/li&gt;
		&lt;li&gt;[OPTIONAL] Add any tables that should not be dumped/restored to the array in the rake task&#8217;s &lt;code&gt;interesting_tables&lt;/code&gt; method. &lt;code&gt;schema_info&lt;/code&gt;, &lt;code&gt;sessions&lt;/code&gt;, and &lt;code&gt;logged_exceptions&lt;/code&gt; are excluded by default.&lt;/li&gt;
		&lt;li&gt;Let&#8217;s do some dumping. This may take some time, depending on your db size.
  &lt;pre&gt;&lt;code&gt;
  RAILS_ENV=production rake db:backup:write
  &lt;/code&gt;&lt;/pre&gt;
  At this point you have all your tables&#8217; data in yaml format in db/backup/*.yaml.&lt;/li&gt;
		&lt;li&gt;Now change your database.yml to the new, empty db (e.g. your brand new pg db). Don&#8217;t mess this up, because the next step will completely wipe whichever db is defined as the production db.&lt;/li&gt;
		&lt;li&gt;Import the yaml data into the new production db.
  &lt;pre&gt;&lt;code&gt;
  RAILS_ENV=production rake db:backup:read
  &lt;/code&gt;&lt;/pre&gt;
  This also runs rake db:schema:load, and restores the correct schema_info.&lt;/li&gt;
		&lt;li&gt;[EXTRA &lt;span class=&quot;caps&quot;&gt;CREDIT&lt;/span&gt;] If you migrate to postgresql, fix your sequences in one easy step with the following rake task I created:
  &lt;pre&gt;&lt;code&gt;
  RAILS_ENV=production rake db:backup:set_sequences
  &lt;/code&gt;&lt;/pre&gt;
  If you want to check the sequence number in psql, run &lt;code&gt;select last_value from table_name_id_seq;&lt;/code&gt; (where table_name is your table&#8217;s name)&lt;/li&gt;
		&lt;li&gt;Lastly, make sure you don&#8217;t forget to adjust your actual application&#8217;s database.yml to point to the new db.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Enjoy your newfound freedom from the stranglehold of your old database. :)&lt;/p&gt;
          </content>  </entry>
</feed>
