Best way to catch :abort signal thrown in Rails 5 controller - ruby-on-rails-5

In Rails 5, when a callback needs to cancel later callbacks, the recommended process is documented as "you should explicitly throw :abort."
My question is: how is it recommended that this exception be caught?
My current solution is to catch UncaughtThrowError in my ApplicationController - given the way it's documented, I thought this feature would trigger some magic in Rails or a Rack middleware to immediately move to the rendering (ActionView) phase.

Here are some examples of how to use the throw/catch in ruby.
For Rails, I think something like this will do the trick:
class SomeController
def some_method
if catch(:abort) { mode.save }
# success
else
# failure
end
end
end

You would probably have to write a method that overrides the underlying method for processing callbacks to have a catch :abort {} that handles it, which feels like too much magic.
I think using a rescue_from UncaughtThrowError in the controller you're throwing in seems a better approach vs. having it in the ApplicationController unless this is really common callback, in which case you probably want a Concern?
I went down this road for a day, and then decided to not use a callback for what I wanted to do, which eliminated the whole need for the callbacks, throws, rescues, and catches.
Still, I'm sure there are good cases for this approach, but it's not well documented as to how.

Related

Validation in setters: What approach is better?

I have dispute with my friend.
He said me that this code:
method SetBalance(balance) {
if (balance > 0) {
this.balance = balance;
return true;
}
return false;
}
is better then this:
method SetBalance(balance) {
if (balance < 0) {
throw new InvalidArgumentException("Balance couldn't be negative")
}
this.balance = balance;
}
My question is: "Which approach is better for validation?" and why?
Thank you.
Ah. Return status versus exception.
I prefer throwing exceptions, because you can't really ignore an exception. The program either crashes, or you have to explicitly catch and handle it.
You can just ignore a return status.
Besides, isn't this the reason exceptions exist in modern programming? To deal with, well... exceptions (balance <= 0, something that shouldn't happen).
In case of setters, developers will never expect the return value from those methods since they feel that this will anyway will take care of setting the value.
In case, if there is an exception, then this will help then to understand that something is really wrong and look after the code again.
Instead of runtime exception, you better define your own exception like InvalidBalanceException and specify that this method will throw this exception in the signature itself. This avoids surprises at testing phase and decide the business logic in development phase itself.
Return value is easily ignored. Here you have clear coding bug, so crash loud. I would even halt/segfault/stop program - the exception may still be caught. We live in "ideal world", but imagine our less fortunate colleagues - they might well go for gagging error signalling facility being unable to deal with the root cause (insert here more complicated error scenario). Coding gets much easier when you dont give clients ways to do things wrong way.
Besides the answers given already, returning a boolean value in a function named "setFoo" is very misleading. If you translate a boolean value you come up with yes/no. So a function that returns booleans in oop should be readable as a question that gives yes/no as an answer, e.g. isBalanceSet.
In discussion with collegues we considered the only valid return-value for a normal setter is the class itself for fluent-interfaces.
Regarding your question throwing exceptions is the better solution if the class actually validates its properties itself ;)
My personal opinion: both approaches has its uses. It depends on why the situation arose, could it be prevented, what the client could have done to prevent it.
Server:
method SetBalance(int balance)
{
// do something only if balance >= 0
}
Client:
myServer.SetBalance(balance);
Case 1:
The situation arises only because of a bug somewhere (in server or client). Throw exception. Let the responsible party fix its code.
Case 2:
A bad input is received from some external dependency. The client could easily check the precondition. Throw exception, let the client fix its code if she is unhappy with that.
if(balance>0)
myServer.SetBalance(balance);
else
//take appropriate action.
Case 3:
A bad input is received from some external dependency. The client could not easily check the precondition. Example: it would require the client to parse a string, which is the server's job. Here, it makes sense that the server should return success:
bool succeeded = myServer.SetBalance(balance);
if(!succeeded)
//take appropriate action.
After writing my answer down, I noticed it all boils down to this: The client should not have to use try-catch to call the method SetBalance. (Either it's a bug so don't catch the exception, or check the precondition yourself, or inspect the return value)
Here is a good reading on a related subject: http://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx
Edit:
Jojo makes a good point. Rename the method TrySetBalance() if there is a probability that it might fail.
Exceptions handling is the method of choice to handle errors in OOP, whether it is runtime error or logic error. One of the arguments to justify exception handling is that, if error code is used a client of a function may forget to check the error code leading to a potential bug which may not be easily found. Whereas, if exception handling is used, even if it is not caught, it will propagate until it is handled. So, OOP purists always advice using exception handling.

Why Railtie initializers are not executed?

While crafting the Passenger-Monit plugin, I thought that it'll be most appropriate to use the initializer, i.e.
module PassengerMonit
class Railtie < Rails::Railtie
initializer "my_plugin.some_init_task" do
# my initialization tasks
end
end
end
However, for some reason the code in the block was never executed.
I finally made a work-around with
config.before_initialize {}
but I'm curious, why the initializer wasn't executed. What could have prevented it from running?
In your gemfile, did you add
gem "Passenger-Monit"
Otherwise you need to put it in your load path and require it in your application.
http://www.igvita.com/2010/08/04/rails-3-internals-railtie-creating-plugins/
Good luck!

How to use 'after_initialize' in Rails 3?

UPDATE
I wrongly checked the edgerails guide instead of the currently correct Rails 3 guide (which has no mention of after_initialize). Not sure why the edgerails guide is "incorrect" though - I thought edgerails guide was supposed to be the latest up-to-date guide?
I'm leaving this question as-is just in case someone comes looking for the same "problem".
Macro-style call to after_initialize is the way to go.
Should after_initialize be used as method or macro-style call ?
This works, but gives a deprecation warning:
def after_initialize
logger.info "Called after_initialize"
end
DEPRECATION WARNING: Base#after_initialize has been deprecated,
please use Base.after_initialize :method instead.
This works, and there is no warning:
after_initialize :do_this_after_initialize
def do_this_after_initialize
logger.info "Called after_initialize"
end
But the Active Record Validations and Callbacks Guide in 10.4 after_initialize and after_find says:
...If you try to register
after_initialize or after_find using
macro-style class methods, they will
just be ignored. This behaviour is
due to performance reasons, since
after_initialize and after_find will
both be called for each record found
in the database, significantly slowing
down the queries...
So that means that the macro-style usage is inefficient versus the method-style way?
(I guess the guide is wrong, 'cos code is king :D)
Another Update
A commit here from January 28, 2011, suggests that the correct way is still to use the macro-style call, not a def after_initialize.
The call backs should be used as macro style in your model: http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

rails3 gem: acts_as_something

I'm trying to extract some common code into a gem.
I'm thinking that acts_as_somethingis a good strategy for simple re-use.
Is there a good tutorial that discusses this for rails3 gems? I've found several that discuss rails2 (such as http://guides.rubyonrails.org/plugins.html) but that is specific to rails2
here are some of the tutorials/blogs I've already read:
http://guides.rubyonrails.org/plugins.html
http://www.thoughtsincomputation.com/categories/coding-gems-for-rails-3-tutorials (this is an excellent start but doesn't cover the act_as_* issue or controllers)
thanks
UPDATE: I've added a blog post based on this answer, but with much more detail: http://thoughtsincomputation.com/posts/coding-an-acts_as-gem-for-rails-3
--
I'm not aware of another tutorial source off the top of my head, but here are some general tips.
Rails 3 makes use of a really useful feature called Railtie - see http://api.rubyonrails.org/classes/Rails/Railtie.html .
So, if I were implementing an acts_as_* gem, I'd start there. My railtie might look something like:
# lib/acts_as_awesome/railtie.rb
require 'rails'
require 'acts_as_awesome'
module ActsAsAwesome
class Railtie < Rails::Railtie
config.to_prepare do
ApplicationController.send(:extend, ActsAsAwesome::Hook)
end
end
end
and the ActsAsAwesome::Hook code:
# lib/acts_as_awesome/hook.rb
module ActsAsAwesome::Hook
def acts_as_awesome(*args)
options = args.extract_options!
# do the things that make the controller awesome.
include ActsAsAwesome::InstanceMethods
before_filter :an_awesome_filter
end
end
I feel the concepts here are sound and have used similar processes before. Basically, it would tell Rails to execute the to_prepare block once during production and before each request in development (we want that because ApplicationController will be reloaded at those times, potentially wiping out our hook method); and the hook is just that: it adds a hook to all controllers (or rather, all controllers that extend ApplicationController) to allow the user to introduce the real "Awesome" code into their controllers without otherwise affecting controllers that don't need it.
The #acts_as_awesome hook doesn't, in itself, convey the Awesome functionality. That's because not all controllers might need this functionality. Instead, the method is responsible for introducing the real awesome stuff, via the ActsAsAwesome::InstanceMethods module. This way, the user only gets the Awesome functionality if they explicitly call the acts_as_awesome method. It also adds a before filter to the controller to demonstrate that the code in this method would be evaluated exactly the same as if it were in the target controller class itself.
This technique should work exactly the same if you're targeting models instead of controllers: just inject your hook into ActiveRecord::Base. As AR:B is only loaded at Rails boot, you should probably be able to put that into an initializer (refer to the Railtie docs), but I reserve the right to be mistaken here.
A gotcha concerning the railtie: the documentation reads as if it should have been autodetected, but I often have problems with this. To get around it, simply require the railtie from your gem's main source file (in the above example, that would be lib/acts_as_awesome.rb).
You can see the entire ActsAsAwesome source in all its glory at my github account:
http://github.com/sinisterchipmunk/acts_as_awesome
I hope this is helpful. Your question was somewhat high-level so a high-level response is the best I can do.
-Colin MacKenzie IV
http://thoughtsincomputation.com
#sinisterchipmnk

Best way to implement try catch in php4

What is the closest you can get to a try-catch block in php4?
I'm in the middle of a callback during an xmlrpc request and it's required to return a specifically structured array no matter what.
I have to error check all accesses to external resources, resulting in a deep stack of nested if-else blocks, ugly.
Late answer, I realise, sorry. I hope this is still relevant for you:
First, I'm echoing the comments your got in response to your post. PHP5 is the way to go.
However:
I'm in the middle of a callback during
an xmlrpc request and it's required to
return a specifically structured array
no matter what.
If you can vouch for that the program cannot possibly continue without getting a structured array back, and you absolutely have to work with PHP4, then an exit() or die() with detailed error information will get you much the same effect as a fatal exception would.
That's far removed from being graceful, of course. If you want something catchable, then return values and if-checking the result are your best bet, unfortunately. There are some standard ways of passing back specific error objects, but it's still the same thing - return the error object, if-check whether the result was an error object, react.
Still, take a look at PEAR's error object.