Home
Testing 1,2,3... [entries|archive|friends|userinfo]
djberg96

[ website | Sapphire ]
[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Links
[Links:| Ruby Home RubyForge RAA comp.lang.ruby Ruby Documentation ]

The Mysteries of Life: Computer Speakers [Oct. 25th, 2009|09:29 am]
[Tags|]
[mood | confused]

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?
linkpost comment

Test::Unit 2.x, now with TAP [Oct. 22nd, 2009|09:34 am]
[Tags|, , ]
[mood | cheerful]

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.
linkpost comment

Back to Rails [Oct. 20th, 2009|02:11 pm]
[Tags|, ]
[mood | annoyed]

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.
link3 comments|post comment

More random thoughts on mixins, selector namespaces [Oct. 14th, 2009|01:05 pm]
[Tags|]
[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.
link4 comments|post comment

Face. Palm. [Sep. 24th, 2009|08:37 am]
[mood | distressed]

Note to self: Dir['*/**'] and Dir['**/*'] do NOT do the same thing.

Gawd.
linkpost comment

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!
link2 comments|post comment

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.
linkpost comment

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.
linkpost comment

For you Smalltalk/Ruby fans [Sep. 1st, 2009|09:13 pm]
[Tags|, ]
[mood | curious]

I just came across this: http://smalltalk.felk.cvut.cz/projects/smallruby

I've no idea what the actually compatibility is. Still, looks cool.
linkpost comment

FFI Blues [Aug. 7th, 2009|11:04 am]
[Tags|, ]
[Current Location |United States, Colorado, Broomfield]
[mood | blah]

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.
link3 comments|post comment

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.
linkpost comment

Hash#fetch [Aug. 5th, 2009|05:01 pm]
[mood |awake]

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" }
link1 comment|post comment

My libraries repackaged...from the future! [Jul. 23rd, 2009|07:44 pm]
[mood |awake]

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.
linkpost comment

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.
link4 comments|post comment

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?
link1 comment|post comment

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.
link1 comment|post comment

More win32-process updates [Jul. 16th, 2009|08:12 am]
[Tags|, ]
[mood |busy]

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.
linkpost comment

Does it hurt to beg? [Jun. 6th, 2009|09:25 pm]
[mood | hopeful]

Help me avoid a soul sucking cubicle job:

Click here to lend your support to: Awesome Ruby Development and make a donation at www.pledgie.com !
link2 comments|post comment

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. ;)
link7 comments|post comment

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.
link10 comments|post comment

navigation
[ viewing | most recent entries ]
[ go | earlier ]

Advertisement