SitePoint Sponsor

User Tag List

Results 1 to 15 of 15
  1. #1
    SitePoint Evangelist
    Join Date
    Apr 2005
    Posts
    485
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    [Rails] Rails App Structure

    hi all,

    i'm reading the agile web dev with rails book and they have a single admin page and create a single controller to support it.

    that's easy enough.

    how do i structure the controller if i want two admin type pages - one to enter customer information and a second one to enter product information (two is an example, it could be many more)?

    do I do one controller for each? will the app get unwieldy working with a large number of controllers?

    if it is one controller, how is the second scaffold set up?

    tia...

  2. #2
    SitePoint Guru Majglow's Avatar
    Join Date
    Aug 1999
    Location
    B-Town
    Posts
    645
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I would personally use two controllers since each controller would hold a number of actions (usually a minum of 4 for CRUD). On top of that, if I spice up the application, a lot more actions can show up, so it's best to keep it seperate.

    Now, the trick to preventing an unwieldly number of controllers is to use namespaces. Usually I will put the whole admin panel in it's own namespace, if users have account sections I put that in a name space and sometimes I even put the bulk of the site in a third name space (of course it all depends on the structure of the site.

    Anyway, if you don't know what namespaces are, I would suggest looking it up in a ruby book. As for how to do it with rails:

    Code:
    ruby script/generate controller Admin/Products
    Trust me, once you get the hang of rails in general, you will want to really be able to use namespaces with controllers. It helps organization a LOT especially since you can have "application" controllers for each namespace and write filters there that will be inherited by all the sub class controllers, for example:

    Code:
    class Admin::ApplicationController < ApplicationController
      before_filter :authenticate_admin
    
      private
        
        def authenticate_admin
          redirect_to homepage_url unless current_user.administrator?
        end
    end
    then your admin products controller

    Code:
    class Admin:ContactsController < Admin::ApplicationController
    
      # Your stuff here
    
    end
    and that controller is already checking for administrator priviledges. It's all about DRY.
    Ohai!

  3. #3
    ☆★☆★ silver trophy vgarcia's Avatar
    Join Date
    Jan 2002
    Location
    in transition
    Posts
    21,235
    Mentioned
    1 Post(s)
    Tagged
    1 Thread(s)
    I would just build single product and customer controllers, then restrict access to certain actions (i.e. edit, update) with before_filters. Example:
    Code:
    class ProductsController < ApplicationController
      # read-only access for everyone but admins
      before_filter :admin_required, :except => [:index, :show]
      
      #...CRUD methods here...
    
      protected
      #before filter
      def admin_required
        #pass a warning message to the unscrupulous user, then redirect
        if !current_user.admin?
          flash[:warning] = "You can't do that!"
          redirect_to :action => 'index'
        end
      end
    end
    Then only make edit/destroy/new links available in views to users with the right credentials.

  4. #4
    SitePoint Evangelist
    Join Date
    Apr 2005
    Posts
    485
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by vgarcia
    I would just build single product and customer controllers, then restrict access to certain actions (i.e. edit, update) with before_filters. Example:
    Code:
    class ProductsController < ApplicationController
      # read-only access for everyone but admins
      before_filter :admin_required, :except => [:index, :show]
      
      #...CRUD methods here...
    
      protected
      #before filter
      def admin_required
        #pass a warning message to the unscrupulous user, then redirect
        if !current_user.admin?
          flash[:warning] = "You can't do that!"
          redirect_to :action => 'index'
        end
      end
    end
    Then only make edit/destroy/new links available in views to users with the right credentials.

    vg, so you'd have one admin controller and then create dmethods for each of the admin tasks while controlling the CRUD functions as shown above?

    tia...

  5. #5
    ☆★☆★ silver trophy vgarcia's Avatar
    Join Date
    Jan 2002
    Location
    in transition
    Posts
    21,235
    Mentioned
    1 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by skeeterbug
    vg, so you'd have one admin controller and then create dmethods for each of the admin tasks while controlling the CRUD functions as shown above?

    tia...
    If I can get away with it I wouldn't even have the admin controller. I'd rather build most admin functionality right into the main interface and hide it from non-admin privileged users.

  6. #6
    SitePoint Evangelist
    Join Date
    Apr 2005
    Posts
    485
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by vgarcia
    If I can get away with it I wouldn't even have the admin controller. I'd rather build most admin functionality right into the main interface and hide it from non-admin privileged users.
    vgarcia, so your vote is for one controller for the whole app?

    if so, what criteria do you use for generating a 2nd controller?

    tia...

  7. #7
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    One controller should do one thing. Admincontrollers are generally a bad idea because it's much more elegant to create a controller for one table.

    Not posts & admin/posts, but simply posts. This posts controller has show/list/destroy/etc. This is better because of this: say you have a posts controller. Only admins may post posts. Visitors may view posts. Say you have a posts controller for the visitors and an admin/posts controller for the admins. Now you add a comments controller. The rules for this controller aren't the same as for posts: visitors may post comments, admins may appove comments (controller: admin/comments). Now say you want to have special rules for registered-users. The comments that these users post do not have to be approved. Are you going to add a new controller for these users? (registered_users/comments). It's much better to have two controllers: posts and comments and handle the authorization in the specific methods. All code that handles comments is in the comments controller now.

  8. #8
    SitePoint Evangelist
    Join Date
    Apr 2005
    Posts
    485
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Fenrir2
    One controller should do one thing. Admincontrollers are generally a bad idea because it's much more elegant to create a controller for one table.

    Not posts & admin/posts, but simply posts. This posts controller has show/list/destroy/etc. This is better because of this: say you have a posts controller. Only admins may post posts. Visitors may view posts. Say you have a posts controller for the visitors and an admin/posts controller for the admins. Now you add a comments controller. The rules for this controller aren't the same as for posts: visitors may post comments, admins may appove comments (controller: admin/comments). Now say you want to have special rules for registered-users. The comments that these users post do not have to be approved. Are you going to add a new controller for these users? (registered_users/comments). It's much better to have two controllers: posts and comments and handle the authorization in the specific methods. All code that handles comments is in the comments controller now.
    thanks for the reply. these concepts are new to me, so let me see if i can apply them to my application. rails creates the crud functionality for you within a controller, so the thought process is that one should create a controller for each table. so, if i have "enter clients" and "enter tranacations" functionality, each would have its own controller and associated crud mechanism.

    so, if i have 10 tables to enter data into and each rquires its own data entry form (and associated crud), i'm looking at 10 controllers, right?

    however, if i start stacking multiple permission levels to do what the controller does (eg, enter clients), then i don't need an additional controller, rather, i need to roll the authentication information into the same controller.

    is that about it in general terms?

  9. #9
    SitePoint Guru Majglow's Avatar
    Join Date
    Aug 1999
    Location
    B-Town
    Posts
    645
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I still disagree with adding admin functionality to the main controllers because it can quickly become unmanageable.

    In all my projects I've found the following:
    * Main site controller functionality and and Administration controller functionality can differ widely.
    * The filters required for admin pages are the same and the filters required for the main site are (mostly) the same.
    * There usually are more than just the simple CRUD methods in the controller.
    * Functional test files will be a lot longer than the actual controller files.
    * The main site rarely mirrors 1 controller per table.

    To me, all these factors combined indicate that it is better to separate the admin controllers and the main site controllers.
    Ohai!

  10. #10
    SitePoint Evangelist
    Join Date
    Apr 2005
    Posts
    485
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Majglow
    I still disagree with adding admin functionality to the main controllers because it can quickly become unmanageable.

    In all my projects I've found the following:
    * Main site controller functionality and and Administration controller functionality can differ widely.
    * The filters required for admin pages are the same and the filters required for the main site are (mostly) the same.
    * There usually are more than just the simple CRUD methods in the controller.
    * Functional test files will be a lot longer than the actual controller files.
    * The main site rarely mirrors 1 controller per table.

    To me, all these factors combined indicate that it is better to separate the admin controllers and the main site controllers.
    Maj, my admin duties include several tables. i think i'm going to end up with admin_client_controller.rb, admin_transaction_controller.rb... for all my admin tasks. of course, i'll work through my application interface and try and divvy up the controllers in a rational way, too.

    does this sound about right?

  11. #11
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If you have a separated admin/visitor (visitors mostly view data, admins enter data) you should definitely try Django: it generates the admin area for you.

    Could you give more information about your database structure and who does what (do admins enter data, or users too, for example).

  12. #12
    SitePoint Evangelist
    Join Date
    Apr 2005
    Posts
    485
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Fenrir2
    If you have a separated admin/visitor (visitors mostly view data, admins enter data) you should definitely try Django: it generates the admin area for you.

    Could you give more information about your database structure and who does what (do admins enter data, or users too, for example).
    for better or worse, i'm going RoR. learning php and ruby have been difficult enough. jumping to python now just isn't realistic.

    i'll have a contacts (and entry form) and a transactions (and entry form) table. i may also have a clients (and entry form) table. if i decide to store emails in a db, i'll also have an email table, but information there will be entered automatically by the program. i'm probably going to use files to track correspondence, though. i'll likely end up with a couple more tables that i don't know about yet.

    one person will enter the data and multiple people will view it to check on the status, important dates, checkoff list, etc. my guess is that there will be multiple pages that need viewing and those pages will likely need their own controller unless i can elegantly combine them in some rational way.

  13. #13
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I would code 3 controllers: contacts, transactions and clients. I don't know how similar the admin functionality of these controllers will be. If the difference isn't very big you could write a macro/procedure that defines the basic crud for you. This is like scaffold() but it could do things that scaffold doesn't do. It could for example add filters to protect the new/edit/update/create/destroy actions.

    Now your controllers look like this:

    Code:
    class ClientsController
      admin :clients # this is the macro/procedure you wrote
    end
    admin :clients produces this:

    Code:
    class ClientsController
      def new; ... ; end
      def create; ... ; end
      def edit; ... ; end
      def update; ... ; end
      def destroy; ... ; end
    
      # and it protects them with before_filters:
    
      before_filter :authorize, :only => [:new, :create, :edit, :update, :destroy]
    
      def authorize
        if the_logged_in_user.admin?
          # continue
        else
          # display not authorized page
        end
      end
    end
    Now you have a nice controller structure and dry+easy code. (you reuse the admin() macro for the other controllers)

  14. #14
    SitePoint Evangelist
    Join Date
    Apr 2005
    Posts
    485
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Fenrir2
    I would code 3 controllers: contacts, transactions and clients. I don't know how similar the admin functionality of these controllers will be. If the difference isn't very big you could write a macro/procedure that defines the basic crud for you. This is like scaffold() but it could do things that scaffold doesn't do. It could for example add filters to protect the new/edit/update/create/destroy actions.

    Now your controllers look like this:

    Code:
    class ClientsController
      admin :clients # this is the macro/procedure you wrote
    end
    admin :clients produces this:

    Code:
    class ClientsController
      def new; ... ; end
      def create; ... ; end
      def edit; ... ; end
      def update; ... ; end
      def destroy; ... ; end
    
      # and it protects them with before_filters:
    
      before_filter :authorize, :only => [:new, :create, :edit, :update, :destroy]
    
      def authorize
        if the_logged_in_user.admin?
          # continue
        else
          # display not authorized page
        end
      end
    end
    Now you have a nice controller structure and dry+easy code. (you reuse the admin() macro for the other controllers)
    fenrir, how does admin :clients produce that code? do i need to code in an admin :clients file? tia...

  15. #15
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Rails uses module_eval:

    Code:
    class ApplicationController
      def self.admin(model)
        module_eval <<ENDCODE
    def show
      @#{model} = #{model.camelize}.find(:all)
    end
    
    ...
    
    ENDCODE
      end
    end


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •