Professionals Act Professional
I’m sick of it.
Every week (at least it feels that way) some new drama rears its ugly head in the ruby community. Petty arguments via twitter, one ranting blog post after another, people mocking ideas they consider less than ideal, and even some personal attacks thrown in the mix. There’s so much drama in fact that there is now a site out there that lists it all for the rest of the world to see.
Seriously? Are we all still in junior high?
Just think for a minute about all of the time and energy we are wasting here. Instead of igniting these flame wars, from which nothing productive is ever achieved, we could be growing as a community. We could be bringing up the next generation of software developers. We could be positively encouraging others to build better software. We could be sharing our experiences with others. We could be leading by example.
For a community of people complaining that they’re not treated like professionals, we sure don’t act very professional. If this is the way we behave, can we honestly expect people to treat us with the respect that they treat doctors, accountants, teachers, and members of other professions?
If you want to be treated like a professional, it’s best to start acting like one first.
Take the high road for once. The view is much nicer.
Optional method parameters in Ruby
One of the things I love about Ruby is the flexibility it provides when it comes to method parameters. It’s dead simple to provide default values for one or more parameters, to handle variable length argument lists, and to pass blocks of code into a method. But perhaps my favorite is the ability to tack hash key/value pairs onto the end of a method call, and have those options combined into a Hash on the other side.
def some_method(required_1, required_2, options={})
# Do something awesome!
end
some_method("foo", "bar")
some_method("foo", "bar", :option_1 => false, :option_2 => true)
some_method("foo",
"bar",
:option_1 => false,
:option_2 => true,
:option_3 => "something",
:option_4 => "something else")
This may not look like much. However, this feature alone is capable of producing some very readable code, and is used extensively in APIs throughout the Ruby ecosystem. Consider for a moment what these APIs would look like if Ruby did not have this capability, which isn’t hard to imagine for those of us with a background in a language like Java. You would either be forced to require that each parameter be specified:
# What is this code doing? What do the nil values,
# or even the true and false values map to?
some_method("foo", "bar", false, nil, true, nil)
or accept a hash or a request object that contains all of the necessary parameters:
# This is much more readable, but requires that the
# options hash be created on its own line.
options = {:option_1 => true, :option_2 => false}
some_method("foo", "bar", options)
Providing optional parameters via hash key/value paris at the end of a method call produces code that is incredibly readable. You have the names of the attributes right next to their corresponding values! There is no ambiguity whatsoever as to which values match up with which parameters.
It is also very flexible. The order of the attributes in the hash does not matter, like it does for required attributes. And, it is very easy to add new options, or delete old ones.
This approach also makes it easy to specify default values for options that were not specified when calling the method:
def some_method(required_1, required_2, options={})
defaults = {
:option_1 => "option 1 default",
:option_2 => "option 2 default",
:option_3 => "option 3 default",
:option_4 => "option 4 default"
}
options = defaults.merge(options)
# Do something awesome!
end
There are however a few minor drawbacks to this approach. The first is documentation. Methods that take a hash of options as a parameter do not convey any information about the valid options in the method definition alone. And, it is possible that the method in question simply forwards the options to another method, sending you on a wild goose chase to determine the set of valid options the code supports.
# Looking for a list of valid option keys...no help here.
def some_method(required_1, required_2, options={})
do_something_awesome_with_the_options(options)
end
This is why it is so important do document your public API if you are using this approach. Take a look at the ActiveRecord::Associations::ClassMethods documentation. This page documents, in a very clear and easy to read mannor, all of the supported options for each method.
It is also worth pointing out that while this approach is great for optional parameters, it is ill suited for required parameters. Required parameters should be specified outside of the options hash, making it clear that values for the required parameters must be provided. While it’s true that stuffing all of your parameters inside a hash means you’ll never have to look at another wrong number of arguments error again, it will make your code difficult to understand, and easy to misuse.
Introducing Tenacity – An ORM Independent Way to Manage Inter-database Relationships
I’m a big believer in polyglot persistence. There are so many (very different) production ready databases available today that’s it is becoming more and more common to find applications using more than one database, utilizing the strengths of each. Using the right tool for the job gives me a warm, fuzzy feeling inside.
However, polyglot persistence comes with its own set of drawbacks. One of those drawbacks is the loss of foreign keys, which are very important in maintaining data integrity. Another drawback is that Object/Relational Mapping (ORM) libraries typically focus on a specific database, or type of database. So, writing code that manages relationships between objects backed by different databases hasn’t been nearly as easy as writing code to manage relationships between objects in the same database.
Tenacity’s goal is to address some of these issues. Tenacity is a ruby gem that provides an ORM independent way of managing relationships between models backed by different databases.
Tenacity works by extending popular Ruby ORM libraries to respond to a set of methods that the tenacity core uses to build and manage relationships between objects. By extending the ORM libraries to implement this interface, tenacity is able work with the objects in a generic way, without having to know what database is backing the given objects. This approach also allows you to continue using your favorite ORM libraries. To use tenacity, you simply need to include Tenacity inside your model.
Tenacity is heavily based on ActiveRecord’s associations, and aims to behave in much the same way, supporting many of the same options.
This initial release of tenacity supports belongs_to, has_one, and has_many associations, and the ActiveRecord, CouchRest, and MongoMapper ORMs. However, there is still plenty of work to be done. Feedback, bug reports, and code contributions are always welcome.
Tenacity is free and open source, and can be found on GitHub at https://github.com/jwood/tenacity.
Example
Download
gem install tenacity
Trastel Accepted as Official Service Level Testing Tool @ Orbitz
Trastel, the DSL I created to help with the automated testing of our services at Orbitz, has been accepted as the QA team’s official testing language. Yippee!
Addressbook Webapp Has Been Released
Yay for me! I set a personal goal to have the code for all of my Rails apps on this site by the end of the year. Tonight, I can check that one off the list. The code for the Addressbook webapp is now available for download. Addressbook was not only my first Rails app, but also my first experience with Ajax. And trust me, it shows. I learned a lot from this project, especially what not to do. However, I must also say that I use Addressbook more than any other personal project I have ever completed. So, it can’t be that bad :) I love the fact that I can access my contact information from anywhere, and that I can manage groups of addresses and print mailing labels with the click of a button. Sure, the UI can be a bit unintuitive, but it’s not that big of an issue for me. There are a few more things I’d like to do with this project. We’ll see where it goes from here.
GitHub
Most Popular Posts
Tags
Archives
- May 2012 (1)
- April 2012 (1)
- March 2012 (1)
- February 2012 (1)
- December 2011 (1)
- September 2011 (1)
- July 2011 (1)
- May 2011 (1)
- April 2011 (1)
- March 2011 (1)
- January 2011 (2)
- November 2010 (2)
- September 2010 (1)
- August 2010 (1)
- July 2010 (2)
- June 2010 (2)
- April 2010 (1)
- March 2010 (1)
- February 2010 (2)
- January 2010 (1)
- December 2009 (1)
- November 2009 (1)
- September 2009 (2)
- August 2009 (3)
- July 2009 (2)
- June 2009 (3)
- April 2009 (1)
- February 2009 (1)
- January 2009 (2)
- December 2008 (8)
- November 2008 (2)
- October 2008 (3)
- September 2008 (6)
- July 2008 (3)
- June 2008 (1)
- May 2008 (8)
- April 2008 (6)
- March 2008 (2)
Blogroll
Industury News
Other Links
My GitHub Feed
- jwood pushed to master at signal/signal-ruby
- jwood pushed to master at signal/proby
- jwood pushed to master at signal/proby
- jwood pushed to master at signal/signal-ruby
- jwood pushed to master at signal/proby
- jwood pushed to master at signal/signal-ruby
- jwood pushed to master at signal/signal-ruby
- jwood pushed to master at signal/proby-ruby
- jwood commented on pull request 9 on stripe/stripe-ruby
- jwood pushed to master at signal/proby




