Initialization code should avoid overwriting parameters explicitly passed in

This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the rails category.

Last Updated: 2024-11-21

What's the problem with this code?

Here's how it's defined...

def state_machine(default_initial_state:, &state_machine_rules)
  after_initialize do
    self.state = default_initial_state
  end
  ...
end

... and here is how it was called:

class Seller
  state_machine default_initial_state: "applied" do
    # rules
    ...
  end
end

seller = Seller.new
# or
seller2 = Seller.create(state: "uploaded_files)

--

The issue is that it always sets the state attribute to default_initial_state, ignoring anything passed in! Thus, in the 2nd example above, the state would not be uploaded_files - but rather applied.

Here's the fix:

def state_machine(default_initial_state:, &state_machine_rules)
  after_initialize do
    self.state ||= default_initial_state
  end
  ...
end