different views for the same function

This question is more for future reference after I've made my website, but one thing I've noticed was there was I had to make a lot of functions on the controller, and different views for each one, each with the same functionality. This is very anti-DRY, in my opinion.

So I was wondering, Is there some way to wrap all this up into a single line of code in the controller, and ditto for the views?

I know a bit about partials, but is rather unsure about how to deal with it in a form. How do I display a form partial, giving it different variables each time?

For the controller, I have a few controllers extending off of user (thought the names are different, basically they're the moderators and administrators). Since a user can edit itself, a mod can edit a user, and an admin edit a mod, I have a lot of duplication in methods, just so I can get different views off of each function. Since I'd rather wrap it up in one view for the higher classes, is there some way to wrap this unneeded extra functions using a bit of super() and different validation methods? Must I put edit_self() method in the Application controller?

Taro, if you;re talking about the very common functions for basic CRUD operations on tables then yes, I think there are a few strategies to keep DRY. I can see by reading around that the RESTful approach has some pretty clear guidelines to help with this but I'm not there yet.

What I have found extremely helpful is a strategy of defining a parent class from which I inherit for my classes (controllers) that do concrete work.

So, lets call this controller Crud

class Crud < ActionController::base   bunch of stuff we'll discuss below end

and then my real controllers are

class Concrete < Crud

end

Now in the Crud controller I define some methods, specifically in my case "show", "new", "edit" and "delete" (you can collapse these even further if you wanted but for me this has been a reasonable balance between being succint and being clear.

The next part is to take advantage of Rails consistency in naming. So for a given controller we can deduce the model name. We know it will have an id field as primary key and if we manage our routes consistently then we know our parameters will be consistent. Then if we agree to use a standard instance variable name for our form data we can abstract the entire CRUD process. In my example, @row is what we agree to always be the variable that holds data from the database.

Here's an example for the "show" method:

  def show     if !@row = crud_obj.find((params[:name]) then       redirect_to home_url       return     end     article_render_show   end

crud_obj is the model object related to our controller. It is defined as below.

  def crud_obj     return Object.const_get(class_name)   end

  def class_name     return self.class.name.sub(/Controller/,"")   end

Once you have a way to abstract the name of the model class from the controller class, you can pretty much abstract the entire crud process.

I now have several controllers than have absolutely no code in them whatsoever - they just inherit the methods from this parent class. To create a new class I simply:

1. Create a new class derived from Crud 2. Create the views "show" and "edit" 3. The logic will use "edit" for new and update functions, and "show" for the rest. You could easily decide to use only one view but I find they're often different enough to warrant clear separation.

If you then create a customer form builder you can get a lot of basic functionality built reliably very fast.

Cheers, --Kip

Hi Taro,

Taro wrote:

one thing I've noticed was there was I had to make a lot of functions on the controller, and different views for each one, each with the same functionality. This is very anti-DRY, in my opinion.

So I was wondering, Is there some way to wrap all this up into a single line of code in the controller,

Not sure if this is what you're asking, but you can render whatever view you want from any controller action with :render => 'action'. That will render the view for the action specified using whatever instance variables you've created in the action you're in.

and ditto for the views?

I know a bit about partials, but is rather unsure about how to deal with it in a form. How do I display a form partial, giving it different variables each time?

:locals => {:var_in_form, @var_from_controller,                  etc...}

HTH, Bill

To Bill, Sorry, I was in a rush. I'll try to explain this a little more thoroughly:

Basically, I have user classes set-up as ApplicationController > UserController > ModeratorController > Admin Controller. As you can see, Mods inherits user methods, and Admins inherit Mods methods. The same goes for the Models; User > Moderator > Admin. Right now, my edit methods goes as follows:

Hi Taro,

Taro wrote:

Sorry, I was in a rush. I'll try to explain this a little more thoroughly:

No problem.

Basically, I have user classes set-up as ApplicationController > UserController > ModeratorController > Admin Controller.

Why the chain? I mean, based on what I see below, Moderator and Admin could both inherit from User. Just asking in case there's there some reason you haven't covered here.

Right now, my edit methods goes as follows: --------------------- class UserController < ApplicationController   def edit_self     @user=User.find(params[:user_id])     #check if you're editting yourself.     if params[:user_id]==@user.id       #edit user     end   end end ----------------------- class ModeratorController < UserController   #edit_self is inherited here.   def edit_user     @user=User.find(params[:user_id])     #check if you're editting a user     if @user.class.name=='User'       #edit user     end   end end ----------------------- class AdminController < ModeratorController   #edit_self and edit_User is inherited here.   def edit_moderator     @user=User.find(params[:user_id])     #check if you're editting a user     if @user.class.name=='Moderator'       #edit moderator     end   end end -------------------------

Not only am I duplicating the same code as the class before (with an exception of different validations),

Different validations may be a good enough reason, in fact a very good reason, NOT to try to refactor these into a single, parameter driven, controller method.

I guess the key question I'd have is this. You've shown that you have two redundant lines of code in each method. The '#check if you're editing a ?' line is probably just that'; a line. But what's the level of similarity between the code blocks behind the '#edit something' comments? It would be a pretty straight-forward exercize to put this in application.rb. The question I'd recommend you focus on is 'what would that do to the readability and maintainability of my code'? Refactoring just to reduce lines of code is not, IMO, a good expenditure of effort. Refactor this if you think that you're going to have to make the same change in 3 places every time you make any change. OTOH, if you think you may end up making changes to one but not the others, then let it be 'til you learn more.

but I have to create a separate view for each method!

No you don't. As I said earlier, you can pass your instance variables to any view you want to use to render them. That attempt will also shed light on whether or not your desire to use a single method to process all your user types is really a viable idea.

HTH, Bill