• New RubyOSA Website April 12th, 2007

    Posted by Mike Naberezny in Ruby   -   1 Comment

    RubyOSA now has a new website! It has a fresh look thanks to Derek DeVries and the Maintainable design team:

    The new site features updated information from Laurent and I, including a new guide. Over the coming weeks, we’ll continue to expand and improve its content.

    Please let us know what you think about it!

    Update: This post was featured on Laurent Sansonetti’s diary.

  • Maintainable Software Hiring PHP Developer April 5th, 2007

    Posted by Mike Naberezny in PHP   -   Comments Off

    Maintainable Software is now hiring a PHP developer. This is a full-time, salary position. We are headquartered in the San Francisco Bay Area but this is a telecommute position. We don’t care where you are as long as you are a talented developer and passionate about creating great software.

    You should have:

    • Strong understanding of XHTML, CSS, and standards-based design
    • Object Oriented Programming experience and familiarity with testing
    • Knowledge of key differences between PHP 4 and 5 and have used PHP 5
    • Some experience with XML and web services
    • Familiarity with MySQL and be able to write SQL queries
    • Understanding of source control including branching and tagging
    • Working knowledge of the UNIX shell and configuring Apache with PHP
    • Strong work ethnic, be a team player, and have excellent references

    Maintainable is a great company with some nice perks. You’ll work with other top notch developers on a variety of different projects, get exposure to new technologies, and even a MacBook Pro to keep you happy while you develop.

    For more about the position and how to apply, please visit the careers section of the Maintainable website.

    Update: The position has been filled. Thank you to everyone who applied and please continue to watch here for future openings.

  • OSA::ObjectSpecifierList#every March 26th, 2007

    Posted by Mike Naberezny in Ruby   -   Post a comment

    For those of you who aren’t yet on the RubyOSA list (you should be), Laurent just committed a nice new feature to OSA::ObjectSpecifierList. It’s actually been there since last week, in the form of some method_missing hackery, but we finally decided to take that out and call it #every.

    Sometimes you need to collect an attribute from every object in the specifier list. Normally, you’d do something like this:

    names = OSA.app('iCal').calendars.collect { |c| c.name }

    Symbol#to_proc fans use the convenient form:

    names = OSA.app('iCal').calendars.collect(&:name)

    Now, OSA::ObjectSpecifierList also has the #every method:

    names = OSA.app('iCal').calendars.every(:name)

    The difference is subtle but #every will fetch all of the attributes in a single Apple Event, something not possible when iterating over each item in the collection. For most purposes this is not important but it is a nice feature that could make a difference on larger collections.

    This feature is currently in the RubyOSA trunk and will appear in the next stable release (coming soon).

    Update: RubyOSA 4.0 has been released and includes this feature!

  • DRY up testing in Rails with Autotest March 23rd, 2007

    Posted by Mike Naberezny in Ruby, Testing   -   Post a comment

    As Rails developers, we’ve been trained hard to test early and test often. We are also acutely aware of the DRY principle (Don’t Repeat Yourself). However, these ideas don’t quite agree in Rails because in our test-code-test cycle, we’re constantly typing rake every time we need to run our tests.

    Autotest will DRY up your testing by running your tests automatically whenever your files change. In this article, we’ll explore Autotest:

    Installation

    Autotest is a smart little program included in the ZenTest bundle of goodies. To install it, you’ll just need to install the gem for ZenTest.

    gem install ZenTest

    Depending on how your system is set up, you might need to run this as the root user or through sudo.

    Starting Autotest

    Running Autotest is as simple as running rake. First, change to the root directory of your Rails project. This is the directory that has Rakefile, app/, config/, etc. Next, run the autotest command:

    $ autotest

    Autotest will discover that it is running inside a Rails project and your tests will run just as they do with rake (or the wordier rake test).

    After your tests run, Autotest will not exit back to the shell prompt. It will then sit and poll your files. When it notices files that change, it will run the tests for only the files that you’ve changed! It will do this continuously until you stop it.

    Stopping Autotest

    Pressing Control-C once will run your entire test suite again.

    Pressing Control-C twice in quick succession will exit Autotest back to the shell prompt.

    Autotest Plugins

    Autotest includes a plugin mechanism that allows plugins to monitor different aspects of the testing lifecycle. Autotest includes a number of useful plugins out of the box.

    In the next sections, we’ll see how to activate the plugins and what functionality they provide.

    Coloring with RedGreen

    One of the problems of testing under rake and autotest is that a lot of output can be generated and when looking at the results, you sometimes have to filter out the normal output to see the failures.

    RedGreen is a simple Autotest plugin that solves this problem by coloring the summary lines of the test output either red or green to indicate whether the tests passed or failed:

    Red/Green for Autotest

    Autotest automatically looks for a dotfile (.autotest) when it is started. This file may be in your Rails project directory or in your home directory where it will be used by all projects.

    To install RedGreen or any other plugin, create the .autotest file with a simple require to load the plugin:

    # .autotest
     
    require 'autotest/redgreen'

    That’s it! When you run autotest again, the plugin will be automatically loaded and your test output colored.

    Notifications

    Autotest also comes with the plugins growl, snarl, and kdenotify. Each are installed the same way as shown above, simply add the require line to your .autotest file. These allow Autotest to communicate each respective notification system.

    Growl for Autotest

    Using one of these can be useful when running autotest in the background or in a minimized window. The screenshot above shows a Growl pop-up notification from Autotest under Mac OS X.

    Note that for Autotest to send notifications to Growl, the growlnotify utility must be installed. This comes in the Extras/ directory of the Growl disk image.

    Next Steps

    Autotest isn’t limited to plugins shown here. There are a number of other useful plugins you can explore and more are added all the time. The plugins can be found in /path/to/your/gems/ZenTest-x.x.x/lib/autotest.

    While Autotest can be an invaluable tool when testing Rails applications, it isn’t limited to Rails at all. Autotest can be used with an Ruby project that follows some simple conventions.

    Visit the Autotest section of the ZenTest RDoc to learn about this, writing plugins, and more.

    Update: This article was featured on Ryan Davis’ blog.

  • Rails Logging Tips February 24th, 2007

    Posted by Mike Naberezny in Ruby   -   Post a comment

    In this article, we’ll take a look at how to use the logging facilities built into Rails and then share a few tips:

    Accessing the Rails Logger

    Rails automatically sets up logging to a file in the log/ directory using Logger from the Ruby Standard Library. Do not confuse this with Log4r, a completely different library. The logfile will be named corresponding to your environment, e.g. log/development.log.

    To log a message from either a controller or a model, access the Rails logger instance with the logger method:

    class HomeController < ActionController::Base
      def index
        logger.info 'informational message'
      end
    end

    From outside a controller or model, you can pass the logger instance or access it with the constant RAILS_DEFAULT_LOGGER.

    Log Levels

    In the snippet above, a message is logged at the INFO level by calling a method of the same name (info).

    The levels available on the logger are (in ascending order): debug, info, warn, error, and fatal.

    Ruby’s Logger supports masking levels so the types of messages recorded in the log can be controlled. By default, Rails will log all levels (debug and higher) in every environment except production. In the production environment, it will only log info and higher. This behavior can be changed in the configuration for each environment.

    Filtering Sensitive Parameters

    When Rails receives a request, ActionController logs the request parameters. This is very handy for debugging but sometimes it’s not desirable to have certain parameters, such as passwords, stored as plain text in the log.

    Rails 1.2 introduced the filter_parameter_logging class method to remedy this:

    class ApplicationController < ActionController::Base
      filter_parameter_logging :password
    end

    The above will cause any parameter name matching /password/i to have its value replaced with [FILTERED] in the log. To filter multiple parameters, simply add them as extra arguments to filter_parameter_logging by separating them with commas. For other uses of filter_parameter_logging, see the ActionController documentation.

    Note: it’s important to remember that filter_parameter_logging will only filter ActionController request information. The parameters could still appear in any SQL queries being logged by ActiveRecord. However, SQL queries are not logged in the production environment by default.

    Creating Audit Logs

    Sometimes logging is required but putting the messages in the Rails log isn’t desirable. One such case is when keeping a separate logfile for auditing is a business requirement.

    To create an audit log, simply create a new instance of Logger and pass it a File instance for your own logfile.

    One possible source of confusion is the formatting of the log message due to a patch Rails makes to Logger. This can be seen when using irb as opposed to script/console:

    $ irb
    irb(main):001:0> require 'logger'
    => true
    irb(main):002:0> Logger.new(STDOUT).info('message')
    I, [2007-02-24T09:45:51.236763 #557]  INFO -- : message
    $ script/console
    Loading development environment.
    >> Logger.new(STDOUT).info('message')
    message

    As you can see, the message formatting is lost when run in the Rails environment. To format a log message when using Rails, create your own Logger subclass and implement the format_message method:

    class AuditLogger < Logger
      def format_message(severity, timestamp, progname, msg)
        "#{timestamp.to_formatted_s(:db)} #{severity} #{msg}\n" 
      end 
    end

    To use the new AuditLogger, instantiate it with a File instance:

    logfile = File.open('/path/to/audit.log', 'a')    
    audit_log = AuditLogger.new(logfile)

    Your new log is now ready to use by calling methods on it like audit_log.info 'message'.

    One important point to remember is that the logfile object does not implicitly flush to the file by default. This means that your code must call logfile.flush for the data to be written out. Alternatively, you can set logfile.sync = true to turn on implicit flushing.

    ActiveRecord Logging on the Console

    When debugging your applications with script/console, it can be very useful to see the SQL output of your ActiveRecord queries. One way to do this is to use tail -f on your logfile.

    However, this isn’t very convenient and shows all other log information as well. An easier way that can be done directly from script/console is to enter this line:

    ActiveRecord::Base.logger = Logger.new(STDOUT)

    This will cause the queries to be displayed immediately on the console as you interact with your ActiveRecord objects with method calls like Article.find :all.

    ActionController Logging on the Console

    Just like with ActiveRecord above, you can also redirect ActionController’s log output to the console when using script/console:

    ActionController::Base.logger = Logger.new(STDOUT)

    You can then observe ActionController activities when using using using the app object on the console, such as app.get ‘/’. For a brief tutorial on using app, see this post on Mike Clark’s weblog.

    Firebug Console

    Firebug is a popular extension for the Firefox browser that provides a number of useful capabilities, with a Javascript console being among them. The console is accessed by console.log('message') in Javascript.

    This means that any Rails view emitting this little Javascript call between <script&gt tags can write to the Firebug console.

    It also means that any RJS template can write to the Firebug console for debugging:

    page.call 'console.log', 'informational message'

    This can be very useful for logging debug information during AJAX requests where a popup from alert() isn’t desirable.

  • New Javascript Goodies February 24th, 2007

    Posted by Mike Naberezny in Javascript, Ruby   -   2 Comments

    On the Maintainable site today are two new articles on Javascript. Minifying Your Rails Javascript shows how to cut down your Javascript footprint with JSMin and Rake. Testing Javascript in Rails introduces the Test.Unit component of Scriptaculous.

    We also released Firebug RJS Errors, a tiny plugin that patches RJS to log errors to the Firebug console instead of its default alert() box.

  • Easier XML-RPC for PHP 5 February 19th, 2007

    Posted by Mike Naberezny in PHP   -   6 Comments

    A few weeks ago, I rewrote the Zend XML-RPC client as part of a customer project at Maintainable. After fixing a fair number of bugs and writing a test suite, I made some enhancements and usability improvements. You can learn more about the new XML-RPC client from its documentation. Here it is in a nutshell:

    Calling Remote Methods

    The new XML-RPC client has always functioned similarly to many existing PHP implementations, providing a call() method:

    $c = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
    echo $c->call('test.sayHello');

    The call() instance method accepts an optional parameter with an array of parameters to marshal to the remote method. These may be native PHP types or PHP objects representing XML-RPC types. The latter is useful for the XML-RPC datatypes that do not map directly to PHP equivalents, such as base64.

    Server Proxy Objects

    The above usage works fine for many purposes but could read easier and gets tedious after many method calls. One of the few advantages of serializing method calls with a protocol like XML-RPC or SOAP is that with a little extra work in the client libraries, the remote service can be exposed in a way that’s very close to a native PHP object. This is where the server proxy comes in.

    In the above example of test.sayHello(), the remote sayHello() method is in the XML-RPC pseudo-namespace test. We can use the new XML-RPC client’s getProxy() method to get a proxy to this remote namespace and then use it similarly to a normal PHP object.

    $c = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
     
    $test = $c->getProxy('test');
    echo $test->sayHello();

    Namespaces may be nested to any depth so the XML-RPC method foo.bar.baz() becomes $foo->bar->baz().

    Faults

    Faults resulting from the remote method call are automatically thrown as PHP exceptions. XML-RPC fault responses are thrown as Zend_XmlRpc_FaultException and transport errors are thrown as Zend_XmlRpc_HttpException. If this is not desirable for some reason, a doRequest() method provides a way to work with request and response objects directly.

  • Best Practices of PHP Development October 30th, 2006

    Posted by Mike Naberezny in PHP, Testing   -   4 Comments

    Slides from my ZendCon 2006 session are now available:

    It is a new, three hour talk that I developed and presented together with Matthew Weier O’Phinney. This is the second opportunity that Matthew and I have had to team up for a session at ZendCon and it was a great time again.

  • Introducing Zend Framework October 24th, 2006

    Posted by Mike Naberezny in PHP   -   Post a comment

    The April 2006 issue of php|architect magazine featured my article, “Introducing Zend Framework“. It can now be downloaded in PDF format. Thanks to php|architect for making it available for free.

  • DC PHP Conference Slides October 20th, 2006

    Posted by Mike Naberezny in PHP   -   1 Comment

    Slides from my DC PHP Conference talks are now available:

    Special thanks to my friends Chuck Hagenbuch, Matthew Weier-O’Phinney, and Paul M. Jones for their feedback and help preparing the talks.