Using model constants for project sanity »
Created at: 23.06.2009 09:39, source: Robby on Rails, tagged: Ruby on Rails ruby programming development ruby rubyonrails model activerecord businesslogic code
On one of our larger client projects (approx. 160 models and growing…) we have a specific model that we refer to quite a bit throughout our code. This model contains less than 10 records, but each of them sits on top of an insanely large and complex set of data. Each record refers to a each of their regions that our client does business in.
For example… we have, Australia, United Kingdom, Canada, United States, and so forth. Each of these regional divisions has their own company code, which are barely distinguishable from the next. They make sense to our client, but when we’re not interacting with those codes on a regular basis, we have to look constantly look them up again to make sure we’re dealing with the right record.
I wanted to share something that we did to make this easier for our team to work around these codes, which we should have thought of long ago.
Let’s take the following mode, Division. We only have about 10 records in our database, but have conditional code throughout the site that are dependent upon which divisions specific actions are being triggered within. Each division has various business logic that we have to maintain.
Prior to our change, we’d come across a lot of code like:
# For all divisions except Canada, invoices are sent via email
# In Canada, invoices are sent via XML to a 3rd-party service
def process_invoices_for(division)
if division.code == 'XIUHR12'
# trigger method to send invoices to 3rd party service
# ...
else
# batch up invoices and send via email
# ...
end
endAn alternative that we’d also find ourselves using was.
if division.name == 'Canada'Hell, I think I’ve even seen if division.id == 2 somewhere in the code before. To be fair to ourselves, we did inherit this project a few years ago. ;-)
Throughout the code base, you’ll find business rules like this. Our developers all agreed that this was far from friendly and/or efficient and worst of all, it was extremely error-prone. There have been a few incidents where we read the code wrong and/or got them confused with one another. We were lacking a convention that we could all begin to rely on and use.
So, we decided to implement the following change.
Model Constants
You might already use constants in your Ruby on Rails application. It’s not uncommon to add a few into config/environment.rb and call it a day, but you might also consider scoping them within your models. (makes it much easier for you to maintain them as well)
In our scenario, we decided to add the following constants to our division model.
class Division < ActiveRecord::Base
AFRICA = self.find_by_code('XYU238')
ASIA = self.find_by_code('XIUHR73')
AUSTRALIA = self.find_by_code('XIUHR152')
CANADA = self.find_by_code('XIUHR12')
USA = self.find_by_code('XIUHR389')
# etc..
endWhat this will do is load up ech of these constants with the corresponding object. It’s basically the equivallent of us doing:
if division == Division.find_by_code('XIUHR389')But, with this approach, we can stop worrying about their codes and use the division names that we’re talking about with our clients. Our client usually approaches us with, “In Australia, we need to do X,Y,Z differently than we do in the other divisions due to new government regulations.”
if division == Division::CANADA
# ...
end
case division
when Division::AFRICA
#
when Division::AUSTRALIA
# ...
endWe are finding this to be much easier to read and maintain. When we’re dealing with a lot of complex business logic in the application, little changes like this can make a big difference.
If you have any alternative solutions, we’d love to hear them. Until then, we’ve been quite pleased with this approach. Perhaps you’ll find some value in it as well.
more »
Aliasing resources in Ruby on Rails »
Created at: 23.06.2009 09:00, source: Robby on Rails, tagged: Ruby on Rails programming PLANET ARGON rubyonrails rails routes seo development
Earlier today, a friend working on a project asked me how we approached routes on our website. If you take a quick peak at our website, you’ll see that we have URLs like so:
- http://planetargon.com/
- http://planetargon.com/who-we-are
- http://planetargon.com/who-we-are/robby-russell
I couldn’t remember where I came across this before and wasn’t quickly finding it in the Ruby on Rails API, so decided that I’d do a quick write up on it.
When we launched our new site a few months ago, we were working off an existing code base. We have a model named, TeamMember and a corresponding controller. When we decided to come up with new conventions for our URL structure, we opted to ditch the normal Rails conventions and go our own route. What we weren’t sure about was how to alias resources in our routes nicely. After some digging around, we came across the :as option.
So, our route was:
map.resources :team_membersWhich provided us with:
- /team_members
- /team_members/robby-russell
We simply added :as => 'who-we-are' to our route:
map.resources :team_members, :as => 'who-we-are'...and we got exactly what we were looking for in our URLs.
* /who-we-are
* /who-we-are/gary-blessington
If you look at our site, you’ll notice that we did this in a few areas of our application so that we could define our own URL structure that was more friendly for visitors and search engines.
Anyhow, just a quick tip for those who want to change up their URLs with Ruby on Rails.
p.s., if you know where I can find this documented, let me know so that I can provide a URL in this post for others. :-)
more »
Howdy Rip! »
Created at: 11.06.2009 20:35, source: Robby on Rails, tagged: Ruby on Rails ruby programming ruby rubygems gems git github rubyonrails development
Chris Wanstrath (@defunkt) just posted the following on twitter.
“Hello Rip – http://hellorip.com/“
The Rip project describes itself as, “an attempt to create a next generation packaging system for Ruby.”
One of the cool features is that it supports multiple environments. For example, you can have different Rip environments (with different gem versioning) that are targeted towards specific applications. I have to dig around more through the project, but this looks fascinating.
Check it out at http://hellorip.com/
I’m also curious as to how you think you might be able to start using this.
- What are some ways that you could use Rip—http://heybrainstormr.com/t/pgte
more »
What can we do right now? »
Created at: 04.06.2009 02:12, source: Robby on Rails, tagged: ruby programming Projects agile gtd team book programming inspiration motivation kindle
Last month I picked up a new kindle from Amazon and have been reading a handful of books. One book that I’ve been really impressed with is Chad Fowler’s new book, The Passionate Programmer.
I plan to post some more thoughts in upcoming articles, but wanted to share this gem.
“If you treat your projects like a race, you’ll get to the end a lot faster than if you treat them like a prison cell. Create movement. Be the one who pushes. Don’t get comfortable. Always be the one to ask, “But what can we do right now?”” - Chad Fowler, The Passionate Programmer
Sometimes we feel stuck, but that doesn’t stop us from stepping to the side and assessing the situation. There is always something useful that we could be doing right now.
more »
Estimating software: a rule of thumb »
Created at: 02.06.2009 19:06, source: Rail Spikes - Home, tagged: Business programming
Estimating software is hard, but most of us have to do it – whether we’re estimating an entire project for a client, or a new feature for a boss, or a change to one of our own projects.
I’ve found the following rule helpful when estimating software. This comes from about four years of estimating Rails projects to consulting clients, and moving from bad – dramatically underestimating fixed-bid projects – to pretty good – usually overestimating time & materials projects slightly. (And more importantly, knowing when I can’t estimate, because the scope is too vague or too large.)
Jon’s Law of Estimates
Software difficulty is primarily determined by volume, logic, and integration.
Jon’s Law of Estimates, explained
1. Volume is easy to understand. If you’re building software that does more, it will require more work. So if you’re estimating a project that stores recipes, and you’re estimating another project that stores recipes AND shopping lists, you can expect that the second one will take more work (if everything else is equal).
2. Logic refers to the rules or business logic behind a feature. The more rules there are, the more work there is. Imagine that our recipe system requires that recipes from some users are manually approved by an administrator, and checks to see that each ingredient in the recipe is present in the step-by-step instructions, and only allows a user to post 3 recipes per hour, and lets users propose alternative versions of a recipe, and lets an alternative version replace the regular version if it achieves a certain rating, etc. That’s more work than a recipe system that just lets users create and rate recipes, even though the volume of features may not be any larger.
Interestingly, a technology can make some logic trivial and some logic hard. Nested forms are a great example of this. Before Rails 2.3, Rails made it trivial to do CRUD on a single table at a time, but difficult handle multiple tables. Now it is (almost) trivial to do CRUD on multiple tables at a time.
3. Integration points are usually deserving of special consideration in an estimate. This includes talking to a web services API, another local software system, a data feed, a complex library, etc. Not only do integration points often take time to get right, but they can become sinkholes of time when the documentation is inadequate or incorrect, the other system doesn’t play nice, or you can’t easily test the integration. And your estimate depends on something out of your control: the other system.
External factors
These rules only apply to the difficulty of the software. Several external factors are important as well. These include, most notably, the client and the team. The client can make a project easy, or they can make a project difficult. Similarly, the right team might be able to blaze through a project quickly, while the wrong team may never finish at all.
The other side of estimating
Here’s the thing about these rules: they’re relative, not absolute. There is no rule that says “Features take 5 days, and integration points take 10”. So estimating requires comparisons. This means that if you’ve never built a Rails app before, you’ll have trouble estimating a Rails project. But once you’ve built a few, you can compare the volume, logic, and integration points of a new project to volume, logic, and integration points of the previous ones.
So estimating requires intuition and experience as well as analysis (e.g. Jon’s Law of Estimates). The key to estimating is to combine analysis and intuition, and to let each side refine the other.
more »

