Archive for the 'Ruby' Category
Writing a Yard Extension To Show Inherited Attributes
So RDoc is an absolutely terrible documentation generator both from the usage and the coding perspective. Although yard is not yet quite as stable as I’d like, it is everything RDoc is not, it’s pretty, well written, and provides numerous well thought out extension points. So as an exercise I decided to fix one of the more annoying issues with yard as an extension.
Read more
Unit, Cucumber, and/or Rspec (DHH Say it ain’t so!)
So recently, dhh tweeted that he doesn’t really get why cucumber and rpsec are so popular and questioned their benefit outside of a niche audience relative to the high cost of writing with them relative to X-Unit style tests. I’ve used ruby test, rspec, and cucumber extensively and I’m finding it hard to see that point of view.
I think the disconnect may be related to what your perspective is on the use of a unit test. While I think most developers would agree that unit tests are for validating and developing code, I think if that is all you see them for it is essentially like saying that good code is code that performs a task correctly. In both cases there are more factors to consider.
First, tests have to be maintained just like any other code. Unmaintainable tests slow down code refactoring rather than supporting it and as such will generally be discarded and the most useless tests are ones that don’t get run. So at the very least you need to apply the same concepts of readability, maintainability, etc to your tests that you (hopefully) bring to the rest of your code.
A second, and to my mind equally important, use of tests is to document what your system is supposed to do. Large projects with many maintainers and users may not have as much of an issue here. If your framework is covered by thousands of blog articles, books, and examples are widely available then feel free to disregard this advice. For the rest of us, getting as much self-documentation out of a code base as possible should be a major goal.
This is really where both cucumber and rspec outshine XUnit style test frameworks. A cucumber test is a human-readable description of feature of your system that a new coder can read without having to understand the underlying code. Even better, because each statement in the description links to code it provides a direct link between feature documentation and code required to configure, execute, and validate that feature. Finally, error messages have the same level of descriptive context making understanding errors that much easier.
The one point I will concede is that cucumber is not one size fits all. If you are validating an API (as opposed to a product interface like a web page or gui) cucumber is less beneficial because it obscures the API itself and replaces it with human language. In these cases rspec is clearly preferred.
In cases where you are testing the system however cucumber has some clear benefits over rspec:
- It forces you to think in terms of how the product will be used rather than how it is implemented.
- It forces you to describe that behavior concisely.
- It documents the behavior of the system clearly in a way even a non-programmer can understand.
- By doing all of this it makes maintaining tests much easier even as product feature implementations change because implementation is clearly abstracted from the test script
Reopening modules in Ruby
Open class definitions in ruby allow libraries to add functionality to existing objects. Standard practice is to define a module with the new functionality and include it into the existing class ( Jay fields on the subject here ). Unfortunately this model breaks when you want to update a module.
Read more
Why class variables in Ruby are a bad idea
In ruby, there are instance variables and class variables. Class variables may not work the way you think… Read more
No commentsImproving your exception backtrace with Ruby DSLs
One issue with a Domain Specific Language in any language is that the error messages from the actual language tend to ruin the illusion of a custom language. In ruby a stack trace with a million “method_missing” calls can be confusing.
So what can you do? Edit and filter the backtrace.
Read more
attr_accessor with default in Ruby
If you aren’t in rails (hello to both of you) the lack of an attr_accessor with a default value is very annoying. I wrote up the following:
module ExtendAccessors def attr_accessor_with_default name, *default, &block if(default.size >= 1) define_method name.to_sym do instance_variable_set("@#{name}", default[0]) unless instance_variable_defined?("@#{name}") instance_variable_get("@#{name}") end elsif block_given? define_method name.to_sym do instance_variable_set("@#{name}", instance_eval(&block)) unless instance_variable_defined?("@#{name}") instance_variable_get("@#{name}") end else raise "Must either provide a default value or a default code block" end define_method "#{name}=".to_sym do |value| instance_variable_set("@#{name}",value) end end end
which supports the following syntax:
class A extend ExtendAccessors attr_accessor_with_default :some_map, {} attr_accessor_with_default :some_object do AnotherObject.new(self) end end
Meaning of ’self’ in Ruby
This came up today. When defining classes in Ruby “self” can refer to the class or the instance of that class depending on the context and understanding which is which is important.
When defining a class “self” in the context of the class definition refers to the object representing the class being defined. When in a (non-class-level) method “self” refers to the instance of the object. So:
class SomeClass #dynamically add a method to the SomeClass object. #self is the SomeClass class object #now I can call SomeClass.class_level_method def self.class_level_method self == SomeClass #this is true.... end #define an instance level method def instance_level_method self #this is now an instance of the object end end
This syntax may make more sense in terms of the following
class SomeClass end #this can be done outside of the class definition def SomeClass.class_level_method echo "hi" end c = SomeClass.new d = SomeClass.new #class objects are notspecial in this regard. #You can do the same thing to #a specific object instance of any other type. def c.specific_instance_method #this method is defined just for this #specific instance of this class end c.specific_instance_method #no problem d.specific_instance_method #nope!
SWIG, Java, and JRuby
Providing a robust, maintainable, and interactive interface to your C/C++ application can be a challenge, but I’ve found that a combination of SWIG, Java, and JRuby (or Jython if you prefer) makes for a very powerful combination.
Read more
A Better Binary File Generator DSL in Ruby
In Creating a Binary File Using a Ruby DSL I did a very small example of using a ruby DSL to generate complex binary files without having to use C or a hexeditor. I’ve beefed it up significantly since then so here is the updated version of h2b.irb.
Read more