Help
No Helps today.
Interesting
Beware of using OpenStruct. It is very slow to create instances. Evidently it defines a new class for every instance created. When you need to create lots of instances of a struct-like object, use Struct.
No Helps today.
Beware of using OpenStruct. It is very slow to create instances. Evidently it defines a new class for every instance created. When you need to create lots of instances of a struct-like object, use Struct.
When modeling complex business domains, not 3 model blog software, fixtures quickly become a quagmire. What’s the size of your domain? Kevin was working on a project with 180 models. This quickly became unworkable even with only 1 fixture file per model. Fixtures don’t scale well. Scenarios are also problematic as now you have to maintain a directory hierarchy of fixtures.
# Define
Factory.define :user do |f|
f.first_name 'John'
f.last_name 'Doe'
end
# use
user = Factory(:user)
Reopens your ActiveRecord class and adds generators for each attribute.
# define
class User << ActiveRecord::Base
generator_for :username, :method => :next_user
generator_for :email, :start => 'test@domain.com' do |prev|
user, domain = prev.split('@')
user.succ + '@' + domain
end
end
# use
@user = User.generate!
Machinist
Foundry
Fixjour
Martin Fowler says Mocks Aren’t Stubs and talks about Classical and Mockist Teting. Dave shows slightly amusing set of photos about “ists” – Rubyists etc. Ist bin ein red herring. The big issue here is when to use a mock.
Terminology: test double – an object standing in for a real object (like a stunt double).
customer = Object.new
logger = Object.new
customer.stub(:name).and_return('Joe Customer')
logger.should_receive(:log)
customer.should_receive(:name).and_return('Joe customer')
# bad - very tightly bound to implementation
customer.stub(:name).and_return('Joe customer')
# also tighly bound to implementation
Isolation from non-determinism: Simulate random value geneators or Time.now.
Isolation from external depedencies: e.g. external database or network. Have gave anexample or an ActiveMerchant test that takes 1.5s to run, and stubbed out gateway.stubs(:authorize).returns(AM:Billing:Response.new(true, ‘ignore’)
Polymorphic collaborators: e.g. employee that knows how to pay itself, uses a strategy. paymet_strategy = mock() employee = E.new(p_s)
p_s.expects(:pay)
employee.pay
mixins/plugins
side effects: background processing
caching: only call a network zipcode lookup once
validator = mock()
zipcode = Zipcode.new("01234", validator)
validator.should_receive(:valid?).with("01234").once
zipcode.valid?
zipcode.valid?
interface discovery: tool to discover the parts of the system that you haven’t really worked out yet. Mock something out that doesn’t exist yet, while designing its interface.
All of these concepts are Isolation Testing – testing an object in isolation from others. This is a good fit when you have lots of little objects (ravioli code, as opposed to spaghetti code).
Rails is calzone code. Three layers: View Controller Model. These 3 layers are not the whole picture: browser, router, database. Standard rails testing:
Partials in view specs:
before :each do
template.stub(:render).with(:partial => anything)
end
...
template.should_receive(:render).with(:partial => 'nav')
Conditional branches in controllers: Stub new and save! methods of models.
Dave has a new project stubble on github: You will need to build RSpec locally to use this for now.
stubbing(Registration) do
# Stubs ActiveRecord finder and save methods on model
Chains are a new RSpec feature: user.stub_chain – some people say this is a test no-no, use with caution.
I’m happy to announce that AutoTagger 0.9 has been released thanks to Brian Takita and Mike Grafton. This resolves a few major issues and brings AutoTagger a big step closer to being ready for prime-time.
You can read more at http://github.com/zilkey/auto_tagger.
You can install the gem like so:
gem sources -a http://gems.github.com
sudo gem install zilkey-auto_tagger
Thanks Brian and Mike!
This year is the 5th/6th year he has been working with Rails. What hasn’t changed is worth looking at. Things are moving fast at a micro level, but not at a macro level. Stop fretting about whether you are
up to date with the latest features. His 5 year old code might have some old idioms, but generally is still working and doing the same thing.
Not Enterprise Ready “You may have noticed that pretty much everyone on the Ruby camp are insultants with many of them being book authors attempting tp capitalize on hype” – James McGovern. Lesson: You can’t win over over everyone in the world with better logical arguments.
Find the One Thing to make Rails work Sails, Biscuit Grails Monorail – all claimed to have found “The Formula” to make Rails work. Later proven to be a wothless exercise. Lesson: Most worthwhile things in the world can’t be boiled down to one thing.
Waves of Pushback “7 reasons I switched back to php after 2 years on Rails” – Derek Sivers. Communities erupted for 2 days. Lesson: Comments on Reddit don’t change peoples minds.
The Fail Whale – “Rails doesn’t scale”. Some memes are so increadibly powerful and it is useless to fight them. Rails actually has a poster-boy that is one of the most talked about sites of our time. We can take the bad with the good. People can be both proud of things and annoyed at them at the same time.
We have the same core principles we had 5 years ago. Take it easy. Chill out. Most of these things don’t matter as much as you think they do, and the importamnt pieces of them will be extracted and used.
Lock up all the unicorns: Rails 3 is not going to be a complete rewrite and is not going to solve evertbody’s problems. Not everyone is going to get the wonderful feature (unicorn) they want.
No holy cows: No “that is the way it has to be”. That was a mistake the Rails team made in that past and what caused Merb to come into existence. Concrete example: alias_method_chain. Nothing is holy in Rails and if you have an idea that is going to break every Rails app in the world, if it is good enough, it is on the table.
Have it your way: (a la Burger King). How many questions do you get asked when you order a burger. Mot people just want to eat; They just want to get their applications done. On the hand if you really hate pickle, you get to make that choice.
Faster. Route by subdomains, user agents, more. Route to other Rack machinery.
resource :projects, :controller => :project do
resource :attachments
resources :participants do
put :update_all, :on => :collection
end
resouces :companies do
resources :people
resource :avatoar
end
end
Note no block variables. Uses instance_eval to make a cleaner DSL. There goes a holy cow (not using instance_eval in Rails DSLs). Still questioning if this is a good idea. Enjoys the asthetics of this.
(Refresher: Allows someone to inject JS code into your public pages, then steal cookies and do other bad things). Old:
=h (html_escape)
New: By default everything will be escaped in views.
=raw
"random_string".html_safe!
(ed: Yahoo! – Security on by default!)
No more inline onclicks. Adopt HTML5 approach to having custom attributes.
<a href="/comments/1" data-remote="true" data-method="delete">Destroy</a>
<a href="/comments/1" data-confirm="true"
- form_for(@comment, :remote => true) do
Under the covers:
$(document.body).observe("click", function(event) {
// javascript
});
Action ORM – a shim layer on top of all the ORMs.
Generators – make generators smarter about whether they are using RSpec etc.
Things you probably won’t notice. Cleaing up a lot of old code. Abstract Controller + Action Dispatch. Active Relation underpins Active Record. Cherry picking from Active Support. Speedy callbacks.
The humorous bit. What were the elements/principles that made him so productive back in the old days working on BaseCamp. One thing: Renegotiate requirements. Don’t treat requirements as stone tablets. Suggest a better way. “Sure, whatever” – Stakeholders everywhere.
Feed Validation: There are a couple of options for validating feeds.
Firefox shortcuts for bookmarks: In Safari, you can use shortcuts like Apple-1 to load the first bookmark. Is there an equivalent for Firefox?
Nothing interesting to report today. Check back tomorrow.
At Pivotal Labs, our clients, customers, and developers love Pivotal Tracker; after all, we wrote it and selfishly kept it to ourselves for 2 years! With that much history, some of our Tracker projects have built up thousands of stories, and keeping these stories organized is a challenge. Luckily, we designed Tracker with a simple yet powerful organizational tool: Labels. Here are some labeling patterns we find useful.
How many Stories, Bugs, and Chores make up that big Facebook integration feature set, anyway? Which stories are related to the big UI version 3 update? Simply label everything related to a feature set with an easy-to-remember name. This is especially helpful when different pairs or teams are focused on certain groups of features.

It’s true that Tracker doesn’t have the traditional bug categories of P0, P1, P2, to PN. We tend to simply prioritize the most important or critical bugs higher than those less critical, but you can simply create the Labels for bug priorities. That said, there is one Label we almost always create to categorize a subset of bugs — want to guess what it is? If you guessed “ie6″ then you feel our pain!

We often use labels to communicate the state of a Story beyond it’s delivery status. For example, a Story we don’t understand that was added by a remote project manager can be labeled “needs discussion.” A bug that we can’t duplicate might be labeled as such. Designers will want to know which UI stories “need assets.” Team leads and project managers are especially interested in seeing any Story labeled “blocked.” Of course, Labels are not intended to replace actual person-to-person communication — talk to each other!

While Labels are a powerful tool to quickly view the state of the world, don’t go too Label crazy. Labels are not intended to be a discussion forum, flame war, or dumping ground for thoughts.

The Labels and Saved Searches panel brings this all together; activate it at View => Labels and Searches. A picture’s with a thousand words, so check out the following screenshots to see just how powerful Labels are for organizing your project.

The concept of flow holds a mystical, holy place in the lore of software development. Nearly any programmer can tell you about being “in the zone,” totally immersed in code, oblivious to the passage of time. Countless programmers have cited this apparently hyper-productive state when stating their need for enclosed office space, separation from their colleagues, working from home, working at night, or any other similarly isolated work situation.
I’m not going to dispute the existence of a flow state; I’ve experienced it myself. I know the feeling of looking up after solving an interesting problem to find that fourteen hours have passed, it’s the middle of the night, and I haven’t eaten anything since the previous morning. I’ve felt the satisfaction of burying myself in ideas until finally finding a way to convert them into code.
However, I will suggest that working in isolation in order to promote a flow state is not the most productive way to write software. It’s better than working in an environment filled with distractions unrelated to the task at hand, but less productive than working in a collaborative space, or pair programming. To illustrate this, consider another, simpler task that also often involves working in a flow state: cruciverbanalysis.
There’s no such word, of course, but if there were I’d like to think it would mean solving crossword puzzles (a cruciverbalist is someone who constructs crossword puzzles, hence a cruciverbanalyst would be someone who solves them; much like the relationship between cryptographer and cryptanalyst).
Standard American-style crosswords depend on uncertainty for their trickery; many of the clues can have two or more answers. As an example, consider the clue “put away.” The answer could be any of “EAT,” “STOW,” “STORE,” “HOARD,” “JAIL,” or a synonym for any of these. The answer could also be the past tense of any of these answers, since “put” can be either past or present tense.
Thus, to find the correct answer for one clue you have to consider the answers to the clues that cross (or “check,” in crossword parlance) the letters for that clue. But the answers to those clues may depend on the answers to yet more clues, or the possible answers to the original clue. So, the solver has to build a mental picture of the puzzle with possible answers for each clue, as well as the interactions between them. As you might imagine, it takes some time to build up this mental picture, and a great deal of concentration to maintain it. Interruptions, distractions, and time away from the puzzle all quickly destroy it. In short, crossword solvers often work in a flow state.
However, there are a number of ways that a solver can fail to complete a puzzle:
I dislike this type of clue, because you either know the answer or you don’t; there’s no wordplay or clever trick to figure out. If you know that the capital of Mali is Bamako, or that John McCormack was Dame Nellie Melba’s preferred tenor, then good on you. But, if you don’t know, then you’d better hope you know the answers to all of the checked clues.
Think about when this happens while you’re writing code (it happens to everyone, you’re not omniscient). You come across an API you don’t know, an unfamiliar area of the code, or a language feature you haven’t used before. You’re stuck. You can take the time to look it up, but that takes time and interrupts your flow anyway. If you’re working with someone, such as a pair, who does know the answer, then you keep moving forward without a hitch and learn the answer in the process.
Lots of crossword clues try to play on your assumptions to lead you down the wrong path. For example, the clue “Hall of fame” probably makes you think of the Baseball Hall of Fame, or something similar, but the answer could be “ANNIE.” The clue “Peter, Paul, and Mary” probably makes you think of the musical group, but the answer could be “SAINTS” or simply “NAMES.” Infrequently, puzzles will go outside the boundaries of the English alphabet to add to the trickery. Consider an eight letter answer for “The city of brotherly love.” You have to use Greek letters to get the correct answer: “(phi)LADEL(phi)A.”
If you miss the trick, you can’t get the answer. Having more than one person, with more than one viewpoint, looking at the clues will greatly increase the chance that you’ll see all the possibilities.
Designing software well requires choosing a correct approach to each problem. You can’t choose the right approach if you don’t think of it. Sometimes starting a conversation with “I’m thinking of solving problem X with approach Y, what do you think?” can be the best possible use of your time. Someone with a fresh perspective, or just a different perspective, might suggest a better approach than the one lodged in your mind. It’s up to you to set aside your ego long enough to accept the new approach, but that’s a different blog post.
Truly insidious crossword clues not only attempt to lead you to the wrong answer, they try to lead you to a wrong answer with the same number of letters as the right answer. In some cases the wrong answer will have some of the same letters in the same positions as the right answer, increasing your confidence that the wrong answer is, in fact, correct. This wrong answer will then give you the wrong letters for checked clues, leading to more wrong answers. Once you start down this dark path, it’s very, very difficult to recover. This is, incidentally, why crossword enthusiasts insist on solving in pen: you have to be certain before you write in an answer. Otherwise you have to keep everything in your head, which adds to the challenge.
In software, as in solving crosswords, this is a path you do not want to go down. Once you choose the wrong approach (for example, using inheritance where it isn’t appropriate), subsequent decisions take this into account. It can be very difficult to figure out where the true problem lies once you do run into a brick wall. Having someone question your design decisions, or offer alternatives, can help to avoid going down the wrong path to start with. And, when you do have to backtrack, you absolutely want to involve someone with a fresh perspective. Another person, free of your assumptions, will more likely see the misstep.
Finally, consider that crossword puzzles are far simpler than software: there’s only one correct answer to any puzzle (with one notable exception). Software problems can have any number of workable solutions, with various trade-offs that make each more or less appropriate in a given situation. Also, working on any software project of significant size is really more like working with multiple people to solve several puzzles which check against one another in various dimensions. As the complexity of interactions increases, I’d expect the advantages of collaboration to increase at least linearly.
For those who would still argue that flow is necessary because it’s how programmers prefer to work (it can be quite enjoyable), I’d suggest you get yourself a book of crosswords. With puzzles you can sit by yourself and exercise your flow state as much as you like without spending anyone else’s money, or making anyone else’s life more difficult.
As web developers in the Web 2.0 world, we work with transparencies and gradients all the time. Sometimes we get a bunch of assets from a designer and can’t easily see how the visual assets are constructed: what parts are transparent? Is the background grey or transparent? How drastically does a gradient fade? Get some answers quickly by tweaking OS X Preview.
These four images from OS X have a lot of grey in them, making it hard to see the transparencies and gradients.

Tell Preview to show the image’s background in View => Show Image Background so you can at least see the dimensions and transparencies. But, this leaves a lot to be desired since it’s still pretty hard to see the grey pieces.

I like this one even better: change Preview’s window background color to something something that definitely will now show up in your images by going to Preview => Preferences => Window Background. Here I’ve chosen “Tangerine” and you can very easily see the dotted lines in ftvpnode.png and might be surprised to find out that the bottom part of user_14.png is not actually a transparent gradient, but a grey gradient.

Hope that helps!
Git merge strategy “ours” is destructive: When doing a git merge that causes a conflict, picking “ours” as the merge strategy causes git to choose our changes for ALL files, not just those with a conflict, i.e. it ignores the changes in the other branch. From git-merge(1): “ours”: This resolves any number of heads, but the result of the merge is always the current branch head. It is meant to be used to supersede old development history of side branches.
New Relic RPM GEM problem: We encountered a case where using the GEM version of RPM in a project caused no telemetry to get logged. This may be an interaction with Desert or Geminstaller (or the GEM may be broken but we consider that unlikely). After switching from the GEM to the plugin, everything worked fine.
Collectl is a system performance data gathering tool. From it’s website: “Unlike most monitoring tools that either focus on a small set of statistics, format their output in only one way, run either interatively or as a daemon but not both, collectl tries to do it all.” Kinda like sar+top and user friendly too.
MySQL Analyze Table – no substitute for Explain: From the MySQL 5.0 docs: “ANALYZE TABLE analyzes and stores the key distribution for a table. MySQL uses the stored key distribution to decide the order in which tables should be joined when you perform a join on something other than a constant. In addition, key distributions can be used when deciding which indexes to use for a specific table within a query.” Sounds great huh. However we found a case here where using FORCE INDEX to get a select statement to use the right index caused a 2 order of magnitude speed increase. Moral: There is No Substitute for Explain and a Brain.