Posted by Ken Brooks
Thu, 21 Jun 2007 20:07:00 GMT
I just got an old Mac G4 at work. Its old and slow but I’m so stinking happy I have a Mac at work.
The challenge: Make it productive for development.
My dirty little secret is that ever since installing my first linux distro years ago I have always hated compiling from source and installing it and not really knowing where all the artifacts end up. MacPorts to the rescue. Well… that is until you try to use it from behind a gauntlet of corporate proxies and firewalls.
Installed XCode. Check.
Installed MacPorts. Check
Update MacPorts definitions. (Insert screeching tire sound here).
The synchronizing is done via rsync. I believe that goes out over TCP 873. Yeah, like that is going to work.
The solution to this was to ssh into my webhost and checkout the info via subversion from MacPorts Subversion I then tar’d up that whole directory and threw it into the public area of my site. Over on the work mac create rsync.rsync.darwinports.orgdpupdatedports in /opt/local/var/db/dports/sources. I was able to download the tar, and untar it into the /opt/local/var/db/dports/sources/rsync.rsync.darwinports.orgdpupdatedports directory. That allowed macports to have a list of available ports and their dependencies. What I can’t do or haven’t bothered to figure out is how to update the macports version itself.
One last little thing before we can actually use it. We need to set an environment variable to allow macports to download the sources for our ports via our proxy. Edit your .profile or .bash_profile and add something like this:
http_proxy=http://myproxy.foo.bar:8080
Ok. So lets take inventory again.
Installed XCode. Check.
Installed MacPorts. Check
Update MacPorts definitions. Check.
Now feel free to install as normal. Ex: sudo port install ruby
Score one for the good guys.
Tags macports | no comments
Posted by Ken Brooks
Mon, 04 Jun 2007 21:18:00 GMT
Seems like a flurry of just bugfixes in edge rails lately. Mixed in today was a few additions.
The ActiveSupport::CoreExtensions::Date:Calculations had since, ago, beginning_of_day, end_of_day added.
Here are the tests so you can see some of the basic usage.
def test_since
assert_equal Time.local(2005,2,21,0,0,45), Date.new(2005,2,21).since(45)
end
def test_ago
assert_equal Time.local(2005,2,20,23,59,15), Date.new(2005,2,21).ago(45)
end
def test_beginning_of_day
assert_equal Time.local(2005,2,21,0,0,0), Date.new(2005,2,21).beginning_of_day
end
def test_end_of_day
assert_equal Time.local(2005,2,21,23,59,59), Date.new(2005,2,21).end_of_day
end
beginningof_day and endof_day make sense, they give you the beginning of the date you are operating on.
not so sure since and ago read correctly.
no comments
Posted by Ken Brooks
Thu, 24 May 2007 22:49:00 GMT
Tonight we’ll be starting down the road of those refactorings I promised and along the way we’ll introduce before and after.
First lets change that snowball itself to be a little more rubyish. In this case that means we will use symbols for the color.
class Snowball
def initialize
@color = :WHITE
end
def color?(color)
@color == color
end
end
Now we can modify the spec to do the same, passing in symbols for the color param.
require 'snowball'
describe Snowball do
before(:each) do
@snowball = Snowball.new
end
it 'Should NOT be yellow' do
@snowball.should_not be_color(:YELLOW)
end
it 'Should be white' do
@snowball.should be_color(:WHITE)
end
after(:each) do
@snowball = nil
end
end
You may have noticed that I did a little more than change the params to use symbols. There are now calls to before and after. If you are from an xUnit background you can think of these as setup and teardown. The before method runs prior to each example. before(:each) is the same as before because :each is the default param. The after method runs post each example. The same default of :each applies to after so after(:each) is identical.
Updated 2007-05-25
Aslak (Core developer of RSpec) was kind enough to point out something that I should have clarified:
Each example (instance) runs in a new instance anyway, and the instance variables are garbage collected.
The after(:each) here has no effect, and since it has no effect, doing it is confusing.
So in my example above the after method is not doing anything of value. That @snowball will be garbage collected without having to set it to nil. I just needed something to plop in there to show that I could be doing something.
End Update
There are also before(:all) and after(:all) that can be used. These are mostly discouraged as it may cause side-effects by having dependencies between examples. I came across a scenario at work (in Java-land) where this actually applies. I was using JUnit to write a func test that can be used as a test client of a deployed J2EE service. Before any calls can be made to the service we must initialize (authenticate). Once that initialization is done then we can call our service as many times from anywhere in our code using a static service wrapper. So in my test since there is only one setup method I was forced to write code similar to this:
private static boolean initialized;
public void setUp() {
if(!initialized) {
SubSystem.init();
initialized = true;
}
doSomeOtherSetupTask();
}
That saves the overhead of authenticating before each test. Unfortunately its ugly to me.
In rspec (altho I’m not sure I would use it to drive a client test like I did with JUnit) I suppose that code would look like this:
before(:all) do
sub_system.init
end
before(:each) do
do_some_other_setup_task
end
Now that is tasty goodness.
Tags bdd, rspec | 2 comments
Posted by Ken Brooks
Mon, 21 May 2007 00:30:00 GMT
RSpec has reached 1.0.0 (congrats to that team).
What is RSpec you ask? Straight from their site:
RSpec provides a Domain Specific Language with which you can express executable examples of the expected behaviour of a system.
A little better (and foreshadowing) explanation from their site:
…use RSpec to #describe Behaviour of a system using Examples of how #it should work.
Over the next few posts I’ll be going thru some of the features with small tutorials.
First up, the basics of installing RSpec and writing your first working spec. We’ll be going thru the specs of a snowball, now that summer is here and I spent the day sweating my snowballs off.
Get rspec
Create your first spec by creating snowball_spec.rb and adding the following to it.
That is telling us that we are going to describe the behavior and requirements for a successful implementation of a snowball.
Now is as good a time as any to fire up rspec and see what the magic is all about.
That just produced a ./snowball_spec.rb:1: uninitialized constant Snowball (NameError) message. Not exactly shaping up to be the greatest tool in the world is it? Take a closer look. Its actually telling you where to go next. Yep, create a Snowball class.
Don’t bother running spec again as you’ll be presented with the same error again. You need to tell the spec we depend on that snowball class. Modify your snowball_spec.rb to require the snowball.
require 'snowball'
describe Snowball do
end
Now if you run spec again you should see a little more positive results.
$ spec snowball_spec.rb
Finished in 7.0e-06 seconds
0 examples, 0 failures
That basically tells us that we are ready to really start describing the behavior of our snowball.
Lets add an example to our spec. We are going to make the statement that snowballs should not be yellow (unless you really don’t like the kid down the street).
require 'snowball'
describe Snowball do
it 'Should NOT be yellow' do
snowball = Snowball.new
snowball.should_not be_color("yellow")
end
end
That is pretty easy to read, and if you now run spec with the --format specdoc it finally hits you why RSpec is different and has its niche as compared to xUnit tests. We really are documenting the behaviour of a system and writing code to meet that required behavior. Now you can have your Keanu Reeves (Neo) ‘Whoah’ moment.
Ok, enough of that moment, lets finish up the snowball code to make this spec run again. And I’ll get back to creating that snowball instance in the middle of the test. If I don’t then please ping me and remind me.
class Snowball
def color?(color)
color == "white"
end
end
$ spec snowball_spec.rb --format specdoc
Snowball
- Should NOT be yellow
Finished in 0.006263 seconds
1 example, 0 failures
Without changing the Snowball class, we should now try and see if the positive test works also.
require 'snowball'
describe Snowball do
it 'Should NOT be yellow' do
snowball = Snowball.new
snowball.should_not be_color("yellow")
end
it 'Should be white' do
snowball = Snowball.new
snowball.should be_color("white")
end
end
Obviously (for the more experienced users) there are a few things that will need to be refactored out but in the interest of simplicity I left them that way to start.
That covers the basics of using RSpec.
We described the behavior of an object and then created some examples of its behavior.
Next section we’ll dig a little deeper and start doing those refactorings.
Tags bdd, rspec, ruby | no comments
Posted by Ken Brooks
Sun, 20 May 2007 23:02:00 GMT
Got MBP back, and if there is one thing I’ll say for Apple’s repair its that its been very speedy for me so far.
Dropped it off Tuesday night and began the obsessive compulsive routine of checking the repair status on the website. I assume it was shipped Wednesday morning. It was received in Texas on Thursday, fixed and shipped out again Thursday night. Had my MBP ready for pickup on Friday.
Still sucks to be without it for 4 days (2 separate times now) but at least it comes back all cleaned up (yes they wipe off the fingerprints from the screen, etc..).
Posted in macbook pro | no comments
Posted by Ken Brooks
Fri, 18 May 2007 23:10:00 GMT
My MacBook Pro is back from repairs… again.
Tomorrow I’ll pick it up. This is the second time that something is screwy with the power input and not being able to charge my battery.
It really is ashame that, as a person who has brought quite a bit of business to Apple in the past year, I would have to be going thru these issues. I’ve purchased a MBP for my wife, a MB for my parents, and two people at work now have them because of me.
Sad. Wonder if there is such a thing as a lemon law on MBPs?
Tags macbook, pro | no comments
Posted by Ken Brooks
Fri, 11 May 2007 21:42:00 GMT
Small change made to the Basic Auth functionality I posted about last time.
file: http_authentication.rb
rev: 6717
def authenticate(controller, &login_procedure)
if authorization(controller.request)
login_procedure.call(*user_name_and_password(controller.request))
else
false
end
end
and now a minor bit of defensive coding
rev: 6718
def authenticate(controller, &login_procedure)
if authorization(controller.request).blank?
false
else
login_procedure.call(*user_name_and_password(controller.request))
end
end
and the commit comment:
don’t assume the http authorization header will be nil, since some configurations will pass it through as an empty string
no comments
Posted by Ken Brooks
Tue, 08 May 2007 23:07:00 GMT
Basic authentication makes it into core ActionController.
The sample given in the commit comments makes it look pretty simple:
class PostsController < ApplicationController
USER_NAME, PASSWORD = "dhh", "secret"
before_filter :authenticate, :except => [ :index ]
def index
render :text => "Everyone can see me!"
end
def edit
render :text => "I'm only accessible if you know the password"
end
private
def authenticate
authenticate_or_request_with_http_basic do |user_name, password|
user_name == USER_NAME && password == PASSWORD
end
end
end
Basically what happens is that your block is passed in to the authenticate_or_request_with_http_basic
def authenticate_or_request_with_http_basic(realm = "Application", &login_procedure)
authenticate_with_http_basic(&login_procedure) || request_http_basic_authentication(realm)
end
The authenticate_with_http_basic passes the block down to the HttpAuthentication::Basic.authenticate method.
def authenticate_with_http_basic(&login_procedure)
HttpAuthentication::Basic.authenticate(self, &login_procedure)
end
The first part of that checks the request to see if its an auth.
def authorization(request)
request.env['HTTP_AUTHORIZATION'] ||
request.env['X-HTTP_AUTHORIZATION'] ||
request.env['X_HTTP_AUTHORIZATION']
end
If so it splits up the credentials and decodes them from the request then passes them as args to the original block you supplied:
login_procedure.call(*user_name_and_password(controller.request))
Posted in edge rails | Tags authentication, basic, edge, http, rails | no comments
Posted by Ken Brooks
Sat, 28 Apr 2007 10:26:00 GMT
From Wikipedia Bridge Pattern
The bridge pattern is a design pattern used in software engineering which is meant to “decouple an abstraction from its implementation so that the two can vary independently” (Gamma et. al.). The bridge uses encapsulation, aggregation, and can use inheritance to separate responsibilities into different classes.
When a class varies often, the features of object-oriented programming become very useful because changes to a program’s code can be made easily with minimal prior knowledge about the program. The bridge pattern is useful when not only the class itself varies often but also what the class does. The class itself can be thought of as the abstraction and what the class can do as the implementation.
Variant: The implementation can be decoupled even more by deferring the presence of the implementation to the point where the abstraction is utilized (as illustrated by the Visual Prolog example below).
Contents
What??
Lets simplify it and show some code examples. Keep in mind that the purpose of Design Patterns is to converse about programming concepts at a higher level not code templates to cut and paste.
I’ll also address the variant alluded to in the quote above as we will take our Bridge code and abstract the implementation out.
A simplified definition:
An abstraction (or refined abstraction) that has an implementation of some core functionality that may vary for instance.
A simplified example:
A brain (Abstract), implemented by Ken’s Brain is passed an implemenation of the ComputingEngine (interface). One of them is a normal implementation, one is my brain on drugs.
And now some simple/sample code.
The Brain
public abstract class Brain {
abstract public String computePower();
}
My brain
public class KensBrain extends Brain {
private ComputingEngine computingEngine;
public KensBrain(ComputingEngine computingEngine) {
this.computingEngine = computingEngine;
}
public String computePower() {
return "Total Power: " + computingEngine.compute();
}
}
The computing engine interface
public interface ComputingEngine {
public String compute();
}
Here is my normal brain function
public class NormalComputingEngineImpl implements ComputingEngine {
public String compute() {
return "100%";
}
}
Here is my brain on drugs
public class DruggedComputingEngineImpl implements ComputingEngine {
public String compute() {
return "4% (but funny)";
}
}
The driver
public class ComputeKensBrainPower {
public static void main(String args[]) {
Brain normalBrain = new KensBrain(new NormalComputingEngineImpl());
Brain druggedBrain = new KensBrain(new DruggedComputingEngineImpl());
System.out.println("Ken's normal brain power: " + normalBrain.computePower());
System.out.println("Ken's drugged brain power: " + druggedBrain.computePower());
}
}
no comments
Posted by Ken Brooks
Thu, 26 Apr 2007 22:44:00 GMT
Eventually I’ll work somewhere that I can use the new 5.0 language features. Either I’ll have to go to that place or if I wait around long enough we might be forced to upgrade to it.
Regardless, I wanted to see what some of those features are so I took a quick tour of them on Sun’s site.
The new/enhanced language features are as follows, with my comments of course.
- Generics - Just what Java needs, more type safety. :) Actually I like this feature but the syntax makes java less elegant to me.
- Enhanced for Loop - Java finally gets a for-each. I definitely like this one.
- Autoboxing/Unboxing - Guess it doesn’t hurt but I’m not jumping up and down about it.
- Typesafe Enums - Some neat concepts embedded into this one. Still not as useful to me as the QuasiEnum.
- Varargs - Not exciting to me at all.
- Static Import - Completely a waste of time to add these to the language. It makes code less readable.
- Metadata (Annotations) - I think this I’ll get the most use out of, but I’m sure (like everything else) it will be abused and taken too far before everyone realizes what the happy medium is.
Educate yourself and make your own opinions. Here is a good starting point.
no comments