Posted over 2 years back at townx - tech
I've got a slightly unstable computer at the moment which I've been trying to diagnose. Still haven't worked out exactly what's wrong (it freezes randomly in both Windows and Linux), but I have found some useful testing tools on the way (for Ubuntu Intrepid Ibex unless otherwise stated).
Memory
Recent Ubuntu Linux distros include MemTest86+, a memory testing tool. You just select this option from the grub boot menu when your computer starts and it boots into a dedicated memory testing OS. The tests are fairly simple to get going, but taking hours, literally. You need to run them overnight.
Hard disks
The smartmontools package includes some testing tools for hard disks which have S.M.A.R.T. capability (most modern motherboards and hard disks support this). Once you've installed the package, you can use the smartctl command line tool to run diagnostics on your hard disks.
I used this tool like this:
$ sudo smartctl -t long /dev/sda
This starts the test, which will take a fair amount of time (mine took around 30 minutes for a 40Gb disk). Once it's finished, you can do:
$ sudo smartctl -H /dev/sda
to see the results. Mine looked like this:
smartctl version 5.37 [i686-pc-linux-gnu] Copyright (C) 2002-6 Bruce Allen
Home page is http://smartmontools.sourceforge.net/
=== START OF READ SMART DATA SECTION ===
SMART overall-health self-assessment test result: PASSED
CPU
A simple test to max out your CPU (and exercise your graphics card) is to run GLX gears:
$ glxgears -info
However, that doesn't really stress your system. For that, I used a tool called CPU Burn-in. This is ostensibly an overclockers tool, but what it does is attempt to push your CPU to maximum operating temperature so you can see whether it's stable. It's a binary download, so it's very easy to use, and has a Linux version. Unzip it, cd to the directory, and run:
./cpuburn-in 10
where 10 is the number of minutes you want to run the tests for. This one scared me a bit, as I watched the temperature of my CPU and system slowly climb. Read the caveats and warnings on the web site before running this tool.
Monitoring
While you're doing all this, you want to watch the system temperature etc. For this, you can use the xsensors tool. This is a simple apt-get on Ubuntu, but for some reason the default config. file is in the wrong place (it's called /etc/sensors3.conf but the app. is expecting /etc/sensors.conf). You can tell it where the config. file is using the -c switch, e.g.
./xsensors -c /etc/sensors3.conf
This displays a graphical readout of various system temperatures, fan speeds etc..
You can also watch various aspects of system usage by adding the hardware monitor applet to your panel (right-click on the panel and select Hardware Monitor). This lets you watch how much your CPU, memory, disks etc. are being utilised.
Posted over 2 years back at Sterling Rose Design Blog
I get asked this question a lot: How do you write a proposal for a freelance contract development job?
First, it’s important to understand that freelancing is a different animal from working for a larger development firm (or, as I lovingly think of them, a Dev-in-a-Box). We have some considerations as independents that they don’t, and vice versa, so I don’t presume to know how best to bid jobs if you’re the Thoughtbots or Hashrockets of the world.
But if you’re an independent developer, then these tips may be useful for you.
1) Never, ever, ever bid flat-rate. Nobody is that good at estimating the time it takes to develop an application, and you will almost surely be wildly over or wildly under the amount of hours it takes you. Also, the client who knows you aren’t going over $X will tack on as many new features to the spec as you will allow them to, since they know it can’t cost them any more. Someone always gets screwed in fixed-bid development, and it’s usually the developer.
2) Make it clear to your client that your estimate is just that – you may be under or over your amount. The client should be able to have a number in their head, but also they need to understand that it might not be the number. Mine say, “I have given what I believe to be worst-case scenarios at each stage, though it should be understood that these are only estimates – actual completion times could be less or more than what is shown for any phase, as we understand the requirements in more detail.” Which leads us into…
3) Phases. I like to break a job out into phases, with upper and lower time estimates for each phase. Not only does this help you think more meaningfully about what a project entails, it lets the client know where all that money is going. If they are keeping their overall budget close to the vest, then they can look at the phases and get a guesstimate of how far down the phase list their budget will stretch, and whether that’s a reasonable investment for them.
4) Don’t undercut your rate. Almost every developer I have talked to about this has a rate range, rather than an absolute rate. The hourly figure you quote for any particular job depends on the complexity of the work, the amount of code you will be able to reuse from other projects vs. the amount you will have to write from scratch, the amount of new tools/skills you will have to learn to deliver the project, the number of referrals you think you might get from the client, how difficult the client is to work with, what the market is like at the time, and how badly you need the work. In the last two months, I have bid projects at the absolute low end of my rate, and at the (current) absolute high end of my rate. Some I’ve landed, and some I haven’t, but I feel good about the rates I’ve given out in every case.
5) Be sure the client understands that any training (them of you or you of them), client phone calls, and the like are billable hours. Add it into the estimate (the amount depends on how long the project will take overall, but usually at least an hour a week).
6) This is one area in which I know some developers will disagree with me, as we’ve had discussions of it on IRC. I do not bill the client for the time it takes me to learn new technologies or techniques. I recently needed to learn a little Prototype to deliver some nifty interactive goodness on a project. I had to read some of the Prototype API, watch a couple of Railscasts, and read several blog entries. None of that time is billable. I’m perfectly willing to bill a client for the time it takes to figure out how to apply something to their particular needs, but billing them for me learning something that is reusable feels like robbery.
7) Put an “expires by” date on your proposal. Your rates should naturally increase over time as your reputation grows and your skillset improves. You don’t want to have to explain to a client a year or two after you submit an estimate to them why you can no longer honor the rate you quoted. I usually give the estimate a lifespan of anything from one to three months.
8) Spell out whether hosting is included or not. If you anticipate any other, outside costs (logo design, image manipulation, whatever) be sure to explain that in your estimate.
9) Submit estimates promptly after meeting with (virtually or in person) the client. You want the information fresh in your mind, and you want the client to know that you deliver promptly. I usually have a written estimate in the customer’s hand within 24 hours.
10) And now, the hardest part – how much time to attach to each phase? I do not have any magic answers to this. To be honest, I’m not that great at estimating time. I wrote a proposal once that a particular phase would take me 2 hours. It took 15 minutes. In that same proposal, I estimated something would take 30 hours. I’m at hour 42 as I write this, and it’s still not done. The general rule of thumb is to take the most you think it could take, and multiply it by 2.5. Even then, the sad truth is that it’s something of a crap shoot, especially when you get into really complex applications. That is why you never, ever bid fixed-bid. When you get to the point where you’re approaching the upper limit of what you’ve estimated and you’re nowhere close to done, then you have to make a hard choice: Do you tell the client you’re going to go wildly over-budget and hope they just understand? Do you suck up the extra hours and consider it an investment in your career? Split the difference? That decision depends on your particular client and circumstances, and might be best left for a different blog entry.
Posted over 2 years back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home
<object height="344" width="425"><param></param><param></param><param></param><embed src="http://www.youtube.com/v/PPkJCZg1T14&hl=en&fs=1&rel=0" height="344" width="425"></embed></object>
Who doesn’t love cars crashing into other cars? And freshly generated documentation? Well, now you can get both. Or maybe just documentation. We’ve moved our open source projects’ documentation onto RDoc.info, which uses YARD and some GitHub post-receive hooks to make sure it’s always up to date. Update your bookmarks, delicious links, cheat sheets, wikis, what have you:
Posted over 2 years back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home
<object height="344" width="425"><param></param><param></param><param></param><embed src="http://www.youtube.com/v/PPkJCZg1T14&hl=en&fs=1&rel=0" height="344" width="425"></embed></object>
Who doesn’t love cars crashing into other cars? And freshly generated documentation? Well, now you can get both. Or maybe just documentation. We’ve moved our open source projects’ documentation onto RDoc.info, which uses YARD and some GitHub post-receive hooks to make sure it’s always up to date. Update your bookmarks, delicious links, cheat sheets, wikis, what have you:
Posted over 2 years back at Rail Spikes
I’ve recently been trying to find a good server automation tool that meets my needs. I looked at Chef and Puppet.
They are both awesome for what they do, but what I don’t like is all the infrastructure I have to maintain to run Chef or Puppet. You need a server to host your server configuration on. But I only have one server![1] Chef does have a solo version which can download configuration from a web server and run it. That’s cool, but I don’t want to have a web server just for putting server configuration on.
When the time commitment to set up one of these tools up greatly exceeds how long it is for me to bring up a new slice and run through the standard Apache/DB/Passenger stack, I lose interest. In the end, these are great tools for managing a cluster of machines and bringing up a new app in the cluster quickly—and keeping it up to date automatically. If you have big infrastructure needs, they make sense. If you just want to set up a single slice…ugh.
After reading a bit about how Puppet and Chef work, what I really wanted was the ability to push server provisioning recipes. I want to maintain the server config in my repository and then provision a new server with a command I run on my machine. Sort of like deprec, but understandable.
Fortunately, I found Sprinkle and passenger-stack.
Sprinkle lets me quickly define which packages I want installed and push it out to a server to run (via Capistrano, Vlad, or Net::SSH). Sprinkle makes it easy to install software using apt, gem, or source. And unlike a simple shell script, Sprinkle tests whether or not the software is installed before running, and has a concept of dependencies.
Passenger-stack removes the pain of writing my own rules for what to install. It comes with the standard stuff you’d need, and you can customize it from there.
Here’s how you install all the software you need for a fresh server, after downloading passenger-stack:
sprinkle -c -s config/install.rb
The best part is that you can run that command again, and it won’t do anything. So you can add new software to your stack, then run it against your server, and only the new software will get installed.
This gives you a great way to manage natively compiled gems and ensure that if you ever need to spin up a staging server or a demo server, everything you need gets installed.
Check out this screencast by Ben Schwartz, author of passenger-stack.
<object height="360" width="640"><param /><param /><param /><embed src="http://vimeo.com/moogaloop.swf?clip_id=2888665&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=00ADEF&fullscreen=1" height="360" width="640"></embed></object>
Passenger-stack demo from Ben Schwarz on Vimeo.
It’s not a smart as Chef and Puppet. It’s not transactional and servers don’t check for new software to install automatically. But it sure is easy. That’s why I call Sprinkle “the provisioning tool for people who don’t have huge server clusters.”
1 Basically. I have many servers with many different applications on them. And I have a few servers that have multiple environments, but the same software. That’s my big driver for wanting a provisioning tool.
Posted over 2 years back at Rail Spikes
I’ve recently been trying to find a good server automation tool that meets my needs. I looked at Chef and Puppet.
They are both awesome for what they do, but what I don’t like is all the infrastructure I have to maintain to run Chef or Puppet. You need a server to host your server configuration on. But I only have one server![1] Chef does have a solo version which can download configuration from a web server and run it. That’s cool, but I don’t want to have a web server just for putting server configuration on.
When the time commitment to set up one of these tools up greatly exceeds how long it is for me to bring up a new slice and run through the standard Apache/DB/Passenger stack, I lose interest. In the end, these are great tools for managing a cluster of machines and bringing up a new app in the cluster quickly—and keeping it up to date automatically. If you have big infrastructure needs, they make sense. If you just want to set up a single slice…ugh.
After reading a bit about how Puppet and Chef work, what I really wanted was the ability to push server provisioning recipes. I want to maintain the server config in my repository and then provision a new server with a command I run on my machine. Sort of like deprec, but understandable.
Fortunately, I found Sprinkle and passenger-stack.
Sprinkle lets me quickly define which packages I want installed and push it out to a server to run (via Capistrano, Vlad, or Net::SSH). Sprinkle makes it easy to install software using apt, gem, or source. And unlike a simple shell script, Sprinkle tests whether or not the software is installed before running, and has a concept of dependencies.
Passenger-stack removes the pain of writing my own rules for what to install. It comes with the standard stuff you’d need, and you can customize it from there.
Here’s how you install all the software you need for a fresh server, after downloading passenger-stack:
sprinkle -c -s config/install.rb
The best part is that you can run that command again, and it won’t do anything. So you can add new software to your stack, then run it against your server, and only the new software will get installed.
This gives you a great way to manage natively compiled gems and ensure that if you ever need to spin up a staging server or a demo server, everything you need gets installed.
Check out this screencast by Ben Schwartz, author of passenger-stack.
<object height="360" width="640"><param /><param /><param /><embed src="http://vimeo.com/moogaloop.swf?clip_id=2888665&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=00ADEF&fullscreen=1" height="360" width="640"></embed></object>
Passenger-stack demo from Ben Schwarz on Vimeo.
It’s not a smart as Chef and Puppet. It’s not transactional and servers don’t check for new software to install automatically. But it sure is easy. That’s why I call Sprinkle “the provisioning tool for people who don’t have huge server clusters.”
1 Basically. I have many servers with many different applications on them. And I have a few servers that have multiple environments, but the same software. That’s my big driver for wanting a provisioning tool.
Posted over 2 years back at has_many :through - home
We're finally getting all our after-conference activities completed. The most exciting thing is that we just got our conference media online. We have video and audio recordings of the Golden Gate Ruby Conference technical sessions! Pivotal Labs sponsored the recordings, and is hosting them at pivotallabs.com/gogaruco - you can watch them there or download the files to watch later, or get them from the iTunes podcasts.
We also are trying something new (for Ruby confs, at least). We have put together a 42 page PDF zine, the Golden Gate Ruby Wrap, in order to document the conference, the speakers, the sessions, and the attendees. There are a lot of photos of the event, speaker bios, talk write-ups, and even interviews with attendees. It's the official record of the conference (as official as we get, anyway), and it's free.
Just because people have been asking, I'll say that Matt Aimonetti's talk on CouchDB is not included in the talk videos. Matt didn't want to offend anyone else, so he asked the talk recording not be released. Please don't ask for a copy privately, as I can't help you out. However, there is a great write-up of Matt's talk in the Wrap.
I'd also encourage you to check out the gogaruco blog posts at Pivotal Labs - there are articles for every session at the conference. Sarah Allen also blogged many of the sessions at her site. Know of any other good posts about sessions? Let us know in the comments.
And if you want to see how things looked, there are a lot of good photos up on flickr.
Posted over 2 years back at has_many :through - home
We're finally getting all our after-conference activities completed. The most exciting thing is that we just got our conference media online. We have video and audio recordings of the Golden Gate Ruby Conference technical sessions! Pivotal Labs sponsored the recordings, and is hosting them at pivotallabs.com/gogaruco - you can watch them there or download the files to watch later, or get them from the iTunes podcasts.
We also are trying something new (for Ruby confs, at least). We have put together a 42 page PDF zine, the Golden Gate Ruby Wrap, in order to document the conference, the speakers, the sessions, and the attendees. There are a lot of photos of the event, speaker bios, talk write-ups, and even interviews with attendees. It's the official record of the conference (as official as we get, anyway), and it's free.
Just because people have been asking, I'll say that Matt Aimonetti's talk on CouchDB is not included in the talk videos. Matt didn't want to offend anyone else, so he asked the talk recording not be released. Please don't ask for a copy privately, as I can't help you out. However, there is a great write-up of Matt's talk in the Wrap.
I'd also encourage you to check out the gogaruco blog posts at Pivotal Labs - there are articles for every session at the conference. Sarah Allen also blogged many of the sessions at her site. Know of any other good posts about sessions? Let us know in the comments.
And if you want to see how things looked, there are a lot of good photos up on flickr.
Posted over 2 years back at WyeWorks Blog - Home
Delegation is a feature Rails introduced in it’s 2.2 version, and in my opinion are quite useful and somehow something we don’t see too much around.
The concept of delegation is to take some methods and send them off to another object to be processed.
Let me explain this with a brief example:
Suppose you have a User class for anyone registered on your site, and a Customer class for those who have actually placed orders:
class User << ActiveRecord::Base
belongs_to :customer
end
class Customer << ActiveRecord::Base
has_one :user
end
As for now, if you are in a Customer instance, you can get their User information doing @customer.user.name, or @customer.user.email.
Delegation allows you to simplify this:
class User << ActiveRecord::Base
belongs_to :customer
end
class Customer << ActiveRecord::Base
has_one :user
delegate :name, :name=, :email, :email=, :to => :user
end
Now you can refer to @customer.name and @customer.email to retrieve and set values for those attributes directly. Pretty nice, huh?
We are now working on some code to make possible to inherit behaviour, along with polymorphic associations, so when you create a Cutomer, the User gets created as well with the data you provided when creating the customer, and so on.
So keep posted, for there will be more to come…
Posted over 2 years back at Katz Got Your Tongue?
I spent the past few days at JavaOne, where I gave a well-received talk on Ruby, and got to attend a number of sessions on both Ruby and other related technologies.
Out of curiosity, I went to a session on Groovy, a language that has a syntax that is derived directly from Java, but with semantics that are fairly close to Ruby’s. Groovy is missing a number of features that Ruby has, and is more clunky in a number of cases.
For instance, while Ruby has pure open classes, Groovy allows you to open or reopen the metaclass of a class and insert new methods. Groovy 1.6 (released in February) added the ability to insert a number of methods to a metaclass at once.
But what I want to discuss here is another distinction. Unlike Ruby, Groovy does not allow executable code anywhere. Instead Groovy classes are compiled, so runtime code execution inside of class bodies can not work. This means that a large number of the features that make Rails stand out, like declarative callbacks and validations, various forms of accessors, runtime method generation based on introspecting the database, and other per-class mutable structures cannot be implemented nearly as elegantly in Groovy.
In case you’re not familiar, Ruby doesn’t need annotations, because class bodies in Ruby are simply executable code, with a self that is the class that is being defined.
Let’s take a simple example. In Ruby, accessors are defined as followed:
class Car
attr_accessor :model, :make
end
In Groovy, accessors are defined as:
At first glance, they seem pretty similar. In both cases, getters and setters are added, and new fields (in the respective languages) exist. The difference is that while Groovy needed to add new syntax to support this, Ruby’s version can be implemented in Ruby itself:
class Class
def attr_accessor(*names)
names.each do |name|
class_eval "def #{name}() @#{name} end"
class_eval "def #{name}=(val) @#{name} = val end"
end
end
end
Rubinius, a complete implementation of Ruby in Ruby, implements attr_accessor as:
class Class
def attr_reader(name)
meth = Rubinius::AccessVariable.get_ivar name
@method_table[name] = meth
return nil
end
def attr_writer(name)
meth = Rubinius::AccessVariable.set_ivar name
@method_table["#{name}=".to_sym] = meth
return nil
end
def attr_accessor(name)
attr_reader(name)
attr_writer(name)
return true
end
end
Here, Rubinius exposes the method table to Ruby, and we store a method representing the instance variable directly into the method table. Obviously, this requires more Ruby infrastructure, but it shows how powerful “everything is executable code” can be.
In an effort to support Ruby’s declarative style, Groovy has added what they call “AST Transformations”, which allows a declarative rule plus some code to be converted, at compile time, into different code to be passed into the compiler.
To make this immediately useful, they shipped a bunch of these annotations with Groovy 1.6, so we can take a look at how this is supposed to work. One example is their “Lazy” annotation, which allows the creation of an accessor that is initialized to something slow, so you want to defer initializing the accessor until it is actually accessed. It works like this (from the Groovy documentation):
class Person {
@Lazy pets = ['Cat', 'Dog', 'Bird']
}
Assuming that creating that Array was slow, this would defer loading the Array until pets was accessed. Pretty nice. Unfortunately, implementing this nice abstraction is a non-trivial operation:
package org.codehaus.groovy.transform;
import org.codehaus.groovy.ast.*;
import org.codehaus.groovy.ast.expr.*;
import org.codehaus.groovy.ast.stmt.*;
import org.codehaus.groovy.control.CompilePhase;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.runtime.MetaClassHelper;
import org.codehaus.groovy.syntax.Token;
import org.objectweb.asm.Opcodes;
/**
* Handles generation of code for the @Lazy annotation
*
* @author Alex Tkachman
*/
@GroovyASTTransformation(phase= CompilePhase.CANONICALIZATION)
public class LazyASTTransformation implements ASTTransformation, Opcodes {
public void visit(ASTNode[] nodes, SourceUnit source) {
if (!(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) {
throw new RuntimeException("Internal error: wrong types: $node.class / $parent.class");
}
AnnotatedNode parent = (AnnotatedNode) nodes[1];
AnnotationNode node = (AnnotationNode) nodes[0];
if (parent instanceof FieldNode) {
FieldNode fieldNode = (FieldNode) parent;
final Expression init = getInitExpr(fieldNode);
fieldNode.rename("$" + fieldNode.getName());
fieldNode.setModifiers(ACC_PRIVATE | (fieldNode.getModifiers() & (~(ACC_PUBLIC|ACC_PROTECTED))));
create(fieldNode, init);
}
}
private void create(FieldNode fieldNode, final Expression initExpr) {
BlockStatement body = new BlockStatement();
final FieldExpression fieldExpr = new FieldExpression(fieldNode);
if ((fieldNode.getModifiers() & ACC_VOLATILE) == 0) {
body.addStatement(new IfStatement(
new BooleanExpression(new BinaryExpression(fieldExpr, Token.newSymbol("!=",-1,-1), ConstantExpression.NULL)),
new ExpressionStatement(fieldExpr),
new ExpressionStatement(new BinaryExpression(fieldExpr, Token.newSymbol("=",-1,-1), initExpr))
));
}
else {
body.addStatement(new IfStatement(
new BooleanExpression(new BinaryExpression(fieldExpr, Token.newSymbol("!=",-1,-1), ConstantExpression.NULL)),
new ReturnStatement(fieldExpr),
new SynchronizedStatement(
VariableExpression.THIS_EXPRESSION,
new IfStatement(
new BooleanExpression(new BinaryExpression(fieldExpr, Token.newSymbol("!=",-1,-1), ConstantExpression.NULL)),
new ReturnStatement(fieldExpr),
new ReturnStatement(new BinaryExpression(fieldExpr,Token.newSymbol("=",-1,-1), initExpr))
)
)
));
}
final String name = "get" + MetaClassHelper.capitalize(fieldNode.getName().substring(1));
fieldNode.getDeclaringClass().addMethod(name, ACC_PUBLIC, fieldNode.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, body);
}
private Expression getInitExpr(FieldNode fieldNode) {
Expression initExpr = fieldNode.getInitialValueExpression();
fieldNode.setInitialValueExpression(null);
if (initExpr == null)
initExpr = new ConstructorCallExpression(fieldNode.getType(), new ArgumentListExpression());
return initExpr;
}
}
Pretty ugly. If you look closely at the code, you’ll see that the amount of code necessary to express even simple concepts is huge, because you’re manipulating an actual AST.
A similar feature in Ruby might look like:
class Person
lazy(:pets) { ["Cat", "Dog", "Bird"] }
end
And the implementation:
class Class
def lazy(name, &block)
define_method("_lazy_#{name}", &block)
class_eval "def #{name}() @#{name} ||= _lazy_#{name} end"
end
end
Because the lazy method is just a method being run on class at runtime, we can evaluate code live into the context. First, we define a method on the object called _lazy_pets. Next, we define a method called pets that memoizes the results of calling that method into an instance variable. And that’s it.
A slightly slower solution in Ruby that doesn’t require eval is:
class Class
def lazy(name)
ivar = "@#{name}"
define_method(name) do
instance_variable_get(ivar) || instance_variable_set(ivar, yield)
end
end
end
In this case, since we’re defining the method in a block, we still have access to the block that was passed in to the original lazy method, so we can yield to it inside the new method. Pretty cool, no?
Because all code is executable in Ruby, it’s easy to abstract away repetitive code in around the same number of lines as it took to write the code in the first place. With these simple examples, it would be possible to implement a simpler way to express these transforms. But as these sorts of things are expected to compose well with each other, the flexibility of executable, runtime code starts to really add up, in the same way that languages that are dynamic at runtime can be more flexible and powerful than languages that try to precompute everything at compile time.
<script type="text/javascript">
addthis_url = 'http%3A%2F%2Fyehudakatz.com%2F2009%2F06%2F04%2Fthe-importance-of-executable-class-bodies%2F';
addthis_title = 'The+Importance+of+Executable+Class+Bodies';
addthis_pub = '';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12"></script>
Posted over 2 years back at Katz Got Your Tongue?
I spent the past few days at JavaOne, where I gave a well-received talk on Ruby, and got to attend a number of sessions on both Ruby and other related technologies.
Out of curiosity, I went to a session on Groovy, a language that has a syntax that is derived directly from Java, but with semantics that are fairly close to Ruby’s. Groovy is missing a number of features that Ruby has, and is more clunky in a number of cases.
For instance, while Ruby has pure open classes, Groovy allows you to open or reopen the metaclass of a class and insert new methods. Groovy 1.6 (released in February) added the ability to insert a number of methods to a metaclass at once.
But what I want to discuss here is another distinction. Unlike Ruby, Groovy does not allow executable code anywhere. Instead Groovy classes are compiled, so runtime code execution inside of class bodies can not work. This means that a large number of the features that make Rails stand out, like declarative callbacks and validations, various forms of accessors, runtime method generation based on introspecting the database, and other per-class mutable structures cannot be implemented nearly as elegantly in Groovy.
In case you’re not familiar, Ruby doesn’t need annotations, because class bodies in Ruby are simply executable code, with a self that is the class that is being defined.
Let’s take a simple example. In Ruby, accessors are defined as followed:
class Car
attr_accessor :model, :make
end
In Groovy, accessors are defined as:
At first glance, they seem pretty similar. In both cases, getters and setters are added, and new fields (in the respective languages) exist. The difference is that while Groovy needed to add new syntax to support this, Ruby’s version can be implemented in Ruby itself:
class Class
def attr_accessor(*names)
names.each do |name|
class_eval "def #{name}() @#{name} end"
class_eval "def #{name}=(val) @#{name} = val end"
end
end
end
Rubinius, a complete implementation of Ruby in Ruby, implements attr_accessor as:
class Class
def attr_reader(name)
meth = Rubinius::AccessVariable.get_ivar name
@method_table[name] = meth
return nil
end
def attr_writer(name)
meth = Rubinius::AccessVariable.set_ivar name
@method_table["#{name}=".to_sym] = meth
return nil
end
def attr_accessor(name)
attr_reader(name)
attr_writer(name)
return true
end
end
Here, Rubinius exposes the method table to Ruby, and we store a method representing the instance variable directly into the method table. Obviously, this requires more Ruby infrastructure, but it shows how powerful “everything is executable code” can be.
In an effort to support Ruby’s declarative style, Groovy has added what they call “AST Transformations”, which allows a declarative rule plus some code to be converted, at compile time, into different code to be passed into the compiler.
To make this immediately useful, they shipped a bunch of these annotations with Groovy 1.6, so we can take a look at how this is supposed to work. One example is their “Lazy” annotation, which allows the creation of an accessor that is initialized to something slow, so you want to defer initializing the accessor until it is actually accessed. It works like this (from the Groovy documentation):
class Person {
@Lazy pets = ['Cat', 'Dog', 'Bird']
}
Assuming that creating that Array was slow, this would defer loading the Array until pets was accessed. Pretty nice. Unfortunately, implementing this nice abstraction is a non-trivial operation:
package org.codehaus.groovy.transform;
import org.codehaus.groovy.ast.*;
import org.codehaus.groovy.ast.expr.*;
import org.codehaus.groovy.ast.stmt.*;
import org.codehaus.groovy.control.CompilePhase;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.runtime.MetaClassHelper;
import org.codehaus.groovy.syntax.Token;
import org.objectweb.asm.Opcodes;
/**
* Handles generation of code for the @Lazy annotation
*
* @author Alex Tkachman
*/
@GroovyASTTransformation(phase= CompilePhase.CANONICALIZATION)
public class LazyASTTransformation implements ASTTransformation, Opcodes {
public void visit(ASTNode[] nodes, SourceUnit source) {
if (!(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) {
throw new RuntimeException("Internal error: wrong types: $node.class / $parent.class");
}
AnnotatedNode parent = (AnnotatedNode) nodes[1];
AnnotationNode node = (AnnotationNode) nodes[0];
if (parent instanceof FieldNode) {
FieldNode fieldNode = (FieldNode) parent;
final Expression init = getInitExpr(fieldNode);
fieldNode.rename("$" + fieldNode.getName());
fieldNode.setModifiers(ACC_PRIVATE | (fieldNode.getModifiers() & (~(ACC_PUBLIC|ACC_PROTECTED))));
create(fieldNode, init);
}
}
private void create(FieldNode fieldNode, final Expression initExpr) {
BlockStatement body = new BlockStatement();
final FieldExpression fieldExpr = new FieldExpression(fieldNode);
if ((fieldNode.getModifiers() & ACC_VOLATILE) == 0) {
body.addStatement(new IfStatement(
new BooleanExpression(new BinaryExpression(fieldExpr, Token.newSymbol("!=",-1,-1), ConstantExpression.NULL)),
new ExpressionStatement(fieldExpr),
new ExpressionStatement(new BinaryExpression(fieldExpr, Token.newSymbol("=",-1,-1), initExpr))
));
}
else {
body.addStatement(new IfStatement(
new BooleanExpression(new BinaryExpression(fieldExpr, Token.newSymbol("!=",-1,-1), ConstantExpression.NULL)),
new ReturnStatement(fieldExpr),
new SynchronizedStatement(
VariableExpression.THIS_EXPRESSION,
new IfStatement(
new BooleanExpression(new BinaryExpression(fieldExpr, Token.newSymbol("!=",-1,-1), ConstantExpression.NULL)),
new ReturnStatement(fieldExpr),
new ReturnStatement(new BinaryExpression(fieldExpr,Token.newSymbol("=",-1,-1), initExpr))
)
)
));
}
final String name = "get" + MetaClassHelper.capitalize(fieldNode.getName().substring(1));
fieldNode.getDeclaringClass().addMethod(name, ACC_PUBLIC, fieldNode.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, body);
}
private Expression getInitExpr(FieldNode fieldNode) {
Expression initExpr = fieldNode.getInitialValueExpression();
fieldNode.setInitialValueExpression(null);
if (initExpr == null)
initExpr = new ConstructorCallExpression(fieldNode.getType(), new ArgumentListExpression());
return initExpr;
}
}
Pretty ugly. If you look closely at the code, you’ll see that the amount of code necessary to express even simple concepts is huge, because you’re manipulating an actual AST.
A similar feature in Ruby might look like:
class Person
lazy(:pets) { ["Cat", "Dog", "Bird"] }
end
And the implementation:
class Class
def lazy(name, &block)
define_method("_lazy_#{name}", &block)
class_eval "def #{name}() @#{name} ||= _lazy_#{name} end"
end
end
Because the lazy method is just a method being run on class at runtime, we can evaluate code live into the context. First, we define a method on the object called _lazy_pets. Next, we define a method called pets that memoizes the results of calling that method into an instance variable. And that’s it.
A slightly slower solution in Ruby that doesn’t require eval is:
class Class
def lazy(name)
ivar = "@#{name}"
define_method(name) do
instance_variable_get(ivar) || instance_variable_set(ivar, yield)
end
end
end
In this case, since we’re defining the method in a block, we still have access to the block that was passed in to the original lazy method, so we can yield to it inside the new method. Pretty cool, no?
Because all code is executable in Ruby, it’s easy to abstract away repetitive code in around the same number of lines as it took to write the code in the first place. With these simple examples, it would be possible to implement a simpler way to express these transforms. But as these sorts of things are expected to compose well with each other, the flexibility of executable, runtime code starts to really add up, in the same way that languages that are dynamic at runtime can be more flexible and powerful than languages that try to precompute everything at compile time.
<script type="text/javascript">
addthis_url = 'http%3A%2F%2Fyehudakatz.com%2F2009%2F06%2F04%2Fthe-importance-of-executable-class-bodies%2F';
addthis_title = 'The+Importance+of+Executable+Class+Bodies';
addthis_pub = '';
</script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12"></script>
Posted over 2 years back at Jake Scruggs
I didn't. The box I was setting up CruiseControl.rb on today had some crazy early version of Ruby 1.8.6 and so test failures returned a code of '0'. Which meant the build would not fail until I upgraded to a more modern 1.8.6. Patch level 114 did the trick. Why are we using 1.8.6 on a new project? Well mostly so we can run along side an older Rails app using 1.8.6, but also because 1.8.7 doesn't really offer that much more to justify the headache of running two rubys on one box, and finnaly because I have no idea when 1.9x will be acceptable on all the gems I use.
Good times.
Posted over 2 years back at Pelargir
I released the initial version of my auto-session-timeout plugin for Rails at West End Ruby tonight.
Have you ever wanted to force your users off your app if they go idle for a certain period of time? Many online banking sites use this technique. If your app is used on any kind of public computer system, this type of functionality is essential for maintaining the privacy of your data.
After installing the plugin, a small snippet of JavaScript is placed on each page. The JS polls the server every minute to see if the session is still active. If the user has been idle for at least an hour, they are immediately redirected to a timeout page. The session will not timeout as long as the user keeps clicking around. The timeout and polling intervals are both configurable.
The plugin is dead simple to install and configure. To get started:
script/plugin install git://github.com/pelargir/auto-session-timeout.git
Then hit the README for step-by-step instructions.
Posted over 2 years back at Riding Rails - home
A security problem has been reported with the digest authentication code in Ruby on Rails. This vulnerability can allow users to bypass your password protection. This vulnerability has been publicly disclosed on several websites, users are advised to take the mitigating steps described below immediately.
The issue comes from the handling of the block passed to authenticate_or_request_with_http_digest. This block must return the user’s password in the clear, or a sha1 hash of the user’s password. Unfortunately the documentation was unclear on this and the examples cited would return nil if the user was not found. The correct behaviour if the user doesn’t exist is to return false.
If the return value was nil, rails proceeded to verify this value against the provided password. Because of this an attacker can provide an invalid username and no password and authentication will succeed.
Fixed Versions
We have altered the behaviour of the relevant code to make nil an authentication failure. This fix has been pushed to 2-3-stable and will be present in 2.3.3 due to be released in the next few days. All versions of edge rails after commit 1ad57cfe2fbda58439e4b7f84008ad23bc68e8b0 contain the fix.
Steps to Protect your application.
Users can protect themselves without upgrading by simply ensuring that their authentication blocks never return nil. To take an example from the documentation:
authenticate_or_request_with_http_digest(REALM) do |username|
USERS[username]
end
Should instead be something like:
authenticate_or_request_with_http_digest(REALM) do |username|
USERS[username] || false
end
Disclosure Notes
Due to communication difficulties and a mis-understanding between the reporter and the security team. This vulnerability has been publicly disclosed on several websites, users are advised to update their applications immediately. Steps are being taken to ensure that the security email is more reliable in the future. We regret the nature of this disclosure and will endeavor to ensure it doesn’t happen again in the future.
Posted over 2 years back at Riding Rails - home
A security problem has been reported with the digest authentication code in Ruby on Rails. This vulnerability can allow users to bypass your password protection. This vulnerability has been publicly disclosed on several websites, users are advised to take the mitigating steps described below immediately.
The issue comes from the handling of the block passed to authenticate_or_request_with_http_digest. This block must return the user’s password in the clear, or a sha1 hash of the user’s password. Unfortunately the documentation was unclear on this and the examples cited would return nil if the user was not found. The correct behaviour if the user doesn’t exist is to return false.
If the return value was nil, rails proceeded to verify this value against the provided password. Because of this an attacker can provide an invalid username and no password and authentication will succeed.
Fixed Versions
We have altered the behaviour of the relevant code to make nil an authentication failure. This fix has been pushed to 2-3-stable and will be present in 2.3.3 due to be released in the next few days. All versions of edge rails after commit 1ad57cfe2fbda58439e4b7f84008ad23bc68e8b0 contain the fix.
Steps to Protect your application.
Users can protect themselves without upgrading by simply ensuring that their authentication blocks never return nil. To take an example from the documentation:
authenticate_or_request_with_http_digest(REALM) do |username|
USERS[username]
end
Should instead be something like:
authenticate_or_request_with_http_digest(REALM) do |username|
USERS[username] || false
end
Disclosure Notes
Due to communication difficulties and a mis-understanding between the reporter and the security team. This vulnerability has been publicly disclosed on several websites, users are advised to update their applications immediately. Steps are being taken to ensure that the security email is more reliable in the future. We regret the nature of this disclosure and will endeavor to ensure it doesn’t happen again in the future.