Wow it's been quite a while since I last posted. In the meantime I've been working hard on RDT and RadRails at Aptana and the job has been great. I'm very lucky to have found a way to work on the open source projects I love full-time.
In that vein I'd like to announce that we've released the 1.0 of Aptana. This release is important for a number of reasons. First, we think the product is good-to-go for everyone. Second, we're announcing a Pro version of the IDE. This version is for users who want to support the project so we can keep going, or who want the extra features and perks that come with a license: nightly build access, priority support, IE Javascript Debugger, SFTP/FTPS support and all sorts of other goodies. The support, nightly builds, SVN access also apply to the other components of what we're now calling Aptana Studio: RadRails, iPhone, PHP and AIR. So if you want to be on the bleeding edge of RadRails/RDT development you'll probably want to look into getting a license.
Keep in mind that while we do offer a pro version for those who'd like to support us or the extra stuff, we are still shipping the same codebase (minus the commercial features) as an open source project under GPL. And we plan to remain an open-source company with an open source product. Here's hoping that model will work for us!
I'm proud to announce today that Aptana has hired me to work full-time on RDT, RadRails and integrating that work with their existing Aptana IDE which focuses on CSS, HTML and Javascript.
This announcement means that RDT will now have commercial backing (but will remain open-source and free!) and that you should see RDT and RadRails move forward at a much quicker pace than in the past.
This is also great news for RadRails users and Rails developers in general as integrating the two will give you code completion, outlines, help, debugging and much more across the entire stack - from model to controller to the HTML, ruby code, CSS and Javascript that make up your views.
It's a shame that this sort of thing happens, but I can't say I'm all that surprised. I've been working on RDT for nearly 4 years now and I can definitely say that people just don't pay for free things. You can beg for donations, but you shouldn't expect them. Given the amount of time and effort - and the sheer number of downloads - it just doesn't pay the bills to run an open source project that passively solicits donations. I estimate the per-user donations for RDT to be at about 1.4 cents*. And if we take out the one large donor? .00071 cents per user.
That doesn't quite cut it for rent and food, unless of course you get the entire world to use your product.
I wish Kyle and Matt well and hope that others from the community step forward and help lead the project onward.
* This estimate assumes we count RadRails users as RDT users, because RadRails contains RDT. It also uses just the raw zip downloads from Sourceforge for both projects. There is a large number of users we are not counting here who have downloaded via Eclipse's update site mechanism, and who use RDT from other distributions available.
I would like to take an existing SVN repository of a project (like say, Typo), check out a tagged version, create local modifications and save the modified version in a local/home SVN repository(my blog). Later, I'd like to sync up the local version to a new tagged version of the original repository (Typo), handle any merges locally and then check in the result into my local repository again. Rinse and repeat, ad infinitum.
Is SVK the right job for this? Has anybody done something like this? Essentially its the equivalent of creating a branch on a SVN repository but having that branch in an entirely separate SVN repository instance. I don't have experience with this, so I'd greatly appreciate any pointers anybody out there might have.
Wow. Steve Jobs has posted an open letter on Apple's website essentially calling for the big four music companies to abolish their restriction that music sold through iTunes be done with DRM. This combined with hints from Bill Gates that he'd love to see DRM dropped as well, may actually move the discussion to the right players - the music companies themselves. (After all, not only have they pushed for DRM, they actually blackmailed Microsoft into giving them money for every Zune sold!)
It's nice to see the big technology companies are starting to push for the right thing - even if it is because the hassle of keeping up the DRM and recent court battles have pushed them into this position.
This means we'll be able to roll out 0.9.0 with this support. Right now we're working to get it integrated into the build process, so that it will begin showing up in our new builds. I'm pretty excited myself, because I've had little chance to try out their work.
This refactoring support joins other recent work in RDT which allows us to do some occurence marking of variables, code completion and other exciting features (thanks Jason!). There's certainly a long way yet to go to get the tools polished - for instance we still have a hard time doing code completion (or much else) on a file which is being edited while the syntax is temporarily incorrect (the JRuby parser is great, but not so forgiving) - but we're constantly marching forward.
So, I was lucky enough to get a Roomba Discovery for Christmas from my parents. My wife and I both love her and we've decided she'd be named Rosie.
My father also grabbed a strange TV remote alarm, which is supposed to learn your remote's infrared signals for turning the TV on and off and then send that signal when the alarm goes off (thereby waking you up by turning your TV on). It also should be able to learn the Roomba power/clean command.
But it won't.
Or at least it says it's got it by flashing it's little red lights, and when the alarm goes off those wonderful little lights go off again - but no movement from Rosie. I can't get it to actually learn the TV remote control either, so I guess it's no fault of Rosie.
So, dear lazyweb, are there any other cheap solutions for setting Rosie up on a timed schedule to clean my house while I'm away? Or do I have to buy some accessories from iRobot (which will be more expensive)?
A while back I wrote an article describing some possible ways to implement a
Decorator pattern in Ruby.
I've stumbled across several mentions of
yet another idiom used so often in the Rails codebase that they've extracted
it into the latest ActiveSupport. That idiom is
alias_method_chain,
and it's a good example of a decorator implementation.
This idiom is a codified example of using the alias approach I briefly mentioned in the earlier article. In that
article we aliased the original implementation with anew name, and set up a new implementation of our method
(often delegating to the original) with the original's name. A quick example makes this clear:
class Windowdef draw# do some drawing here...end# some code...# creates a 'copy' of draw method, but gives it# the name/selector 'original_draw'alias:original_draw:drawdef drawdraw_vertical_scrollbaroriginal_drawendend
alias_method_chain
In Rails 1.2 (ActiveSupport specifically), the Rails core team found many instances of this pattern
and codified a new method on the class Module, alias_method_chain. This class-level method encapsulates this
pattern of wrapping existing methods with additional behavior.
Here's a specific example, showing how they would wrap rendering with layouts:
In this small code snippet, they are creating a small chain of methods to wrap the existing render behavior.
Now calls to render will be routed to render_with_a_layout and then on to the original render implementation
(which is now aliased to render_with_no_layout). So they coded up alias_method_chain which simply does
the wrapping for them (using naming conventions):
class Module# Encapsulates the common pattern of:## alias_method :foo_without_feature, :foo# alias_method :foo, :foo_with_feature## With this, you simply do:## alias_method_chain :foo, :feature## And both aliases are set up for you.def alias_method_chain(target,feature)alias_method"#{target}_without_#{feature}",targetalias_methodtarget,"#{target}_with_#{feature}"endend
Please note that if they were to replace their existing two calls to alias_method above, they would need to tweak the naming a little
(the methods would become render_without_layout and render_with_layout as opposed to
render_with_no_layout and render_with_a_layout respectively).
Since I talk about real estate with some regularity I thought I should share some personal experience around getting your credit report.
First things first, get your credit report when you are beginning to think about buying a home. If you have a low score you will need to address any inaccuracies or problems the report brings up or you won't get approved by a mortgage lender (or you will get charged a higher rate). In fact, you should probably get one annually anyways to avoid higher rates on credit cards and loans and to help avoid landlords from renting to you, etc.
Next, if you want a free credit report, use www.annualcreditreport.com. The federal government passed legislation allowing you to request a free report every 12 months and this is the site to do so. Those of you who try the others (like www.freecreditreport.com) beware - Read the fine print and you'll see that getting the report will sign you up for a subscription of some sorts that will charge you on a monthly basis until canceled. They typically say that if you cancel within 30 days you won't be charged. I'm not alleging that they're outright lying, but I canceled within 3 days and was charged for 4 months and was never able to recover the charges. Your mileage may vary, but why bother?
I occasionally write columns on real estate here and given the latest news I thought I should post an update.
CNN and other major outlets have all been reporting the news for some time - the housing market is stagnant and the bubble has burst.
They're right. The bubble has officially burst and those of you who got into the speculative game in Florida, California, Las Vegas or some of the other areas who saw incredible gains are now paying the price. I don't have much first-hand knowledge of those markets, but as I mentioned before they were well overpriced, they continue to be overpriced and I don't imagine that we'll see any appreciable gains (real gains, adjusted for inflation) in home prices in those markets in the coming quarter, year, and probably not in the next five years. Definitely nothing like those ridiculous 20%+ YOY gains of the past. Gains of that nature are unsustainable in the long term and we're seeing a natural correction in the market.
As for the secondary and tertiary markets, I'm predicting that as a result of the general malaise felt by the aftershocks of the major-market bubble-burst prices will remain at current rates or, in some markets, achieve single-digit gains. Investment in homebuilders and other real estate related holdings will be dropping as returns disappoint (no more flipping properties for a 100% profit!?) and this will ripple into some of these smaller markets holding down price growth.
While this is bad short term news for many owners who bought into the market in the past couple years, assuming you bought into the market for the right reasons (not to flip, the real estate equivalent of day trading), time frame (more than 5 years), and with the right financing (fixed rate mortgages that fit in your budget) you should feel comfortable holding onto your holdings. Those of you who hold ARMs may want to consider dropping properties and even forfeiting deposits on properties in construction which were intended to be sold for profit from appreciation.
Another easy to implement pattern in Ruby is the Observer pattern.
The Observer pattern is a publish/subscribe mechanism where an objects can register to be notified of state changes (or observe changes) on another observed object. This pattern may often become refactored into a more general event framework (where objects fire events off into queues to which there are listeners subscribed).
The basic implementation
Here's a look at a simple ruby implementation:
class Observabledef initialize@listeners=[]enddef register_listener(listener)@listeners<<listenerenddef unregister_listener(listener)@listeners.remove(listener)enddef runnotify_listeners("Hello!")endprotecteddef notify_listeners(event)@listeners.each{|l|l.notify(event)}endendclass Listenerdef initialize(observable)observable.register_listener(self)enddef notify(event)puts"Notified of '#{event}'"endendobservable=Observable.newlistener=Listener.new(observable)observable.run#=> Notified of 'Hello!'
The pattern itself in this form is pretty general. So general, in fact, that there is a module mixin of Observer inside the standard ruby library (observer.rb).
There's some good documentation in there, and it provides a simpler path to this implementation:
require"observer"class TVincludeObservabledef initialize(channel)@channel=channelenddef up@channel+=1changednotify_observers(@channel)endendclass ChannelWatcherdef initialize(tv)tv.add_observer(self)enddef update(channel)puts"Changed channel to #{channel}"endendtv=TV.new(160)watcher=ChannelWatcher.new(tv)tv.up#=> Changed channel to 161
Please be aware that the API is a little different from my initial example.
Moving towards events
Both of the above implementations rely on a generic observer pattern, but the Observer pattern can often evolve into a simple event mechanism. The difference is that instead of firing a generic event object via a generic notify method, the move towards events uses unique method names, and filters events to notify only those interested in the type of event occurring.
Let's see a TV example where we move towards a more specialized event firing version of the pattern:
require"observer"class TVdef initialize(channel)@channel=channel@listeners=[]enddef add_listener(listener)@listeners<<listenerenddef up@channel+=1@listeners.each{|l|l.channel_increased(@channel)}enddef down@channel-=1@listeners.each{|l|l.channel_decreased(@channel)}endendclass ChannelUpWatcherdef initialize(tv)tv.add_listener(self)enddef channel_increased(channel)puts"Changed channel to #{channel}"enddef channel_decreased# do nothing...endendtv=TV.new(160)watcher=ChannelUpWatcher.new(tv)tv.up#=> Changed channel to 161
In this instance we can fire off events for surfing the Tv upwards or downwards (in channels) separately, though we still register listeners into a generic pool, and listeners are expected to contain both event methods. Variations of this can be done to register listeners into sub-groups upon registration by calling unique methods names for each registration, or by passing in a Filter object that can be used to filter to the events the listener cares about. In filtering at registration we can avoid listeners having to implement every event firing method and minimize the number of events fired off.
Extending the pattern towards this event firing mechanism even further we'd likely move into using queues and firing events off to the queues themselves rather than directly to observers. Observers would then become subscribers to the queues.
Using blocks and procs
The Observer pattern as described above is the typical pattern followed in most languages without closures, lambdas or functors.
In Ruby we have the ability to throw around closures/blocks so we can take the pattern a little further.
Let's revisit our original implementation, but let's add the ability to register the callback function to be performed upon notification.
class Observabledef initialize@listeners=[]enddef register_listener(&blk)@listeners<<blkenddef unregister_listener(&blk)@listeners.remove(blk)enddef runnotify_listeners("Hello!")endprotecteddef notify_listeners(event)@listeners.each{|l|l.call(event)}endendclass Listenerdef initialize(observable)observable.register_listener{|event|"Notified of '#{event}'"}endendobservable=Observable.newlistener=Listener.new(observable)observable.run#=> Notified of 'Hello!'
This is the model illustrated in the Tk bindings for Ruby - you can see examples of usage in Programming Ruby's section on binding events in Tk. That section and their section on blocks as closures begin to broach the how closures capture the context in which they were defined - allowing for some very interesting and complex behavior in using blocks and procs as event or observer callbacks (allowing you to refer to objects available at the scope of the block definition, not when the callback/block execution occurs).
The Singleton pattern is the black sheep of the pattern family.
It was easy to grasp, developers everywhere applied it liberally, and an inevitable backlash came against its overuse.
I won't make any judgments or reccomendations on when to use it - but I will show you just how easy it is to apply in Ruby.
The literal translation of the pattern is to create a class level instance method and to hide the new method.
class Exampledef initialize# do something?enddef self.instancereturn@@instanceifdefined?@@instance@@instance=newendprivate_class_method:newendputsExample.instance.object_id#=> 21783380putsExample.instance.object_id#=> 21783380
This example gives you the basic idea, but it doesn't cover many cases you'd like to handle, like cloning or duping the singleton. It also doesn't hide the class level allocate method, which means a sneaky coder could still create another instance through some hacking.
Lastly, it's not thread safe.
Luckily, Ruby already provides a module for making classes singletons. It's in the standard library, inside 'singleton.rb'.
Here's how you use it:
This module will do the same thing as my example above but will also handle hiding allocate, overriding the clone and dup methods, and is thread safe. The library file itself contains a bunch of examples of its usage, and those interested should definitely read through it.
One thing to note about these implementations is that the instance method takes no arguments, so none are passed on to the object's constructor. This makes sense because the first time instance is called those will be the arguments used for this global instance. Setters are typically more appropriate for most singletons.
Since singletons are global in nature setters should be at the class level. As an extra bonus here's the implementation of the class level attr_ methods to generate the vanilla getter/setter methods (stolen from Rails).
class Class# :nodoc:def cattr_reader(*syms)syms.flatten.eachdo|sym|class_eval(<<-EOS,__FILE__,__LINE__)
unless defined? @@#{sym}
@@#{sym} = nil
end
def self.#{sym}
@@#{sym}
end
def #{sym}
@@#{sym}
end
EOSendenddef cattr_writer(*syms)syms.flatten.eachdo|sym|class_eval(<<-EOS,__FILE__,__LINE__)
unless defined? @@#{sym}
@@#{sym} = nil
end
def self.#{sym}=(obj)
@@#{sym} = obj
end
def #{sym}=(obj)
@@#{sym} = obj
end
EOSendenddef cattr_accessor(*syms)cattr_reader(*syms)cattr_writer(*syms)endend
Today's article is the twist on the Decorator pattern. The Decorator pattern wraps the original object in a new one which will add functionality to some of the methods and then delegate to the original object. The prototypical example is decorating a window object.
A Decorator Example
public interface Window {
public void draw();
}
In Java, we'd probably use a decorator to add scroll bars.
public Class VerticalScrollWindow implements Window {
private Window window;
public VerticalScrollWindow(Window window) {
this.window = window;
}
public void draw() {
drawScrollBar();
window.draw();
}
}
The basic concept is that we'll usually want to be adding some behavior around a particular method call to extend behavior, while retaining the same interface.
Ruby
In ruby, we have a number of options to achieve this pattern. First, let's define our original Window in Ruby code:
class Windowdef draw# do some drawing here...endend
Translating the pattern literally
Given ruby's duck-typing nature, we could easily create a VerticalScrollWindow that wraps the original Window when we create the original window object, and pass that around. In fact we could patch only the single method and add a method_missing implementation that always delegated to the original Window.
class VerticalScrollWindowdef initialize(window)@window=windowenddef drawdraw_vertical_scrollbarwindow.drawenddef method_missing(method,*args,&block)@window.send(method,*args,&block)endend
This approach could be evolved to a much higher level using method_missing tricks and dynamic modifications. One could create a generic Proxy class which took a target class and intercepted all method calls, executing pre- and post- method blocks for specific methods. I'll leave that as an exercise for the reader for now...
Using Alias
Another option we have is to "monkeypatch" the original class (or specific instances of it). The idea here is to rename the old implementation of the method, insert a new implementation and have that refer to the renamed original.
class Windowdef draw# do some drawing here...end# some code...alias:original_draw:drawdef drawdraw_vertical_scrollbaroriginal_drawendend
Building pre and post hooks
Our last option is to build pre and post method hooks into the original class definition. Obviously, this approach requires the original class' author to explicitly build in callback hooks. This approach can be found in Capistrano (you can add tasks which get executed before or after well known tasks), or in ActiveRecord (lifecycle type callbacks - i.e. before_save, after_destroy).
This option is a bit more advanced and differs in the approach taken. To learn how Capistrano does it, dive into capistrano/actor.rb, line 118. Each task is defined as a method which explicitly calls before and after methods if they exist.
For ActiveRecord, please refer to activerecord/callback.rb. ActiveRecord goes a little further by allowing class level methods to add pre- and post- code blocks to be executed which will be inherited down the class hierarchy. They also allow instance level methods to be defined for each hook which would not be inherited.
I've been working on an internal project that connects to a legacy Oracle database. The process of getting the driver and client set up was a bit annoying, but I'd done it before and I managed to get through it again. (For those of you braving it, be sure you don't include a trailing slash on your ORACLE_HOME environment variable).
The Oracle driver and client are like most Oracle products - unnecessarily complex. One of its requirements is that you set an ORACLE_HOME environment variable. I'd managed to do this and add it to my .bashrc file so that when I manually logged into the app server via SSH I could get the rails app up and running. The problems was that remotely deploying via Capistrano was causing errors - anything that loaded the rails framework, and therefore the Oracle driver, would die with a stack trace about an undefined method. Luckily in my past troubles with the driver, I knew that meant that it didn't have the ORACLE_HOME environment variable set.
In case anyone else is running into this (or I do again), here's a patch:
First, add the following to your deploy.rb recipe:
set :use_sudo, false
Next, modify your capistrano/actor.rb file to force all run commands through bash with BASH_ENV set:
Hello again! It's been two weeks since we last spoke, and I miss you already. As I mentioned then, I appreciate your efforts to market your vehicles in my area and your attempts at regional advertisements. Since that time you've introduced a new ad referring to I-95. While I'm no expert on geography, I'm quite sure that I-95 runs by New York City and just barely touches a corner of our state - the opposite corner from where you are advertising. Here, I've provided a helpful illustration:
I-95 is the red winding line. Rochester is located at the tip of the arrow.
Perhaps you are trying to save money by referring to a 1,927 mile long interstate highway that spans the entire east coast and running the ad in all those markets as "local". While this is ingenius, to reach Western New York you would likely want to reference I-90, or as we New Yorkers call it, the Thruway. It has the added bonus of stretching the entire continental US's northern states.
But those are really just semantics, after all you've discovered a way to make "regional" ads that span a huge swath of the country. Maybe you can subdivide the audience into similar niches beyond region by referencing very specific interests. Targetting such a niche would make the listener feel unique and passionate about your product. I suggest using in-jokes about Seinfeld, or maybe sharply dividing the audience and creating passionate responses by professing a love of puppies and babies.
I'm seeing a recurring theme in my feed reader today - multi-stage deployments with Capistrano.
It seems that those of us working in larger companies have all hit the same issue - we have some form of user acceptance, staging or other system which mirrors the production in configuration; and we want to use Capistrano to deploy to it as well as production. I know that my current company has a 5-stage process for pushing out releases (we're in financial services, and very paranoid. Whether they'd ever accept Capistrano is another issue).
This is an interesting variation on the Turing test, in which humans generate and grade tests that most humans can pass, but current computer programs cannot pass. Is there another variation in the future, in which computers generate and grade tests that computers can pass, but humans cannot pass?
I’m not sure of the applicability of such a test, but the idea is intriguing none the less. I would think that there are plenty of problems that would be too difficult to solve by a human, but they are based on the assumption that a time limit is given for the production of a solution. You could simply give a very difficult mathematical question with a subsecond solve time.
One possible example without a need for a time-limit: a picture with a randomly generated steganographic message embedded and a text field with no explanation - computers fill it with the embedded message, humans would likely try to ascertain the image’s contents as the answer. Sort of a reverse captcha. The assumption here is that the algorithm for generating the random message is truly random, or not able to be reverse-engineered and the next value guessed by a human (sort of like those random card shufflers in Vegas that aren’t supposed to be beatable).
In any case, the idea is thought provoking. Anyone else have examples?
I've been working on a website that uses tags internally. The acts_as_taggable plugin has been great, but it only takes care of the ActiveRecord portion of tagging. One of the pieces of functionality I needed was to create an autocompleter for users to enter a list of tags on a record. Below is a pure copy-paste dump of my implementation. I'm not claiming it's good code or the right way top do things, but for those looking to use an autocompleter for a text field holding tags might find it useful. The implementation is close to that used by delicious in the tags field on posting new bookmarks.
I appreciate your efforts to market your vehicles in my area; and I also appreciate your effort in creating regional specific advertisements - it lends a nice local feel to them. Bravo! However, you may want to actually make sure that the region you're airing the commercials within actually makes sense.
There are other cities in New York state besides New York city. Upstate / Western New York is not referred to as the tri-state area. So, your slogan to tell use that we "try everything" and maybe that's why we're the "try-state" area is cute as buttons and puppy dogs - and horribly wrong. The area you're referring to is a 400 mile, 7-hour drive across nowheresville from us. Perhaps you could create one specific for our area: Since we are "Western" New York you may want to mention cowboys and indians. Or perhaps use the title "Finger Lakes region" and talk about rude gestures.