| The Mysteries of Life: Computer Speakers |
[Oct. 25th, 2009|09:29 am] |
Can someone explain to me why it's always the right speaker that flakes out with computer speakers? And why turning it off and on can sometimes make it pop back on? |
|
|
| Test::Unit 2.x, now with TAP |
[Oct. 22nd, 2009|09:34 am] |
The test-unit gem now supports a TAP runner.
dberger@file-temp>ruby -Ilib test/test_file_temp.rb --runner tap
1..9
ok 1 - test_file_temp_auto_delete(TC_File_Temp)
ok 2 - test_file_temp_expected_errors(TC_File_Temp)
ok 3 - test_file_temp_name(TC_File_Temp)
ok 4 - test_file_temp_name_basic_functionality(TC_File_Temp)
ok 5 - test_file_temp_no_delete(TC_File_Temp)
ok 6 - test_file_temp_no_delete_with_template(TC_File_Temp)
ok 7 - test_file_temp_threaded(TC_File_Temp)
ok 8 - test_file_temp_tmpdir(TC_File_Temp)
ok 9 - test_file_temp_version(TC_File_Temp)
# Finished in 0.160204 seconds.
# 9 tests, 20 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
There is also Bacon. |
|
|
| Back to Rails |
[Oct. 20th, 2009|02:11 pm] |
So, I'm doing RoR work again, and I'm hitting those annoying little issues that bugged me the first time around.
Today, it's the fact that I have to setup separate validations to handle nils/blanks. IMO I should be able to do this:
validates_numericality_of :elevation, :allow_nil => false
Now, this works. It validates that elevation is a number and it doesn't allow nulls. The problem is that, in the case of a null, it still sets the error message to "not a number". That's not what I want. I want "can't be blank". And I *only* want that error message. To get that effect I have to setup two separate validations, and add a conditional to the second one.
validates_presence_of :elevation
validates_numericality_of :elevation,
:unless => Proc.new{ |site| site.elevation.blank? }
What a hassle.
Update: Anonymous user posted a better solution. See the comments. |
|
|
| More random thoughts on mixins, selector namespaces |
[Oct. 14th, 2009|01:05 pm] |
| [ | Tags | | | ruby | ] |
| [ | mood |
| | contemplative | ] |
Ovid's journal got me thinking about the multi-mixin problem again. That got me thinking about selector namespaces again, too.
Consider the current mixin behavior:
module Alpha
def hello
puts "Alpha"
end
end
module Beta
def hello
puts "Beta"
end
end
class Tango
include Alpha
include Beta
end
Tango.new.hello # => "Beta"
Possible solutions: * First method definition wins * Last method definition wins, raises a warning * No one wins, it's an error
And my new, crazy idea:
* First method definition wins, later methods are auto-namespaced
# Let's assume this syntax actually works
t = Tango.new
t.hello # => "Alpha" (wins, first definition)
t.hello:alpha # => "Alpha" (same, but explicit)
t.hello:beta # => "Beta" (calls Beta module's method)
Thoughts?
Update: As per the comments below, you could still have "last definition wins" behavior with the above syntax. Also, "alpha" and "beta" should probably be capitalized in the last example above. I dunno, though. I kinda like the lowercase notation in that context. |
|
|
| Face. Palm. |
[Sep. 24th, 2009|08:37 am] |
| [ | mood |
| | distressed | ] | Note to self: Dir['*/**'] and Dir['**/*'] do NOT do the same thing.
Gawd. |
|
|
| LJ Settings Change |
[Sep. 12th, 2009|12:07 pm] |
| [ | mood |
| | blank | ] | It seems that LJ still treats OpenID users as "anonymous", so I've changed my settings so that anonymous users can post, but those posts will be screened.
Happy posting! |
|
|
| Rake tasks to build gems |
[Sep. 11th, 2009|08:55 pm] |
| [ | mood |
| | chipper | ] | For gems where you may want to ship both a source bundle and a binary bundle, consider using Rake tasks instead of hard coding a gem spec directly in your Rake task. The first step is to remove this line from your .gemspec file:
Gem::Builder.new(spec).build
Why? Because we're going to eval the gemspec file and, in the case of the binary gem, modify the spec before we build it. Here are the Rake tasks I'm using that let me use a single gemspec and build either version without a lot of fuss:
desc 'Build a standard gem'
task :build_gem => :clean do
rm_rf('lib') if File.exists?('lib')
spec = eval(IO.read('foo.gemspec'))
Gem::Builder.new(spec).build
end
desc 'Build a binary gem'
task :build_binary_gem => [:build] do
file = 'ext/foo.' + CONFIG['DLEXT']
mkdir_p('lib')
mv(file, 'lib')
spec = eval(IO.read('foo.gemspec'))
spec.extensions = nil
spec.files = spec.files.reject{ |f| f.include?('ext/') }
spec.platform = Gem::Platform::CURRENT
Gem::Builder.new(spec).build
end
The standard gem is pretty straightforward. In the case of the binary gem, we need to build the binary, copy it to a 'lib' directory, remove the 'extensions' specification item, remove any 'ext' files (we don't want to ship build files do we? no), set the platform to the current platform and then, finally, build the gem.
Enjoy. |
|
|
| Be Nice |
[Sep. 10th, 2009|10:50 pm] |
| [ | mood |
| | calm | ] | I rarely agree with what Andy Lester has to say, but this is one of those times. He's talking about #perl, but he could be talking about any channel. Actually, he really could just be talking about acting like a decent human being online instead of a snot. |
|
|
| FFI Blues |
[Aug. 7th, 2009|11:04 am] |
Lately I've been experimenting with FFI, the wrapper around libffi that let's you write C code without ever leaving pure Ruby. I figured with JRuby already using it, and Rubinius and IronRuby on their way, it might be time to start porting some of my C extensions over.
Unfortunately, I've slammed into the cold hard fact that FFI just isn't the grand solution we all hoped it would be. The first problem is that libffi, the underlying source for C based implementations, isn't going to build without the gcc toolchain. That pretty much leaves everyone but Linux, FreeBSD and OS X in the dust, including two heavy hitters, MS Windows and Solaris (if you're using the Sun Studio compiler). Then there's the issue of JRuby's lack of support for certain parts of C, such as file descriptors, as my attempt to port file-temp demonstrated.
So now I'm in a dilemma. If I want to write cross-platform code that will work with JRuby and C based implementations, I'm relegated to keeping two (or more) separate source files, one for MRI and one for JRuby. It would more likely be 3, as I'll still need a separate source file for Windows, since the code is radically different from its *nix counterpart most of the time.
On top of that I've heard disturbing reports that there is little interest in supporting FFI on Windows, in which case we may as well declare it dead in the water. Whether you like it or not, Windows is a major player and its here to stay. If it's not going to work on Windows you may as well chuck it now and stick with C extensions. |
|
|
| Firefox Blues |
[Aug. 5th, 2009|06:56 pm] |
| [ | mood |
| | annoyed | ] | I've gone back to IE 8 on the Vista laptop for now. Seeing Firefox (3.5.2 btw) balloon to 800 mb with 2 tabs open, doing nothing in particular, but bringing my system to a crawl is simply unacceptable. |
|
|
| Hash#fetch |
[Aug. 5th, 2009|05:01 pm] |
I generally eschew Array#fetch. It's worthless in my opinion. But what about Hash#fetch? Ah, now there's a good reason for this one. Consider this:
def foo(name)
code = SomeHash[name]
raise ArgumentError, "Illegal prototype '#{name}'" unless code
return code
end
There's one immediate problem. What if false is a valid key argument? Or what if you want to merely check if a particular key has been defined even if it's nil? The above code will fail. But Hash#fetch has slightly different semantics. It checks that the key is defined without concern for the actual value and so, can pick up false and nil key values
Basically, you've got three options. Option 1 is to fail with an IndexError if the key isn't defined:
SomeHash.fetch(:bogus) # Boom, IndexError
# vs.
SomeHash[:bogus] # nil
Option 2 lets you specify a default value if the key isn't found:
SomeHash.fetch(:bogus, 7) # 7
Option 3 allows the value of a code block to serve as the value. This is generally used to re-raise a custom exception.
SomeHash.fetch(:bogus){ raise MyError, "Key not found" }
|
|
|
| My libraries repackaged...from the future! |
[Jul. 23rd, 2009|07:44 pm] |
Go ahead, take a look here. Notice anything odd?
"Released Apr 21, 2010"
Huh. Pretty impressive, considering it's only 2009. I hope it includes lottery numbers, too.
This was originally reported to me by Roger Pack here. I think it's the Debian folks repacking my stuff, though it's not entirely clear. It's definitely NOT a mistake in my gemspec - I double checked.
Should I be mad? What should I do about this?
Update: Huh, I think this might be my own fault. It looks like my Linux VM can't keep its own time straight. |
|
|
| How to get a (local) user's home directory on Windows |
[Jul. 22nd, 2009|08:41 pm] |
| [ | mood |
| | calm | ] |
| [ | music |
| | Voices of Autumn 2006 (Beautiful) | ] | While getting the current user's home directory is easy enough for the current user if you're willing to rely on ENV['USERPROFILE'], obtaining the home directory of an arbitrary local user isn't so straightforward. Here's the Ruby solution:
require 'win32/security'
require 'win32/registry'
key = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\"
usr = 'some_user'
sec = Win32::Security::SID.open(usr)
key += sec.to_s
Win32::Registry::HKEY_LOCAL_MACHINE.open(key) do |reg|
puts reg['ProfileImagePath']
end
While win32-registry is part of the standard library, win32-security will have to be installed.
gem install win32-security
In other news, I'm inlining CSS to get purrtier code. I'm using "style='background: lightgray; padding: 1em; border: 1px solid black; color: black'" if anyone cares. |
|
|
| Mixing in singleton methods |
[Jul. 21st, 2009|05:56 am] |
| [ | mood |
| | chipper | ] | I released facade 1.0.3 today. I don't know if I've blogged about it before so I thought I would mention it. In short, it lets you mix in (all or some) singleton methods from a class or module, and turn them into instance methods of the extending class without overriding any existing methods.
For example, there are several singleton methods of the File class, such as File.basename, File.dirname, etc. What if you want to mix them into the String class directly as instance methods? Here's how you do it:
require 'facade'
class String
extend Facade
facade File, :dirname, :basename
end
str = '/export/home/djberge'
str.basename # => 'djberge'
str.dirname # => '/export/home'
Neat, eh? |
|
|
| Preventing massive CPU suckage |
[Jul. 18th, 2009|08:16 am] |
| [ | mood |
| | contemplative | ] | While trying to find a way to simulate getrlimit and setrlimit on MS Windows I realized you could do this on most Unix platforms as a way to prevent your process from sucking massive CPU cycles:
trap('XCPU'){
puts "CPU time exceeded!"
# Insert diagnostic code here
exit!
}
Process.setrlimit(Process::RLIMIT_CPU, 1) # Or whatever max value you want
while true
puts "This should exit in a few seconds..."
end
What I'm not sure of is what a good value is for the maximum CPU time. Then again, maybe limiting RLIMIT_VMEM would be better. Or perhaps both?
I've never done this in practice, btw, but it might be a good way to deal with spiking processes. Just a thought. |
|
|
| More win32-process updates |
[Jul. 16th, 2009|08:12 am] |
We've added a few methods in win32-process to the Process module that were previously unimplemented. Specifically:
* Process.uid * Process.getpriority * Process.setpriority
For Process.uid I decided to return the RID of the owning user's SID. This is the same value that you'll get if you look at the local user account id on your Windows box. The only difference is that I allow an optional parameter which, if set to true, will instead return the binary SID. That way you can use it directly if you need to.
One use would be to use it in conjunction with the win32-security library.
require 'win32/process'
require 'win32/security'
p Process.uid # 1000
p Win32::Security::SID.open(Process.uid(true)) # Security object
Implementing Process.getpriority and Process.setpriority was fairly trivial for processes. I just used the GetPriorityClass and SetPriorityClass functions. The only difference is that you can only set the priority for processes, not process groups or users. Also, the values are different (and limited) when compared to its UNIX counterpart. |
|
|
| Does it hurt to beg? |
[Jun. 6th, 2009|09:25 pm] |
| [ | mood |
| | hopeful | ] | Help me avoid a soul sucking cubicle job:
 |
|
|
| Published! |
[Jun. 2nd, 2009|06:42 pm] |
| [ | mood |
| | ecstatic | ] | I. Am. Published! Nope, not a book, but a game.
Should be out in early August. Oh, and here is the BGG link.
Yes, I know about the typos and have already pointed them out. ;) |
|
|
| Maybe -t isn't the answer |
[Jun. 1st, 2009|04:13 pm] |
| [ | mood |
| | contemplative | ] | I recently submitted a feature request for Rubygems to run with -t (run tests) by default. Because, hey, we're test obsessed right? Maybe it's not such a wise idea, though.
Dave Rolsky points out a problem with running tests by default when installing modules via the CPAN shell in the world of Perl:
Perl has a great culture of testing. We expect all modules uploaded to CPAN to come with a test suite, and we expect modules to run their tests on install and to pass. I love that we have such high standards, but these standards are not without problems. When a module fails its tests, the person doing the install isn't in a good position to handle it. In many cases, they could probably force the install and use the module, but how could they know that? In the comments Perrin Harkin points out:
Running the tests in the CPAN shell before every module install was never very realistic and gets less so every day. I remember back in the early days of working with mod_perl, when the Perl testing culture was not that strong. I would find modules didn't install with the CPAN shell because the tests were written in a way that would never run on any computer except the author's. When I told authors about this, they would say "Oh, I've never used the CPAN shell. I just install modules in the normal way."
No one does that anymore, because the dependency chains are now too long and annoying to do manually. We have to use the CPAN shell. (Or make alternative packaging of some kind, but that's a different story.) So, CPAN.pm should stop running the tests. Either they should be off by default, or it should be obvious how to turn them off globally. If someone is having trouble with a module, they can go run the tests then.
Simply turning off the tests in the CPAN shell would make installing Moose a reasonable thing and do away with nearly all griping about dependencies. Something to think about. |
|
|
| navigation |
| [ |
viewing |
| |
most recent entries |
] |
| [ |
go |
| |
earlier |
] |
| |
|
|