

Rails Gotcha With before_validation - squid_ca
http://factore.ca/on-the-floor/77-rails-gotcha-with-before-validation

======
technoweenie
It's not really a gotcha since it's documented:

See the section "Cancelling Callbacks" in the docs for ActiveRecord::Callback:
[http://rails.rubyonrails.org/classes/ActiveRecord/Callbacks....](http://rails.rubyonrails.org/classes/ActiveRecord/Callbacks.html)

"If a before_* callback returns false, all the later callbacks and the
associated action are cancelled. If an after_* callback returns false, all the
later callbacks are cancelled. Callbacks are generally run in the order they
are defined, with the exception of callbacks defined as methods on the model,
which are called last."

before_filter in controllers used to work the same way, but somewhere along
the way it was changed to check #performed? on the controller. That way
before_filters only cancel the action if it redirects or renders a template.

How else would you do that for callbacks though? Force the user to raise
something like ActiveRecord::CancelCallback? Use the obscure throw/catch
statements?

~~~
Robin_Message
Raising an exception is a good method. A better method would be a condition
system [1], which enables more fine grained handling of such things. throw and
catch are a kind of bad implementation of this, but there is no reason you
couldn't use them, except that very few people do.

In practice, maybe a Ruby linter could/should pick this pattern up and warn
about it? It wouldn't be hard to identify functions which return a value based
on a block if with no else say.

[1] [http://www.gigamonkeys.com/book/beyond-exception-handling-
co...](http://www.gigamonkeys.com/book/beyond-exception-handling-conditions-
and-restarts.html)

------
subbu
This is one of the reasons why you should learn Ruby throughly before you
could become a Rails master. The value of last expression executed within the
function becomes the return value of the function itself.

------
dansingerman
I don't think the gotcha is so much with before_validation, as with Ruby's
implicit return values.

~~~
pak
Besides brevity is there any other case for implicit return values? I love
little lambdas as much as the next guy but does the cost have to be that every
one of my functions returns something unless I write an extra line to the
contrary?

I'd rather pay the price of typing

    
    
      return self.shipping = false
    

to make the function return false if I actually wanted it to do so, rather
than

    
    
      self.shipping = false
      true
    

which just looks bizarre to me and doesn't make its motive clear (you wind up
only including it when your last expression evaluates to false). I have vague,
unpleasant memories of also encountering this gotcha with Perl in RT scrips,
where you would suffix silly little 1;'s and 0;'s to everything to make the
next action run or not run.

I don't know about everybody else, but I don't FP to the extent that I never
write subprocedures. Isn't this still typical?

