Need help with a code smell
In my Rails application I'm trying to make the controllers skinnier and am having difficulty with one object that I keep having to pass around.
The object represents a user's facebook session and is instantiated off of the session so it exists in the controller side of things. Many model methods use it, so it is repeatedly passed in as an argument all over the place.
开发者_开发知识库This smells like something, how to DRY it up the Rails way? Thanks!
First, I would recommend using a system similar to Authlogic for your authentication. This gives you two bonuses:
- You have proven, stable, tested authentication for your application
- The sessions are based like Models, so you can do this kind of stuff...
class Widget < ActiveRecord::Base
def do_facebook_stuff
UserSession.find #This gets you the current session
UserSession.find.record # This gets your the user for the current session
end
end
Now you no longer need to pass the session information in, as you can do basic model-style lookups to find it. In addition to this, Authlogic has a plugin architecture that supports Facebook Connect, which may help you further.
I can give you the CakePHP way (which was originally designed to be like rails).
All CakePHP models extend the same parent AppModel, and all controllers extend an AppController.
I would make an empty parameter in the AppModel that represents your object. Then in the AppController I would store the object in the current model's parameter, if the object exists. There is a callback in the CakePHP AppController called beforeFilter() which fires before any code in the controller. The ideal place to check for the object and store it in the model would be in whatever equivalent Rails has of this beforeFilter callback.
That is unless all models don't use the object. If that is true, you could put the parameter in only the Models that use it (instead of the parent), and then in the beforeFilter of the AppModel you can check first if the Model has that empty parameter.
I know it's not Ruby, but it would look like this:
public function beforeFilter() {
if (isset($this->{$this->modelName}->yourObjectParameter)) {
$this->{$this->modelName}->yourObjectParameter = $this->yourObject;
}
}
$this->modelName
is a string that corresponds to the name of the current model. the { }
around $this->modelName
in PHP is called complex syntax. It basically converts the string into the model object. Not sure how to do the same thing in Ruby.
You can take your method to application controller, something like this
class ApplicationController < ActionController::Base
before_filter :get_facebook_session
def get_facebook_session
@facebook_session = <your code >
end
end
And you can access @facebook_session variable from your controllers and views
cheers
sameera
精彩评论