More on RestController and some updates 2

Posted by Tim Connor Fri, 20 Apr 2007 18:58:00 GMT

I’ve fleshed out RestController, through some more usage. Combined with moving associated object creation into the model, it now really DRYs out my code, by being a little more flexible.

On any overridden action you can call super, passing in an option options hash. The current options are :template, which works for the editing template for errors on update and create and :find_options, for sorting the index view, for instance. As well, the instance variables (@page_title and @your_model_name) are set with ||=, so you can do custom init and then call super.

Well a picture is worth a thousand words, so, here are the public methods, using all of these techniques, from my most complicated controller on a project using it:


def index(options = {})
super ({:find_options => {:order => ‘date DESC’}}.merge(options))
end

def public_index @page_title = ‘Sun Valley Fishing Report’ @body_class = ‘archive’ index :template => ‘public_index’ end def current @report = Report.current @page_title = ‘Latest Sun Valley Fishing Report’ public_show end def public_show @report ||= Report.find_by_date(params[:date]) @page_title ||= ‘Sun Valley Fishing Report’ render :text => ‘No report found’, :layout => ‘public’ and return unless @report show :template => ‘public_show’ end def new @report = Report.new() Location.find(:all).each { |location| @report.conditions.build(:location => location) } super end def edit @report = Report.find(params[:id]) Location.find(:all).each { |location| @report.conditions.build(:location => location) unless @report.locations.include?(location) } super end

Most of the other controllers ones are a couple of lines, maybe over-riding one action. For instance, here is my UserController, and even this might be simplified when I add in an error condition on edit and show (and/or an passed in error handling block):


class UsersController < REST::RestController
def edit
user = User.find_by_id(params[:id]) unless @user flash[:notice] = @messages[:editing_invalid_id]
redirect_to users_path and return
end
super
end
end

UPDATE: Same day – I updated again, and now I can empty out that user controller, because the edit and show actions have basic checks for not found.

Dynamic-Scaffold-Resource is dead, long live RestController 4

Posted by Tim Connor Tue, 03 Apr 2007 18:39:00 GMT

I got tired of the complexities of my plug-in solution to DRYing up the shared code in all my Restful controllers, and scaffolding gets no love from core. But after a little while I got almost as tired of having the same 7 methods repeated throughout my code base. Thus a new simpler project is born: RestContoller.

Instead of scaffolding your views (which the core team is right about – those should diverge widely to fit the UI needs) or adding tests for you, it just gives you a main rest controller to inherit from that has the 7 basic actions (index, show, new, edit, create, update, and destroy). I was also able to simply further and drop the giant block eval, by looking over Jake Howerto’s CRUDController and borrowing a technique or two (such as the use of instance_variable_set). This should make the code easier to follow, customize, and also more performant.

You can just do a vanilla checkout from Google Code, and then inherit from that.


svn checkout http://restcontroller.googlecode.com/svn/trunk/ app/controllers/rest
class YourModelController < REST::RestController

but with this new approach it’s much more natural to customize per project. You can just go ahead and grab the file, save a local copy, check it into your own source control, and do with it as you will. For instance, if all of your resources have a public facing front, but the rest should be restricted, just add something like this (as well as the appropriate function in your application.rb)
before_filter :require_login, :except =>[:show, :index]