A Django site.
August 20, 2008

Hans Fugal
no nic
The Fugue :
» MVC

A friend of mine is struggling to grok the MVC pattern. I remember when I first tried to grok it how frustrating it was. There wasn't one final "a-ha" moment when I grokked it, but one day I looked back and realized I understood it. At that moment it dawned on me just how amazingly silly this whole process is. MVC is not some magical formula that if you implement it will endow your application with magical powers. It is a paradigm. A worldview of application programming. Once you get it, you realize that everything is MVC. It's just that some of it is cleaner MVC than others. The trick is in keeping the three components separate, but they're always there. My friend is still confused after an IM conversation, because his preconceptions about the computer and probably his desire to find that something different are getting in the way. So let's use a non-computer analogy.

You've seen The Hitchhiker's Guide to the Galaxy, right? Of course you have. If not, I'll wait.

Ok, remember the scene where Trillian is at a desk with a Vogon who asks her here home planet? She says it's Earth, the Vogon can't find Earth, she tells her where it is, she says it was destroyed, and does Trillian perhaps have another home planet? Yeah, I don't do it justice. Ok, so Trillian is the user. The Vogon is the controller, the computer is the database, and there are several views in play. The first view is the Vogon telling Trillian that it was destroyed. The second view is when she turns the computer monitor around so the incredulous Trillian can see for herself the video of the Earth being blown up. The third view is authorization with Zaphod's autograph.

The nice thing about MVC, see, is that the model has no clue about the view or the controller. It just provides an interface for the controller to get and change the model's information. Likewise the view is pretty dumb. It accesses the model, or a snapshot thereof. But it doesn't make decisions. It just displays stuff. The controller is the "brains" behind the operation. It coordinates showing the user the correct view of the bit of the model that the user wants to see. It handles updating the model with new information.

Ok, still confused? Let's try another. This time the controller is your CD player. The model is a CD. The view is your amplifier and speakers, or whatever else you have plugged into the audio outputs. An oscilloscope maybe? You the user push buttons and the controller changes the view. The model and view are obviously decoupled. But this analogy isn't perfect because the view isn't accessing the model directly, as is usually the case in MVC, but is being spoonfed the data by the controller. In my opinion this distinction is irrelevant, because the whole point is to achieve decoupling and whether the controller provides the decoupleable data or the view fetches it directly from the model is irrelevant to decoupleability, as we can see with this real-world example. Also this analogy might be better if we think back to cassette tapes which allow us to change the model (by recording), whereas the CD is read-only.

Ok, so now let's bring it to the computer domain. The model is a database. Actually it's usually a wrapper around a database (which is in turn usually decoupled too), like ActiveRecord or your homegrown classes. You almost always write classes, because representing "stuff" is what OOP is good at. It doesn't have to be a real database of course, it could be just objects in RAM or a flat file. The key word for models is data.

Now, the view is almost always entirely contained in the GUI toolkit you're using. The toolkit writers figured out all that boring stuff that lets you draw widgets and pack them together in a dialog box, etc. All that stuff you wouldn't want to do manually is the view. You may have some view code which deals with setting up the widgets, etc. The view may not even be visual—it might be a file on disk or sound coming out the speakers. The key word for views is render.

The controller is everything else. Those GUI toolkits usually have some controller help too, since GUIs are interactive views and the events that the controller reacts to are coming from the view, in a sense. When you write callbacks, you're writing the controller. The controller figures out what to do in response to various events. It decides how to manipulate the views. It tells the views what data to display. The key word is event, and maybe coordination.

So you see, if you're using a toolkit or framework you're already sort of doing MVC. The real litmus test can be boiled down to the following questions. If you can answer yes to all of them, then you're doing MVC. If not, you're not.

  1. Could I render different views without duplicating control code?
  2. Could I use my model code unchanged in a completely different application, and could I switch databases (if you have a persistent model) like I switch CDs?
  3. Is my model ignorant of the rest of the program?
  4. Do I feel like MVC is making my life easier, not harder?
  5. Have I sent chocolate to Hans recently?

There you have it. I hope it was helpful.

March 27, 2008

Hans Fugal
no nic
The Fugue :
» Rails Sessions

I was doing some maintenance on my blog, and was devastated to find that Typo was taking 225 megabytes of resident RAM. Yikes! After some creative debug thinking and digging I figured out it was due to sessions. Typo now stores sessions in the database, so my maintenance cron job to delete old sessions didn't clean up old sessions. (Ha! had you going for a second!)

Well I could write a cron job to run a script to clean the sessions out of the db, like:

#!/bin/sh
sqlite3 /path/to/typo/db/production.db 'delete from sessions'

Ok, that's a bit extreme, but you get the idea. But when I deleted the sessions in this manner the memory usage didn't drop at all until I had restarted the server, which seems unnecessary. So instead I changed typo's configuration to use a different session store. I commented out this line in config/environment.rb:

-  config.action_controller.session_store = :active_record_store
+  #config.action_controller.session_store = :active_record_store

Then I restarted the server and fired up a browser. "Huh, that's odd… no sessions in tmp/sessions or /tmp or anywhere I can see. No, they're not in the database…" What I was seeing didn't match up with what all the stuff Google said. The default session store was PStore, aka file system, so they said. But apparently that recently changed in Rails, and now the default is CookieStore. From ActionController::Base documentation:

Sessions are stored in a browser cookie that‘s cryptographically signed, but unencrypted, by default. This prevents the user from tampering with the session but also allows him to see its contents.

Do not put secret information in session!

Well a quick grep -ri session app lib told me that typo wasn't storing anything secret, so I decided that default was alright with me. Now I don't have to set up any session cleanup script at all. Sweet.

Now, don't stop there. You should set your session key and secret while you're hanging out in config/environment.rb. Add the following lines in the same place as the line you commented out above:

config.action_controller.session['session_key'] = 'something unique'
config.action_controller.session['secret'] = 'get this from rake secret'

January 23, 2008

Pat Eyler
pate
On Ruby
» RubyZone, RailsSpace, and Ruby DVDs

dZone has recently introduced a set of ‘zones’ with original content, forums, and other things about specific topics to compliment their social bookmarking site. One of these is the RubyZone. I’ve been asked to work as a ‘Zone Leader’ there, writing new material and helping build the community. Even before I’d gotten there someone else had written some material, a review of the book RailsSpace

January 10, 2008

Kevin Kubasik
nonic
For Once I Oneder
» Scripted Web Frameworks, and why Django Got it Right

So, I've been working on a few small web projects for an assortment of businesses, pretty standard fair stuff, so I've seized the opportunity to finally do something of a personal analysis of the enormous mass of web frameworks out there (Rails, TG, Django etc). Before anyone gets the wrong idea, this is _NOT_ a comparison, its an opinion. I've just been working with Django for the past several days, and I feel like I owe it a little bit of word-of-mouth.

Let me first explain, Django is really a completely different beast than either Rails or TurboGears. In my experiance, it seems that the real goal of those systems is to make sure we have to code as little as often, so massive slews of differently formatted configuration files, naming conventions and templates are really to be expected. Here's the problem, I'm a developer. I _like_ coding. Now, sometimes it is nice to design a SQL schema, and find your objects already waiting for you. Its also nice to have an authentication framework, templates are fine too, as long as its not a whole new language. The problem I started to run into fairly early on was I didn't know the 'Ruby on Rails' way to do it, but knew perfectly well how I might have done it in a chitzy CGI.

Turbo Gears wasn't much better, again, the goals of the project seems to be as little code as possible, but code is a wonderful common denominator, chances are if I'm using a python web framework, I already know python, why do I need a slew of other random file formats and templating systems? While Turbo Gears did offer an interesting GUI API (all AJAX'ed up of course) its still fairly new, and as a result, wasn't really featureful enough for my needs, and I was stuck with it, so I ventured onward.

Now, I had passed over Django initially because some reading left me with the impression that it wasn't nearly as much of a 'Magical Framework' as the other 2. It turnes out, thats what makes it rock. While Django doesn't have a flashy "Build ____ in 10 min screencast', and doesn't try to make decisions for you, its basically a nice pythonic wrapper around all the nasty bits of working with the web. Django only has 1 real config file, and its just python declarations, to handle url mapping, you get regular expressions. I know it doesn't sound glamorus, but after only an hour or so with Django, its abundantly obvious it was designed by real web developers. Theres an incredibly powerful and sleek caching system, a down right dirt easy templating system (its basically python, 20 minutes and you have it down).

I think perhaps the single most defining design decision (and one that does a great job embedding the usefulness of Django) is the lack of 'toolkit' like elements in the API. Instead, JSON and XML serialization are made fast and easy to use. Django doesn't shove a website on you, its really just a set of libraries and tools but with a little more polish and glue. Not to short what Django offers, on the contrary,  I think it brilliant. I know python, so why shouldn't I define my models in SQLObject?

<offtopic> I wanted to apologize for the blog bumps I've been having, I think a post or 2 got reposted to some Planets, I hope it wasn't too irritating! </offtopic>


January 2, 2008

Pat Eyler
pate
On Ruby
» Practical Rails Projects Interview

To celebrate the close of the Holiday Practical Ruby and Rails blogging contest I wanted to post this interview with Eldon Alameda. He and I spent some time talking about his new book Practical Rails Projects and other Ruby and Rails topics. I'll be announcing the contest winners soon, until then, enjoy this interview. Why do you think Rails is a practical framework for Web development?

December 3, 2007

Von Fugal
no nic
ATOM von Fugal
» Rails :memory: revisited

As I was creating a new rails app, I used this previous post of mine to set up the in memory database. Well it’s time for an update. Apparently now the rails config/environments/*.rb are run in the context of Rails::Initializer. So instead of creating that context as in the previous post, you simply do:

        alias initialize_database_old initialize_database
        def initialize_database *args
          initialize_database_old
          load "#{RAILS_ROOT}/db/schema.rb" 
        end
0 comments

November 28, 2007

Pat Eyler
pate
On Ruby
» Holiday Blogging Contest

It’s been a while since I’ve run a blogging contest here but, just in time for the holidays, I’ve teamed up with Apress to run another one. Earlier this month, they released Practical Rails Projects, and in December, they’ll be publishing Practical Ruby Projects. The idea of ‘practical projects’ sounded like a great topic for blogging, and the folks over at Apress agreed. So

November 8, 2007

Hans Fugal
no nic
The Fugue :
» Send it to Obedience School

I have a little rails app that can have a lot of images on each page. It worked fine in development, but when I went to deploy it with mongrel behind apache's mod_proxy, it started behaving oddly. It would randomly and inexplicably not serve up thumbnails. I checked all my code, the thumbnails were being generated properly, and my code checked out. Apache would complain with something like this:

[error] proxy: error reading status line from remote server 127.0.0.1, referer: http://foton.fugal.net/album/detail/23
[error] proxy: Error reading from remote server returned by /foto/thumbnail/93, referer: http://foton.fugal.net/album/detail/23

Carefully watching my rails logs, I noticed they weren't mentioning the offending files (that Apache was complaining about), so I guessed the problem must be between Apache and my code, i.e. in Mongrel. So I fired it up with Lighttpd instead of Mongrel, and lo and behold it worked fine. To be fair, I didn't try upgrading Mongrel (from 1.0.1 to whatever's current—1.1 I think). Maybe this is a fixed bug. But now you know it's Mongrel's fault, if you're seeing something similar.

November 7, 2007

Phil Windley
pjw
Phil Windley's Technometria
» New Conferences on IT Conversations

This week, I published shows on IT Conversations from two new series: the Singularity Summit and RailsConf. Here are the show descriptions.

Rodey Brookes Rodney Brooks - The Singularity: A Period Not An Event - In the keynote presentation from the 2007 Singularity Summit, Rodney Brooks, Panasonic Professor of Robotics at MIT, explores many possible singularity futures based on decades of experience researching, inventing, and commercializing robots. During this presentation Dr. Brooks examines why we need robotics and AI as well as how the singularity will not be like it is portrayed by Hollywood.

David Heinemeier Hansson David Heinemeier Hansson - Rails 2007 Keynote - The next evolution of Rails isn't going to be a unicorn, according to David Heinemeier Hansson. In this keynote address at the 2007 RailsConf, Hansson talks about what the Rails community has and where it's going, and the gradual improvements Rails will see in the coming years.

There are many other new conferences, including Supernova and Defrag that will be coming along in the next few weeks and months. Watch for them--they're sure to give you something to listen to on those long winter nights.

Tags: itconversations rails singularity

November 5, 2007

Hans Fugal
no nic
The Fugue :
» X-Sendfile

I'm writing a little photo gallery of my own, because everything out there stinks. But sending big images files in Rails (using send_file and send_data) is slow, mostly because you tie up a whole rails process just feeding data to the web. Web servers like Apache, Lighttpd, and Mongrel are good at serving static files, let them do it.

That's the idea behind X-Sendfile. If you send an X-Sendfile header with the path of the file you want to send, then a supporting webserver will do the dirty work and do it fast, and you can get on with serving other requests.

That's the theory anyway, but there's some bumps in the road. First, AFAICT mongrel doesn't support X-Sendfile. This is fine when mongrel is running behind an Apache proxy which does, but kind of throws a wet blanket on development and apachephobes like myself. Ok, apachephobe might be a bit strong, but I don't want to set that monster on my laptop just for some rails development. So mongrel's out. Correct me if I'm wrong.

Lighttpd supposedly invented X-Sendfile, but 1.4.x and earlier don't seem to support it. Instead, you have to use the header X-LIGHTTPD-send-file. Also, it doesn't work unless Content-Length is properly set (or perhaps if it's absent). This is bad news for rails users, since a bug in rails causes the Content-Length header to be set to the content, which is not the file. If you do render :nothing => true, then the content is one space character, and the Content-Length is 1, and Lighttpd defiantly refuses to fix it. So you either have to work around the rails bug, or upgrade to lighttpd version 1.5.x (now in release candidate) which supposedly works (I haven't tested it—I can't get it to compile on Leopard). I say bug in rails, but frankly I'm more inclined to consider this bad behavior on the part of lighttpd. In that vein, here is a patch for lighttpd version 1.4.18 that will enable both X-LIGHTTPD-send-file and X-Sendfile headers with rails 1.2.3 which has the Content-Length resetting behavior. It makes lighttpd set the Content-Length on its own. Thanks to stbuehler for the patch.

--- src/mod_fastcgi.c.orig      2007-11-05 13:52:47.000000000 -0700
+++ src/mod_fastcgi.c   2007-11-05 13:55:17.000000000 -0700
@@ -2530,22 +2530,28 @@
                }

                if (host->allow_xsendfile &&
-                                   NULL != (ds = (data_string *) array_get_element(con->response.headers, "X-LIGHTTPD-send-file"))) {
+                                   ((NULL != (ds = (data_string *) array_get_element(con->response.headers, "X-LIGHTTPD-send-file")))
+                                     || (NULL != (ds = (data_string *) array_get_element(con->response.headers, "X-Sendfile"))))) {
                    stat_cache_entry *sce;

                                         if (HANDLER_ERROR != stat_cache_get_entry(srv, con, ds->value, &sce)) {
-                                               /* found */
-                                                con->parsed_response &= ~HTTP_CONTENT_LENGTH;
-
+                                               data_string *dcls = data_string_init();
+                                                /* found */
                        http_chunk_append_file(srv, con, ds->value, 0, sce->st.st_size);
                        hctx->send_content_body = 0; /* ignore the content */
                        joblist_append(srv, con);
-                                       }
-                                        else
-                                        {
-                                               log_error_write(srv, __FILE__, __LINE__, "sb",
-                                                       "send-file error: couldn't get stat_cache entry for:",
-                                                       ds->value);
+
+                                               buffer_copy_string_len(dcls->key, "Content-Length", sizeof("Content-Length")-1);
+                                               buffer_copy_long(dcls->value, sce->st.st_size);
+                                               dcls = (data_string*) array_replace(con->response.headers, (data_unset *)dcls);
+                                               if (dcls) dcls->free((data_unset*)dcls);
+
+                                               con->parsed_response |= HTTP_CONTENT_LENGTH;
+                                               con->response.content_length = sce->st.st_size;
+                                       } else {
+                                               log_error_write(srv, __FILE__, __LINE__, "sb",
+                                                       "send-file error: couldn't get stat_cache entry for:",
+                                                       ds->value);
                                         }
                }
--- src/response.c.orig 2007-11-05 14:08:26.000000000 -0700
+++ src/response.c      2007-11-05 14:04:49.000000000 -0700
@@ -59,7 +59,8 @@
    ds = (data_string *)con->response.headers->data[i];

    if (ds->value->used && ds->key->used &&
-                   0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1)) {
+                   0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1) &&
+                   0 != strncmp(ds->key->ptr, "X-Sendfile", sizeof("X-Sendfile") - 1)) {
            if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Date"))) have_date = 1;
            if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Server"))) have_server = 1;

Then, you need to configure your lighttpd server. Run script/server lighttpd once to generate config/lighttpd.conf, and add this bit to the fastcgi.server section:

    "allow-x-send-file" => "enable"

Finally, use it—either by setting the X-Sendfile header manually or by using the rails x_send_file plugin (I recommend the latter).

Here's some links for more reading:

September 21, 2007

Phil Windley
pjw
Phil Windley's Technometria
» Installing Rails on Fedora

I'm building a virtual machine (VMWare flavor) for use with Rails development. After installing Fedora, there were a few things I had to do to get everything ready. I thought I'd take a minute and document them in one play for the next poor soul.

First, I don't know what I do wrong, but the GUI auto-update feature seems more trouble than it's worth. I like doing it manually. So the first thing to do is:

sudo /usr/bin/yum -y update

I've found that the Yum system can get corrupted and hang (I think I do this by force quitting the auto-update tool). Alternantely, you might see a bunch of errors. To fix that, I do the following:

sudo rm -f /var/lib/rpm/__db.*
sudo rpm --rebuilddb

Next, I install or update some other tools:

sudo /usr/bin/yum -y install \
sudo \
wget \
tar \
gzip \
make \
gcc \
mysql \
mysql-devel \
mysql-server \
ruby \
ruby-libs \
ruby-mode \
ruby-rdoc \
ruby-irb \
ruby-ri \
ruby-docs \
ruby-devel \
ruby-mysql \
rubygems \
subversion \
lighttpd \
lighttpd-fastcgi \
httpd \
ImageMagick \ 
ImageMagick-devel

Now, we're ready to install rails and some other gems:

sudo gem install rails --include-dependencies
sudo gem install rmagick

If gem complains about "Could not find rails..." you need to reset the gem cache. The correct path can be found using the command gem env.

sudo rm -rf /usr/lib/ruby/gems/1.8/source_cache
sudo gem update

If you're going to use MySQL, be sure to set it to start up and set a root password:

sudo /sbin/chkconfig mysqld on

/usr/bin/mysqladmin -u root password 'new-password'
/usr/bin/mysqladmin -u root -h localhost.localdomain password 'new-password'

If you're going to use FastCGI with LightTPD, then you'll need to install the FastCGI code:

curl -O http://www.fastcgi.com/dist/fcgi-2.4.0.tar.gz
tar xzvf fcgi-2.4.0.tar.gz
cd fcgi-2.4.0
./configure --prefix=/usr/local
make
sudo make install
cd ..

And the Ruby FastCGI support:

curl -O http://rubyforge.iasi.roedu.net/files/fcgi/ruby-fcgi-0.8.7.tar.gz
tar xzvf ruby-fcgi-0.8.7.tar.gz
cd ruby-fcgi-0.8.7
ruby install.rb config --prefix=/usr/local
ruby install.rb setup
sudo ruby install.rb install
cd ..

And the fcgi gem:

sudo gem install fcgi

I also need RMagick (the Ruby ImageMagick package) installed. Notice that I installed ImageMagick in the yum command above. To install RMagick, I used the gem install:

sudo gem install rmagick

Note that the ImageMagick install I got from yum had been built with the configuration option for TrueType fonts, so it was looking for those and failing. You can see what fonts your installation is looking for using the convert command:

convert -list type

You'll see path information for the configuration files as well as the various fonts each type file is loading. I changed my type-windows.xml file to look like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE typemap [
  <!ELEMENT typemap (type+)>
  <!ELEMENT type (#PCDATA)>
  <!ELEMENT include (#PCDATA)>
  <!ATTLIST type name CDATA #REQUIRED>
  <!ATTLIST type fullname CDATA #IMPLIED>
  <!ATTLIST type family CDATA #IMPLIED>
  <!ATTLIST type foundry CDATA #IMPLIED>
  <!ATTLIST type weight CDATA #IMPLIED>
  <!ATTLIST type style CDATA #IMPLIED>
  <!ATTLIST type stretch CDATA #IMPLIED>
  <!ATTLIST type format CDATA #IMPLIED>
  <!ATTLIST type metrics CDATA #IMPLIED>
  <!ATTLIST type glyphs CDATA #REQUIRED>
  <!ATTLIST type version CDATA #IMPLIED>
  <!ATTLIST include file CDATA #REQUIRED>
]>
<typemap>
</typemap>

This did the job, but beware that it may break other things you want to use ImageMagick for. I just know it worked for what I wanted to do.

Finally there are a few small jobs.

  • Add /usr/local/lib to /etc/ld.so.conf and run /sbin/ldconfig.
  • Add a alias for root to /etc/aliases. Don't forget to run newaliases.
  • Set up hostname. I like to edit /etc/sysconfig/network directly, but that's OS specific.
  • Set up any users. Be sure to set passwords.
  • Run chkconfig --list |more and turn off anything you don't need. I usually turn off bluetooth, cups, and yum-updatesd for starters. Turn on anything you do (like mysqld).
  • Set up /etc/sudoers. I can't tell you what to do since that's specific to what you are setting up. The simplest configuration is to use set it up so that anyone in group wheel can be a sudoer. Then add the wheel group to each user who should be able to sudo.

At this point, I'm unsure that the FastCGI is working completely with LightTPD. I'll add more information if something changes.

Tags: linux howto rails ruby

August 10, 2007

Von Fugal
no nic
ATOM von Fugal
» Rails and SQLite3: Default Values

Here’s another rails fix. This one is for SQLite3 >= 3.3.8. SQLite decided to return sql strings for the default values shown in table definitions. This broke rails, the rails people got mad and won’t introduce a workaround. Well here’s my workaround.

sqlite_fix.rb:
module ActiveRecord
          module ConnectionAdapters
            class SQLiteAdapter < AbstractAdapter
              def columns table_name, name=nil
                table_structure(table_name).map do |field|
                  /^'?(.*)'?$/.match field['dflt_value']
                  field['dflt_value'] = $1
                  SQLiteColumn.new(field['name'], field['dflt_value'], field['type'], field['notnull'] == "0")
                end
              end
            end
          end
        end
Include it at the end of environment.rb. That’s it! 0 comments

August 5, 2007

Von Fugal
no nic
ATOM von Fugal
» Rails :memory: testing in SqLite

I wanted to get that nifty :memory: db thing working for the test database in Rails. There are a sparse few articles floating around telling you how to do this. All of them, IMHO, are kinda ugly, or at least not-so-elegant. Here’s my answer, which took a lot of digging around in the inner workings of rails to come by.

First, do what everyone else tells you, put this in your config/database.yml:
        test:
          adapter: sqlite3
          database: ":memory:" 
        
Once you got that, you have to have some way of loading the schema into your memory db every time you run the test. I found that the best place to do this is in config/environments/test.rb. If you have an even better place, please let me know. At first I thought I could just load "#{RAILS_ROOT}/db/schema.rb" and be done with it. Alas, at this point there is no established connection to the db. So we have to modify things in such a way that this cute little command will get run just after establishing the db connection, but before the db is accessed. I did it like so:
        module Rails
          class Initializer
            alias initialize_database_old initialize_database
            def initialize_database
              initialize_database_old
              load "#{RAILS_ROOT}/db/schema.rb" 
            end
          end
        end
        
Then don’t forget to rake db:schema:dump before running rake test.

There’s probably other things you could do, like use ActiveRecord::Base.establish_connection instead of Initializer.initialize_database.

I break the above code block into lib/memdb.rb and simply require that inside of config/environments/test.rb. I tried to just add a metaclass to the config variable you see in test.rb but that is apparently some kind of impostor, because it didn’t work. Anyway, armed with this knowledge someone could probably make a pretty sane plugin to cleanly bring you :memory: testing.

0 comments

August 1, 2007
» Does Oracle really love Rails?

If one searched for Oracle and Rails they're bound to turn up a bunch of results that appear to indicate that Oracle is on the Rails bandwagon. How Web2.0 of them. (I'm trying to think of some funny snide remark about a rails acquisition, but can't

July 4, 2007

Von Fugal
no nic
ATOM von Fugal
» Acts as Dead?

Been a while… So my blog was broken just now, not sure for how long. Not more than a month I think. The problem was in the acts_as_taggable plugin, which rumor has it is dead. For now I will still use it, and describe the fix in case it also is broken for you. The problem is in the join table. The geniuses decided to make the join table <tag class>_<taggable class>. This is backwards from the regular has_and_belongs_to_many convention in activerecord. Somewhere, somehow, this backwardsness was reversed. I had it using it’s default join table before (tags_posts) and it broke as now it’s looking for posts_tags. So I add an option to the call:

acts_as_taggable :join_table => :tags_posts

I suppose I could have changed the table name, but at least this way it will never (hopefully) break again. I’m not quite sure how this default behavior changed in the first place.

0 comments

May 2, 2007

Pat Eyler
pate
On Ruby
» erubycon Contest

Continuing my happy tradition of letting readers win cool stuff, I have another contest to get started. Before I spill the beans (and tell you what you need to do to win), I’d like to fill in a little bit of background. Last year, RailsConf and several smaller conferences joined RubyConf on the list of places discriminating rubyists might be found. This year, the regional

April 11, 2006

Rob Merrell
no nic
» Calculate distance between zip codes

Well, I’m a little behind on getting a screencast of AssocUpload out, so I thought that I would post this little tidbit. Most of the information here I gleaned and converted to ruby from zipdy

Basically to calculate the distance between two zip codes one needs to use the great circle formula. It’s actually not that complicated of a formula considering what it does. Given the longitude and latitude of the zip codes (provided in a CSV file on the zipdy site) the distance can be calculated.

In this code the distance between the two zip codes are in miles. To change to another unit of measure change the constant (3956) at the bottom of the equation.

In a site that I’m currently working on we needed to find some specified art dealers within a 50 mile radius of the entered zip code. I tested the application performing these equations on a set of 300 pairs of latitude and longitude to see how long it would take to process big sets of data. It did the 300 in about 2 or 3 seconds.

This equation could be further optimized by storing the radian values in the database for the long/lat instead of decimal degrees. I also assume that one could find the number of radians per mile, and further delimit the data.

See the code

March 23, 2006

Rob Merrell
no nic
» Rails segfault woes

So I’ve been working on a few projects at work in rails. Things have been going really well time wise, and stability wise. Well as it comes time to start hosting these sites on our RackSpace server I had trouble getting rails to play nicely with my apps. The trouble? Segfaults.

I started getting random segfault problems, or so it seemed. As it turns out after some dumb luck I deduced that it was the ruby mysql api that was causing the segfault. Well, I googled and found nearly nothing about this problem so I tried reinstalling it via gems, which didn’t work so I tried getting the source and compiling it myself. Still nothing.

Then after a while of beating my head against the wall I decided to take a look at the packages installed on our server. The mysql-devel package was from a completely different version than our actual running server. I’m not talking about something like 4.1 to 4.2, it was more like 3.2 to 4.1. Anyways after getting that problem resolved a file in the mysql-devel package 4.1 called mysql_config was installed. Now there is no real mention of the necessity of this file anywhere but here, so listen well. You need mysql_config for it work!!! In the aftermath of everything it seems like well duh, but it wasn’t one of those apparent things.

After compiling it with mysql_config on my system it worked like a charm. And I got my blog up!