Dedicated controller? How to structure admin feature? - ruby-on-rails

Is it better to extend my users controller to include administrative task on other nested controllers?
Or create a 'profile' controller where I could create different actions and views that summarize admin actions.
Scenario A:
"/users/current/" : would show a link to edit products user own.
"/users/current/products" - Products controller would detect if it is accessed as a nested ressources. If so, would show all user products and edit links to product. In that case, the view would have to be completely different if it is access as nested ressource or not.
Scenario B:
"/profile/" : would show a link to edit products user own.
"profile/products" : products would be an action in profile controller that show all products own by the user with links to edit those products on products controller.

I do find it helpful to separate admin actions from a end-user actions, so I would lean towards the "/profile/" scenario.
But really, it's a matter of personal taste. Just decide which structure you'll most easily recognize in 6 months, when you've forgotten where everything is. Also take into consideration which structure will become less cluttered if you should ever start adding more features (actions) to those controllers.

Related

Controller logic for two different type of users

In my project i have three different categories of users:
Guest
Registered
Admin
If a Registered user is logged in, I want to show them (if they click on a button) their orders.
The Admin instead can see the orders of all the users. I can use OrdersController to show things to the Registered user.
Is it necessary to create a new controller for the Admin , or I can use a if the user is a admin do this clause in the same controller(say OrdersController) that I use for the Registered users?
There's no single right answer to this question, it really depends a lot on your code, your app, your use cases, and a whole bunch of other detail that you haven't provided (and that this is not the best forum for).
So, generally the administration tasks are so distinct from the regular users that people create new controllers for them, usually under their own Admin:: namespace.

Best practice when developing an RoR application

I am currently creating an application. It's relatively simple, lets say for now it only contains users & posts
What I am trying to do is display basically a blog with a new post form at the top in case the signed in user is admin.
I have two options:
I can use an index for posts and keep it all within the posts controller. I could add a form to the index.html.erb which checks for admin attributes.
However, I will most likely use the index functionality later on in other parts of the app.
Second option would be to create a static page called blog and render the form view and all posts.
Both should be possible, but what is the "rails way"? Or is there no best practice?
Controllers should be RESTful, and should be appropriately named for the resources they manipulate.
The index action of your PostsController should have one purpose ... providing appropriate information relating to all of the posts to its view. The exact output of this could change within the view depending on whether you're logged in as an admin or not, but essentially the role of that action should be restricted to that function.
I would advise you to take a look at the CanCan gem and think about how you could use that to authenticate users, providing appropriate page content to admins and normal users alike.

Rails polymorphic association - controllers and views?

I have a model User (used for authentication purposes) which is connected to two other models, Customer and Seller via polymorphic association in Rails. A customer and seller must have different sign up forms because of their different data but can use a single login form because they're both Users. In order to manage the customer and seller resources separately, is it a good idea to create respective controllers and views for them, or should management of all Users be done in the UsersController?
It depends upon the design of the two views customers and sellers. If the design of both the views are different then I will encourage you to create two controllers customers_controller and sellers_controller and you may want to have a module for common actions like lib/authentication.rb.So
# customers_controller.rb
include Authentication
def some_action
end
and
# sellers_controller.rb
include Authentication
def other_action
end
Authentication file like
# lib/authentication.rb
module Authentication
def common_method
end
end
You can have two controllers and one module which you can write common methods/actions
As #madyrockss pointed out, STI is probably the way to go here because User.find(params[:login]) will return either an instance of Customer or Seller automatically.
I would encourage forgetting about the UsersController and views and encourage thinking in terms of seller and customer controllers/views (that is, don't share a single controller and views per action that can handle either customer or seller and has conditionals within view determining what to show). If the two users have different business rules, the whole thing starts to get messy real quick and becomes unwieldy to manage as business rules change.
For login/logout, if the form is going to be the same for both, then a single controller will suffice and I'd consider a different name than UsersController, such as SessionsController to be more semantically in line with what the controller's purpose is. You are not confined to a one-to-one Models <==> Controllers <==> Views which many beginning Rails developers fall into the trap of.

Rails application with multiple roles

I have a rails application with 2 roles, say admin and user. But the thing is, The admin doesn't use a backend like ActiveAdmin for example. I want both Admin and User to see the same views, but depending on the role, I restrict what they can see. I'm using Cancan, but since for example both admin and user can see the product page, I end up with many conditions inside the view and controller actions stating for example if this is an admin show that, if not then show that instead.
So I don't really think that this is the "Rails way". I end up with many repeated code, and code inside the views which doesn't really support the idea of keeping the logic away from the views.
So my question is, What's the best way to implement such a scenario with many roles but the same views.
Thank you.
I'm thinking of two options currently, but I don't like either. One is to redirect the admin to another view, but this way most of the view is the same hence it's not DRY at all.
Option 2 is to use the exact same view, but add many conditions in the view, so I end up with a huge complex view with code. I'm trying to find a way that keeps things DRY yet simple, and keeps the views code free.
You can have the admin module under seperate namespace and users as the default namespace. You can extract the common code under partials and use the same in both admin and user module.
This way you can separate the code for user and admin, and if sometime in future if you decide to go for a different views for admin and user. It won;t be much of a task.
Have controllers as
app/controllers/admin/articles ------ for admin users
app/controllers/articles ---- for normal users
and
views
app/views/admin/articles
app/views/articles
app/views/shared
There are different possible approaches. A variation of the 'decorator' pattern would come to mind as described here
It's some time I last read it, but I think the basic idea is to put the logic in the model or helpers. As soon as a user logs in and you can see if he is an admin or normal user you have methods that return the necessary html or text.
A more simple approach would be to just have two partials for everything. Either as Ross says in a separate admin namespace or even simpler (but more work if you later need to change that) just like _user_view_something.html.erb and _admin_view_something.html.erb.
Somewhat similar thoughts go into the DCI pattern. This Blog gives some nice overview how this could play into Rails. The article is more about permissions, but again the basic idea is to supplement the user object with the necessary functions.
So you have the basic "do_something" method which renders something or places some information in the view and replace it with the one that fits to the role the actual user has.

Use nested controller or declarative authorization for admin action?

Say, I've an app with multiple models:posts, blogs, todos etc and I want an admin to edit, delete all users posts, blogs, todos, do I create a nested admin controller for each or use declarative authorization to setup an admin account that can edit/destroy the users, posts etc?
I understand this has no right answer, I'm just looking for the easiest and DRYest way to do it.
Thanks
Declaritive authorization is completely different thing from how you organize your admin situation. These are not different alternatives for the same problem. How you authorize actions or perform access control has nothing to do with whether your admin interface uses nested controllers and a different interface or uses the same interface as regular users with a few more buttons.
That said I'll take a stab at what I think you want to ask: Should your admin interface be the same as your user interface but with a few more buttons for admin actions?
My answer would be no even for the simplest of sites. Imagine having to clean spam from each and every post on your blog by having to visit each and every post.
Now imagine if you had a table of comments by date.
Which would you prefer?
Now if you decide your admins deserve a custom interface that suits their needs then you need to ask if it should be nested.
I'm not exactly a rails expert, but I thought this article was good: http://www.contextualdevelopment.com/articles/2008/nested-controllers-and-resources It points out some advantages of using the nested controller thing in the admin context you are describing.
If I understand right, in both cases you need an user with an admin role, right? So probably it's more about how to structure the controller. The nested controller setup imho is a bit cleaner because it saves a couple of conditions in the "main" controller. You simply put everything "admin" into the nested controller and everything else in the main controller.

Resources