Share an Apache Config With Dropbox

Like many, I run local development environments. I have no love for a shared development environment. Also like many, I split time between two computers—one at home and another at the office. Finally, still clutching the “like many” mantra, my work-life balance kind of sucks. My vocation is also my avocation, so when I’m working on something interesting, it follows me around from location to location, computer to computer with no regard for this mythical concept of balance.

I’ve always had different systems for work and play and it’s no secret that I’m a huge fan of Dropbox, so sharing what I need to and can has always been part of my setup. In the past, though, my systems have always been heterogeneous; a Mac at home, Windows or Linux at the office. Because the environments were different enough, sharing was often a rudimentary effort that involved multiple variations of a file that was optimized for its runtime. Still useful for access and versioning, but there’s no meaningful sharing going on there.

These days both of my machines are Macs these days (yay!) and both run Apache installed via MacPorts, so a few months back I decided it was time to share properly. My httpd.conf file was already in my Dropbox, as were a few projects that I like to have access to on either machine so I expected this to be easy. And it was.

Except that it wasn’t. The sand in the gears is that my username on each machine is different. That makes my home directory different on each machine and Macs, more so that either Windows or Linux, really encourage users to keep everything in their home directories. To some degree, that last statement is my own projection—I realize that it’s possible and even easy to install and store files anywhere—but I’ve really liked keeping everything in that tight of a grouping and wanted to continue doing so. That left me with the problem that I couldn’t hard code my paths.

Before we go on, I should outline my configuration at a very high level. I do everything web-related in virtual hosts. The reasons for doing so are beyond the scope of this post, but suffice to say that it’s something I think every developer should be doing. The fact that I still see developers working in circa-1998 directories beneath a single web root makes me crazy.

Anyway, back to the sharing. My Dropbox is in the standard location at ∼/Dropbox and my development environments are all in ∼/Development/domains. Similarly, for convenience, I keep my virtual host configs in individual files that I can easily include or uninclude. Those that I want to be able to access on either machine are stored in my Dropbox (∼/Dropbox/Application Support/apache/conf.d) and those that I don’t are stored in my Application Support directory (∼/Library/Application Support/MacPorts/apache/conf.d).

That’s a lot of resources tucked neatly into a directory that’s different on each machine that I want to share across, but fortunately Apache understands environment variables, so I just tweaked my httpd.conf and shared virtual host config files. I replaced each path that explicitly referenced my home directory with ${HOME}. For example:

Include "${HOME}/Dropbox/Application Support/apache/conf.d/*.conf"
Include "${HOME}/Library/Application Support/MacPorts/apache/conf.d/*.conf"

Once complete, I bounced Apache and everything worked.

Except that it didn’t. You didn’t really think it’d be that easy, did you?

Some time later, after a reboot, I noticed that Apache didn’t start automatically like it always had in the past. I don’t reboot often, so my Apache config changes were ancient history; I just chalked it up to a hiccup, started Apache manually and went on with my day. Eventually, in spite of the infrequency of reboots, I came to recognize a pattern. Something was wrong.

This post has become longer than I intended, so I’ll cut to the chase. The problem is that, at boot, Apache isn’t starting as me, so it doesn’t understand the ${HOME} directory I told it to use. Once booted, that’s not a problem, so manual starts worked just fine. I tried several solutions and asked questions related to this on StackOverflow here, here and here (in the order of their asking). Eventually I had to settle for a Linux-like file system config coupled with symlink usage to maintain my OS X consolidation.

I already had my Apache config file (/opt/local/apache2/conf/httpd.confJ) symlinked to a physical file in my Dropbox, so that was fine. Next I needed to access my shared and local virtual host config files, so I created /opt/local/apache2/conf.d. Inside of that directory, I created two symlinks. local pointed to my non-shared virtual host files in ∼/Library/Application Support/MacPorts/apache/conf.d and shared pointed to the shared config files in ∼/Dropbox/Application Support/apache/conf.d.

Next I needed to be able to access my development environments from outside of my home directory. I chose the Linux-like path of /var/www. I created a symlink such that /var/www pointed to ∼/Development/domains.

Finally, I just updated my Apache config so that it loaded the virtual host config files using a relative path:

Include "conf.d/*.conf"
Include "conf.d/*.conf"

And updated all of my virtual host configurations so that all resources were being accessed through /var/www instead of my home directory.

Git Tip: Ignore Changes to Tracked Files

Every once in a while, I find myself working on a project that forces me to modify key files—often config files—in order to get it running locally. In those cases, the last thing I want to do, for a number of reasons, is to commit those changes. That’s hard to do, though, since I regularly use git add . and/or git ci -a to commit everything I’ve changed. Make enough changes in enough files that you don’t want to commit and these changes begin to cause as many problems as they solve.

As is so often the case, it seems, Git comes to the rescue with its update-index command. Reading the documentation, it’s not really intended for this purpose, but its effectiveness as a “coarse file-level mechanism to ignore uncommitted changes in tracked files” is recognized. To apply it, simply make a change to a committed file, say, database.yml and execute git status. Git should report the modified file. Since we don’t want to commit, we don’t want to see this listed as a modified file until the end of time and we can’t ignore it (because it’s already being tracked), we need to tell Git to assume the file is not changed.

git update-index --assume-unchanged path/to/database.yml

I’ve been using this command since I learned of it a few weeks ago and it works perfectly for this use case. Inevitably, though, a question will arise:

What files have I marked this way?

Since those files will no longer appear in the modified list, can’t be easily found in a .gitignore file or exposed by removing a .gitignore file, there will eventually be a need to know this. Maybe you’re trying to get another instance running or maybe you’re just the curious sort and you’ve forgotten. Like many things in Git-land, the functionality exists, but is far from obvious. I asked on StackOverflow and Andrew Aylett provided the answer I was looking for.

If you ever find yourself needing to know, this command will display the files that have been marked as —assumed-unchanged.

git ls-files -v | grep -e "^[hsmrck]"

Enhancing SuperDuper Backups

I’ve been using SuperDuper for a few years now. It’s saved my tuchus a few times and provided tremendous convenience many times. In the last few months, though, I’ve noticed a few things that annoy me after the backup is complete:

  1. Growth
  2. Web Server Conflicts

Growth

I archive to a sparse bundle and those only grow. After backing up a few times, that bundle can get insanely huge. Over time, they actually take up more space than they need, but they can be compacted. I have two separate, bootable backups that I store on a single 320GB external hard drive, so this growth can quickly consume a disk that size.

Web Server Conflicts

I use an Apache instance that I installed via MacPorts. To stop and start that instance, I added the location of its apachectl executable to my path so that I can stop and start the web server the same way that I’m used to doing on my Linux servers. To ensure no confusion, I disable execute permissions on OS X’s native apachectl script. The problem is that OS X expects its apachectl script to be executable and its repair permissions operation makes this script executable.

Since I ask SuperDuper to repair permissions before every backup, the built in apachectl script becomes executable and if/when I have to bounce my web server, the command sudo apachectl restart actually starts the native Apache instance which creates conflicts (they share the same port) and all sorts of preventable mayhem that used to take me a while to track down until I got used to recognizing the symptoms.

Remediation

One of the things I love about SuperDuper is that is provides hooks into its process. These hooks allow me to write a script and tell SuperDuper to execute that script when the backup is complete. So I did.

#!/usr/bin/ruby
require 'logger'
log_file = '/Users/me/Desktop/post-backup.log'
File.delete( log_file ) if File.exists? log_file
log = Logger.new( log_file )
# 
# Compact the MWF backup volume if it's not currently mounted
# 
if !File.exists? "/Volumes/mbp17.daily.mwf"
  # system "hdiutil compact '/Volumes/SuperDuper Backups/mbp17.daily.mwf.sparsebundle' > #{log_file}"
  log.info 'Finished compacting mbp17.daily.mwf.sparsebundle'
end 
# 
# Compact the TTS backup volume if it's not currently mounted
# 
if !File.exists? "/Volumes/mbp17.daily.tts"
  system "hdiutil compact '/Volumes/SuperDuper Backups/mbp17.daily.tts.sparsebundle' > #{log_file}"
  log.info 'Finished compacting mbp17.daily.tts.sparsebundle'
end 
# 
# Ensure that the native OSX Apache install remains
# disabled after permissions are repaired.
# 
log.info 'Disabling execute permissions for OS X Apache components'
system 'chmod a-x /usr/sbin/httpd'
system 'chmod a-x /usr/sbin/apachectl'
system 'chmod a-x /usr/sbin/apxs'

As I mentioned above, I have two backups that run on a schedule. One runs Monday, Wednesday and Friday evenings and the other runs on Tuesday, Thursday and Friday evenings. The backup is currently running cannot be compacted because its volume is mounted. That explains the test for whether a backup image is mounted before attempting to compact it.

Because this is a new process, I create a log on my desktop and write a few things to it just in case there’s a problem. Because it’s on my desktop, my (mild) OCD reminds me to look at it and delete it regularly (read:daily). I’ll remove the log prints once I feel comfortable that everything is doing what it’s supposed to be doing.

Finally, I re-disable the executable permission on the native apachectl script as well as a few other executables that belong to OS X’s built-in Apache instance.

Learning Ruby on Rails: File Upload

Whenever I decide to pick up a new language – or framework – there are usually two ubiquitous problems that I like to try to solve immediately: authentication and file uploads. Over the years I’ve found that these are great learning tools for a couple of reasons.

  1. They’re well known problems. They’ve been around for a long time and the best practices for solving them are pretty well documented.
  2. They’re finite problems. There are only so many ways to skin these particular cats and the solutions are very contained. I could build an app whose sole purpose is to login, upload a file and display it.
  3. The problems may be well known and finite, but they’re not trivial. Trivial solutions don’t make for good learning tools.

This month, I’ve finally taken the plunge and picked up Ruby and Rails. That’s a two-fer (a language and a framework), so once again I started figuring out how to solve these same problems with the new toolkit.

Authentication

After looking around, I found that there is already an authentication plugin, AuthLogic, that looked remarkably comprehensive and solved that particular problem just about the same way I would have if I’d done it manually, but then threw a few more useful tools in the kit that I probably wouldn’t have. Additionally, it looked relatively easy to install and configure.

That sounded like a pretty good deal to me, so I followed along with Ryan Bates’ excellent Railscast and got authentication hooked up rather quickly. No point in re-inventing the wheel as long as the existing wheel is as good as or better than the one you’d have invented, right?

Upload

I did not, however, find a similarly comprehensive plugin for file uploads. There are a few out there – Attachment_fu and Paperclip seem to lead the pack – but none that appear to handle physical media the way I like to handle it. Since my wheel is better than (or at least different from) those wheels, this became my de facto learning experience.

Disclaimer: I only took a quick look at what these plugins had to offer, so maybe they’re closer to my way than it appeared. Nonetheless, I needed a problem to solve and this became the one.

Requirements

As I mentioned, my requirements are slightly different from most I’ve seen, so it’s probably worth outlining them really quickly.

  1. Store physical files to their own directory structure dedicated to user contributed content. In my Rails project, I have a Rails.root/public/bin/ directory for this. However, since I don’t want to store (what I hope will be) thousands of files or more in a single directory, I create 26 subdirectories named a-z. In each of those, I create 26 more directories also named a-z. Now I have 676 possible locations so my (potentially) huge number of files can be nicely distributed (for example, Rails.root/public/bin/r/m/file.ext) for performance.
  2. Store physical file metadata (file size, MIME type, URI, etc.) in the database. I often find myself needing or wanting to query this kind of data directly and I don’t want to have to do so through the application. I want easy access to find out how many images I have that are over 50KB, for example.
  3. Abstract the common functionality to allow the upload of many different types of file (images, videos, flash movies, etc.) with very little effort. In a traditional inheritance model, I might have a File class (a concrete class) that is extended by any type with specialized properties or actions.

For the sake of this article, I’ll keep this simple and focus on images as the only subtype. The extrapolation should be easy enough.

Approach

As I alluded to above, an image is-a file, so a simple inheritance model would be a perfect fit, but…

  1. Rails doesn’t offer much in the way of inheritance (no, single table inheritance is not a sufficient solution).
  2. “File” is a reserved word in the Rails framework.

The latter problem was easy to solve, so I created an Image model and a Binary model. The first, though, was a little trickier. Although Rails’, well, ActiveRecord’s, support for inheritance is non-existent, Rails offers something very helpful for this purpose: observer support.

At a Really High Level

From 10,000’, it’s quite simple (isn’t everything at that distance?). I create an image, but before the image object is actually saved, I want to hand off the physical file to the Binary class for uploading to a temporary directory, inspection and extraction of metadata. If that’s successful, I want to move the file to a permanent location and continue saving the image. If anything fails at any point in the process, I want to remove any database records and delete the physical file.

Code

Enough with the chit-chat, let’s write some code.

View

The only relevant view code is that for the form partial. It allows the user to enter a title for the image, a description and to select a file. Images have other properties (like width and height), but they’re derived and I don’t want the user to enter those.

<% form_for( @image, :html => { :multipart => true } ) do |f| %>
  <%= f.error_messages -%>
  <p>
    <%= f.label :name, 'Title' %>
    <%= f.text_field :name %>
  </p>
  <p>
    <%= f.label :upload, 'File' -%>
    <%= f.file_field :upload -%>
  </p>
  <p>
    <%= f.label :description %>
    <%= f.text_area :description %>
  </p>
  <p><%= f.submit( 'Upload' ) %></p>
<% end %>

Controller

As with most, there are two controller actions in play to upload a new image: new and create.

class ImagesController < ApplicationController
  def new
    @image  = Image.new
  end

def create @image = Image.new( params[:image] ) @image.user_id = current_user @image.save! flash[:notice] = “Successfully created image.” redirect_to @image rescue => e logger.error( ‘Upload failed. ‘ + e ) flash[:error] = ‘Upload failed. Please try again.’ render :action => ‘new’ end end

The only significant – and perhaps non-obvious – difference from the basic scaffold code is the move away from if @image.save! to an exception-centric approach. I did that, first, because I can raise exceptions anywhere and how they’re handled is absolutely predictable. I can’t always return false and be sure that activity simply stops. Second, Rails has a very nice feature, in my opinion, that encapsulates the entirety of a save action in a transaction. If an exception is raised at any time during the save process, the transaction is rolled back and it’s like nothing ever happened. That’s a lot of goodness for absolutely no effort and I wanted to take advantage of it.

Models and Observer

I find it easiest to think about the model code in the order in which it’s encountered, so I’m going to split the code views and build on them accordingly. If that proves unpopular, I’ll publish a more unified version of the model code.

First, a snippet of the Image model to show its association, accessor attribute and validation.

 class Image < ActiveRecord::Base
   belongs_to :binary

validates_presence_of( :upload ) attr_accessor :upload # snip (for now) end

The observer is watching the Image model. When the save process is kicked off (and because we’re creating a new image), the BinaryObserver is engaged and its before_create callback is executed. In that callback we’re offering the Image model the opportunity to execute any instructions it may have before_ the physical file is actually uploaded. If no exceptions are raised, the Binary model is told to upload the file.

 class BinaryObserver < ActiveRecord::Observer
   observe :image

def before_create( model ) # in this case, the Image model is passed if model.respond_to?( ‘before_upload’ ) model.before_upload( model ) rescue raise end binary = Binary.new.upload( model.upload ) # snip (for now) end

The file uploaded by the form is passed to the Binary model and stored to a temporary location on the server. The upload method stores the file in a temporary location so that it can be further inspected and/or validated by the subtype for any details that may be relevant to that subtype. Any file that remains in the temporary location is assumed to be orphaned and is subject to deletion. Any file that makes it into the bin/ directory hash is assumed to be live and is left alone unless there’s a good reason for touching it.

 class Binary < ActiveRecord::Base
   has_one :image

def upload( uploaded_file ) self.name = uploaded_file.original_path self.mime_type = uploaded_file.content_type # get_bin_root() returns File.join( Rails.root, ‘public’, ‘bin’ ) save_as = File.join( get_bin_root(), ‘_tmp’, uploaded_file.original_path ) File.open( save_as.to_s, ‘w’ ) do |file| file.write( uploaded_file.read ) end self.extension = File.extname( self.name ).sub( /^\./, ‘’ ).downcase self.size = File.size( save_as ) self.path = save_as.sub( Rails.root.to_s + ‘/’, ‘’ ) self.uri = get_uri_from_path() self.save! return self end end

Since this is a specific type of file – an image, I want to extract certain additional properties (in this case, the image’s width and height) from the physical file before the final save. I may also want to perform additional validation on the physical file while it’s stored in its temporary location on the file system. That’s where the custom after_upload callback comes into play.

 # models/binary_observer.rb
 class BinaryObserver < ActiveRecord::Observer
   observe :image

def before_create( model ) if model.respond_to?( ‘before_upload’ ) model.before_upload( model ) rescue raise end binary = Binary.new.upload( model.upload ) if model.respond_to?( ‘after_upload’ ) model.after_upload( model, binary ) rescue raise end end

The original model (Image, in case you’ve forgotten) is passed along with the Binary object. The image is read and additional metadata pertinent only to images (not to generic files) is extracted and written to the model.

# models/image.rb
 require ‘RMagick’ # The rmagick gem is required to inspect/manipulate images

class Image < ActiveRecord::Base belongs_to :binary validates_presence_of( :upload ) attr_accessor :upload def after_upload( model, file ) # Insert any physical file validation requirements here image = Magick::Image::read( file.path ).first self.width = image.columns self.height = image.rows end end

Assuming everything goes well, we now have complete Binary and Image models as well as a valid file on our file system. To close out, we’re going to tell the Binary class to move the file to its permanent location, update any model properties accordingly and send the user to the image page so they can see their new upload.

class BinaryObserver < ActiveRecord::Observer
  observe :image

def before_create( model ) if model.respond_to?( ‘before_upload’ ) model.before_upload( model ) rescue raise end binary = Binary.new.upload( model.upload ) if model.respond_to?( ‘after_upload’ ) model.after_upload( model, binary ) rescue raise end binary = binary.store() model.binary_id = binary.id model.active = 1 rescue => e # # Because we’re raising an exception, Rails will rollback # the binary save operation at the database level. # File.delete( File.join( Rails.root, binary.path ) ) if binary # # Rethrow any exception that was raised. # raise e end end

What I Like

  1. It should take very little effort to support a new file type.
  2. The view and controller for a subtype doesn’t deviate very far from what’s provided by scaffolding. That makes for easy reading for new developers.
  3. The controller really has very little to do. The work is done down the stack by the models. I love a skinny controller.

What I Don’t Like

  1. I’d prefer to add the upload virtual attribute to the Binary class so I don’t have to add it to each new subtype, but doing so made the views more complex. Overall, it just feels like less effort to do it this way.
  2. Although it will take very little to support a new file subtype, it will require some effort (updating the observer, including the attribute accessor, etc.). Ideally, I’d like to have it be a no-effort kind of endeavor. That’s probably just wishful thinking.

It should be fairly clear from the title and intro that I’m on the (very) short side of the learning curve with Ruby & Rails. It’s entirely possible that I’ve made a mockery of any number of best practices or conventions. Constructive criticism is welcome. I’ve learned a lot by doing this, input from experience is never a bad thing.

Learning CakePHP: Validation

I started developing for the web sometime in 1995 while I was still in the military. I “turned pro” in 1997. At that time there were two methods of data validation: client-side and server-side. Yeah, I know, that’s still all we have, but I think that Ajax has helped to blur the line between the two – perceptually, I mean, not technically.

Then

Even back then I hated duplication. Frankly, I hated doing validation at all; I damn sure hated doing it twice. Moreover, I hated server-side validation because doing it (without also doing a whole lot of extra work) involved:

  1. Submitting a form to an action page
  2. Having that action page validate the form values
  3. Displaying (what was usually) an ugly error message to the user
  4. Asking the user to use their Back button to return to the form
  5. Expecting the user to remember the errors that had been displayed
  6. Asking the user correct each error
  7. Rinse
  8. Repeat

That’s a lot of lousy user experience. Since that sucked so mightily, I chose client-side. With Javascript, I could validate user input without having to make the round trip to the server. Talk to me all you want about graceful degradation, but first of all, that concept didn’t exist in 1996 and second…this is Javascript we’re talking about.

Now

With the relatively recent proliferation of API‘s, server-side validation has taken on a whole new urgency. With multiple gateways into an application’s business core, it’s more critical than ever that validation be moved as far down the application stack as possible in order to eliminate redundancy and, in the process, ensure consistency. For most applications that I’ve built in the last 5 years or so, there’s been some kind of API involved.

With CakePHP

Once I had worked with CakePHP for a few months, I got comfortable enough to start thinking about validation and how I wanted it to work from end-to-end. I had a few requirements:

  1. I only wanted to write my rules and messages once. Do something once and you don’t have to worry about consistency. One less pain point is always going to be a good thing.
  2. I wanted to be able to validate without necessarily saving. Most of the time I’d be doing both, but decoupling them is just a good idea.
  3. Hide from the user the fact that my validation was happening on the server. To them, generating and displaying error messages should be a smooth and seamless experience.

I came up with something that seems reasonably elegant and has met my needs to date.

The Basics

Although I’m not a big fan of the semantics, CakePHP nicely decouples the validation and save actions. I would expect this of any framework, of course, but that’s a place to start. If I’m validating something independent of a save operation, I usually want that validation to return one or more error messages. CakePHP makes this easy and even offers me a convenient means of using my preferred semantics.

Never, Ever Mess With the Core

This is one of my basic tenets for developing with third-party libraries. Messing with core code is almost certain to destroy your upgrade path. Find another way.

In this case, I want to be able to validate model data based on the rules defined by that model and I want this validation to be available to all models in my application in exactly the same way. To do that, I created a copy of CakePHP’s app_model.php file as app/app_model.php. By creating a copy in my app/ directory, I can preserve my upgrade path, but still inherit from the proper parent class.

Validate

In the newly copied AppModel class, I added this function:

/**
 * function validate
 * 
 * Validates model data. This function can be called independently
 * on any model for validation independent of a save operation. It
 * can also be overridden, for example, by a model requiring more
 * complex validation.
 *
 * param   $data
 * return  array     An array of error messages or an empty array
 *                   if the data validates properly.
 */
public function validate ( $data = array() ) { $this->set ( $data );

/** * Corrected based on input from Miles Johnson in the comments * below. */ return !$this->validates() ? $this->validationErrors : array(); }

That snippet alone provides basic validation across my entire application with a simple line of code:

Model->validate ( $this->data )

Complex validation

Something of a misnomer since this isn’t very complex, but there are times when more is required. For example, if I have customers and vendors that have addresses, I usually want to break the address out so that the data structure can be shared. Separate table, separate model. The data is abstracted, but I can’t really have a valid customer or vendor unless their address also validates. To do that, I need to override my simple validate() method in the Vendor (or Customer) model so that I can do just a little bit more:

public function validate ( $data = array() ) {
   return array_merge ( $this->Address->validate ( $data ), parent::validate ( $data ) );
}

User Interface

As I alluded to initially, what I really want to do is to perform server-side validation while providing the illusion of client-side validation. To do that, I employ the appropriate controller. If I’m able to submit the entire form via Ajax, this becomes trivial because the same request can perform both actions (provided no errors are reported). Here’s how it might look on a vendor application page (/vendors/apply):

public function apply() {
   $errors = $this->Vendor->validate ( $this->data );

if ( !empty ( $errors ) ) { /** Package the errors for an ajax return */ echo json_encode ( array ( ‘errors’ => $errors ); ); exit(); } /** If there are no errors…save */ exit(); }

If I want to validate first (again, via Ajax) and then submit to a different action page, all I have to do is create a validate() method in the controller, make the Ajax call to that and, if no errors are returned, submit the form to the preferred action. If errors are returned, I can use jQuery’s JSON parser to extract the messages and drop them on the screen.

With this technique, I can consolidate my validation, rarely write more than one block of code to access that validation and present the results to a user attractively without that user ever being aware that anything more than client-side error handling has been done. What technique(s) do you employ to minimize your validation headaches?

← Earlier Posts Page 1 of 34