Web and Database Programming.

Welcome!

I’m a software professional with 10 years experience spanning the full development life cycle–especially requirements analysis and database development. I’ve worked for small startups, large corporations, and government entities. My current interest is developing web applications with Ruby on Rails and related tools (MySQL, CSS, nginx/Passenger, Capistrano, Shoulda, git).

I collaborate with graphic designers to create solutions for business owners' websites. I also support general business computing needs.


Beware two models on one table

Posted: July 22nd, 2010 | Author: Bill | Filed under: Uncategorized | No Comments »

I just diagnosed the root cause of a tractable bug.  The symptom was that I seemed to successfully delete a collection item from a model, but that delete wouldn’t save to the database. It stems from a rather complicated data model that looks like this:

class Person < ActiveRecord::Base
has_many :custom_properties, :dependent => :destroy
has_many :boilerplate_properties, :through => :custom_properties
...
class BoilerplateProperty < ActiveRecord::Base
has_many :custom_properties, :dependent => :destroy
has_many :people, :through => :custom_properties
...
class CustomProperty < ActiveRecord::Base
belongs_to :person
belongs_to :boilerplate_property

The custom_properties table looks like this:

+-------------------------+--------------+------+-----+
| Field                   | Type         | Null | Key |
+-------------------------+--------------+------+-----+
| id                      | int(11)      | NO   | PRI |
| person_id               | int(11)      | NO   | MUL |
| boilerplate_property_id | int(11)      | NO   |     |
| custom_value            | varchar(255) | YES  |     |
+-------------------------+--------------+------+-----+

The purpose of the model is to associate properties (name value pairs) to people. But I wanted to have both:

  • Frequently-used (boilerplate) property name:value pairs in a jion model.
  • Frequently-used property names with infrequently used values.
    If I’d used two models and tables for these things, I’d have to duplicate the frequently-used property name data, which seemed like something to avoid from a maintenance perspective. So the custom_properties table solves this, by acting as a :though association to the frequently-used name:value and as the collection for infrequently-used values (stored in the custom_value field).

Again, the symptom was that I seemed to successfully delete a collection item from a model, but that delete wouldn’t save to the database. It turns out that I was deleting from the Person.boilerplate_property collection, but not the Person.custom_property. A single row in the database represents an item from each collection.

I’m considering that maintaining a small amount of duplicate data may be more straightforward…


SSL, nginx, passenger

Posted: June 23rd, 2010 | Author: Bill | Filed under: Uncategorized | No Comments »

I added some personalization features to a Ruby-on-Rails site and needed SSL for logging in and changing passwords. The steps I took were:

  • Install the ssl_requirement gem.
  • Update the controllers to use SSL where appropriate (documented with the gem).
  • Update the passenger gem.
  • Run passenger’s installer.
  • Use the advanced mode in order to compile nginx with the SSL module.
  • Update nginx configuration to serve SSL on port 443.
  • Purchase and install SSL certificate.

It was fairly painless.  Only one minor bugaboo:  You must run the passenger installer after updating the passenger gem, always.  The HelperServer in the passenger gem folder is compiled by the installer as well.  I got a bit stuck when nginx wouldn’t start right after I updated the passenger gem, but the nginx error log had a descriptive message.


Git submodules in Capistrano

Posted: June 6th, 2010 | Author: Bill | Filed under: Uncategorized | No Comments »

So, I’d added a module to my project by cloning it from github, and when I pushed it, the folder (on my Github’s’ project page) had a green arrow indicator. This means the folder contains a submodule.

Instead of pushing the cloned files, we’re going to create a pointer to the plugin so other copies of the repo will checkout the module from its own repo. If you deploy using Capistrano, you’ll have to make a small adjustment to make sure that happens. In your Capistrano config/deploy.rb file, put:

set :git_enable_submodules, true

And in RAILS_ROOT, put this in your .gitmodules file:

[submodule "vendor/plugins/awesome_nested_set"]
	path = vendor/plugins/awesome_nested_set
	url = git://github.com/collectiveidea/awesome_nested_set.git

When you run “cap deploy”, in addition to performing a “git pull”, Capistrano will also run a “git submodule init && git submodule update && git submodule sync.”


jQueryUI Autocomplete versus auto_complete

Posted: June 1st, 2010 | Author: Bill | Filed under: Uncategorized | No Comments »

I recently decided to upgrade the aging auto_complete plugin with jQueryUI’s Autocomplete widget.

It was mostly smooth sailing, but I had a bit of trouble getting the styling to look correct. jQueryUI was appending the Autocomplete results to the end of the html body, instead of after the text input where the user types his search query. This behavior seemed to contradict the documentation, so I submitted a bug report. It turns out this is intended behavior to account for the fact that IE does not recognize z-index, but the search results must obviously appear on top of all other page elements.

Fortunately, you can easily modify the default behavior of the search event and append it where you want it. I probably broke IE6 support, but if Google can drop it, why not?