My question is about controller methods (possibly included from an outside class) that work with instance variables. I frequently use a before_filter in controllers to set up certain variables, e.g.:
class DocumentController < ApplicationController
before_filter :fetch_document
def action
@document.do_something
end
private
def fetch_document
@document = Document.find(params[:id])
end
end
I’ve been working on a project in which a few controllers will share some functionality, say, document editing. My first thought was to extract the relevant methods, and get them from application_controller.rb or a separate module. But then I noticed I was writing code that looks like this:
def fetch_document
@document = Document.find(params[:id])
end
def do_something_to_document
@document.do_something
end
This sets off warning bells: do_something_to_document is essentially assuming the existence of @document, rather than taking it as an argument. Is this, in your sage opinions, a bad coding practice? Or am I being paranoid?
Assuming it is an issue, I see two general approaches to deal with it:
-
Check for the instance var and bail unless it’s set:
def do_something_to_document raise "no doc!" unless @document [...] end -
Call the action with the instance var as an argument:
def do_something_to_document(document) [...] end
2 looks better, because it hides the context of the calling object. But do_something_to_doc will only be called by controllers that have already set up @document, and taking @document as a method argument incurs the overhead of object creation. (Right?) 1 seems hackish, but should cover all of the cases.
I’m inclined to go with 1 (assuming I’m right about the performance issue), even though seeing a list of methods referencing mysterious instance vars gives me hives. Thoughts? Let me know if I can be more clear. (And of course, if this is answered somewhere I didn’t see it, just point me in the right direction…)
Thanks,
-Erik
If you really need document in different controllers, I’d do something like this: