Multiple controllers with a single model - ruby-on-rails

I'm setting up a directory application for which I need to have two separate interfaces for the same Users table. Basically, administrators use the Users controller and views to list, edit, and add users, while non-admins need a separate interface which lists users in a completely different manner. To do this, would I be able to just set up another controller with different views but which accesses the Users model?
Sorry if this is a simple question, but I've had a hard time finding how to do this.

Why not put the admin part into a separate namespace - you would have Admin::UsersController with views in app/views/admin/users/. And your users would go to UsersController with its own views in app/views/users/.
The routing is defined like this:
map.namespace :admin do |admin|
admin.resources :users
end
map.resources :users
And can be got to via admin_users_path and users_path

Related

Two different show views for restful resource in rails

I have a job app with two kinds of (not-authenticated) users, referrers and candidates.
Currently I have 1 jobs controller and model.
Basically, I want to have two routes:
job/1 # jobs#show for referrers
j/1 # jobs#show for candidates
Both routes are public, there are no logged-in users.
While the model data (=content) is very similar for the two routes, the views are obviously different. I am struggling to create two different show views within the same controller.
I have looked at setting up a separate namespace (seems to be for the entire controller), specific get routes or setting up a separate controller, but really not sure what the best "Rails" way is.
Any suggestions would be really helpful, thanks in advance!
I see 2 options:
1) Create a separate action in your controller
def referrers
end
def cadidates
end
get '/j/:id' => 'jobs#cadidates'
get '/job/:id' => 'jobs#referrers'
This requires two new views with the actions. In your job views folder add two files: candidates.erb and referrers.erb. You can there adjust the view for each.
2) You can nest the resources
resources :job do
member do
get :referrers, :candidates
end
end
You would have to define a new model and create joint tables where both referrers and candidates are defined as users but part of different table referrers and candidates respectively.
In your JobsController create two different methods. Say
def referrers
end
def cadidates
end
Now in your routes.rb add newly created methods as like,
get '/j/:id', :to => 'jobs#cadidates'
get '/job/:id', :to => 'jobs#referrers'

RESTful actions specified in Users controller AND Devise?

So I'm running Rails 4, just made a barebones application and a User model with Devise. I also ran a migration to add a name attribute to the User model. I also generated a Users controller, as I want to be able to have a Users index page, where all Users are listed. If I specify resources :users in my routes.rb, then what do I do about methods like create in my Users controller, which are already handled by Devise? (I'm aware that this is a rather open-ended question, but some direction would be much appreciated.)
Thanks.
You only need the index action in your user controller.
You can do resources :users, :only => [:index] in your routes.rb file.

How to structure nested resources - Rails

In my Rails 4 app, an admin can moderate/approve posts, user accounts, and photos. I already have controllers for each of these (PostsController, UsersController, PhotosController) that handle the basic CRUD operations initiated by the user.
Having the update method for each controller seems incorrect and ... dirty. So does creating a single ModerationController with non-RESTful methods for each of the models.
I think I need something like a ModeratePostsController for each of the models, but I'm not sure how that gets scoped (under /admin?) or nested in routes.rb and generated as a controller.
Thoughts?
I was pretty much there.
I ran rails g controller Admin::Posts to create /app/controllers/admin/posts_controller.rb and in the routes file I added:
namespace :admin do
resources :teams
end

Rails - CRUD for user and admin, how many controllers?

My model holds expenses, including user and project references..
class Expense < ActiveRecord::Base
attr_accessible :amount, :expense_date, :description, :project_id, :user_id
belongs_to :project
belongs_to :user
end
The ExpensesController handles basic CRUD operations for the expenses.
I now am needing to build an administrators version of this same page, a new view preferably, which can include the different views of the data, by user, by project, etc, and can also edit data that the user cannot.
My question is: Do a build a second controller to handle the administrative perspective of the data, -- or do I setup conditions inside of every method, to detect the originating view and form, and then conditions to redirect them back to where they belong?
If I do build a second controller, how do I properly setup the form_for so that it knows what controller to go to?
Thanks!
PS - If anyone has any books about how to properly put together a rails app, I feel like I know the pieces ant parts, but I'm getting stuck on the big picture implementation. I learned rails with Michael Hartl's guide, prior to that I was a PHP developer.
IMHO, if security is a big concern for your app then using an admin namespace and separate controllers is the best way to make sure you don't leave any gaps. It's also just simpler and lower stress.
I would have a directory structure like so:
/app/controllers/application_controller.rb
/app/controllers/admin_controller.rb - inherits from application_controller
/app/controllers/expenses_controller.rb - non-admin, inherits from application_controller
/app/controllers/admin/expenses_controller.rb - inherits from admin_controller
Your views would be similarly separated/duplicated:
/app/views/expenses/* - non-admin expenses views
/app/views/admin/expenses/* - admin expenses views
In application_controller you'd put the Devise methods to authenticate_user and CanCan method to check_authorization (which throws an exception if authorization is not checked at some point in the controller action). In admin_controller you have more strict filters to make sure the user is an admin. Then you can get even more fine-grained in the specific controllers and their actions.
Of course each controller only has to define the actions it really needs and you don't have to duplicate views. Maybe the non-admin expenses_controller has index, show, new, create, while the admin one has only edit, update, and destroy. Then in the 'show' view you'd still have code that add links to the 'edit' action if the user is an admin.
Edit - Routes
With the above example, your routes.rb would look something like:
resources :expenses, :only => [:index, :show, :new, :create]
namespace :admin do
resources :expenses, :only => [:edit, :update, :destroy]
end
So you still use expenses_path() for the index and expense_path(foo) for show. A form on the admin page, however, would post to admin_expense_path(#expense).
If you wish to add another Controller I would suggest having common code in a module and importing them in each Controller. Each controller would also have an adequate before filter to check for adequate rights.
But I would prefer having one controller and one set of views since I think it avoids code duplication and/or confusion. Pass the user as a local variable to the view and check for administrator rights when you need to decide the URL for the form_for or whether to hide or show some part.
If the views differ significantly, check for admin rights in the controller and render either the user view or the admin view.
You can even create a special partial for the admin part of the view and decide whether to render it in the view or not, sending the appropriate data in the params or not.
You can use Devise gem for authentication.
You can create somekind of "namespace" for administrative part of your application.
I my opinion, creating another controller depends on how many views and actions your admin will access.
About the doubt about form_for action, it will be managed by your routes and paths that you configure in your form_for params.

Rails RESTful website vs user experience and less clicks

Situation: I have a team model, a user model and a teamate model for the users of a team.
Say I want to have a view that contains the information of a team team/show
and that I wish (to simplify the user's experience) to add a list of the users, an add user to team and the possibility to remove a user from that team.
To be perfectly restful, I would need a controller (let's call it Teamates), it would handle the users of a team.
I would have all the CRUD needed.
Is it clean to have the team/show view call the teamates controller for the following actions: adduser, removeuser, listusers.
What I am trying to achieve is less clicks for the users.
In other words, I would like the user to be able to manage the users of a team from the team view instead if requireing him to navigate even further.
I don't think you need a controller for teamates.
And you really should not have adduser/removeuser/etc actions in your team controller!
You could set up your routes like that:
resources :teams do
scope :module => "team_scope" do
resources :users
end
end
Then you would have a UsersController in app/controllers/team_scope/users_controller.rb
To create a new user for a team, you would post to: /team/1-team-a/users and it would hit the create action in the UsersController above.
When you use scope in your routes, it does not change the route helpers like with namespace. The new action would just be accessible via new_team_user_path(#team).
Hum... so yeah, in this case I would have a TeamatesController, and maybe set up my routes like that:
resources :teams do
resources :teamates, :only => [] do
collection do
get :edit
put :update
end
end
end
And then you could edit the associations between a team and its players...
Your form would post the users id to team_teamates_path(team)...
But I'm really not sure it's the best way, I'd have to think about it. This is not really restful as well.

Resources