Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confused about nested resources and authentication in Rails

Let's see if I can explain myself well enough about the doubts I have.

I have a User model that is managed by Devise. So in my routes I have:

devise_for :users

In the User model, I have an association with the model Plan. The assocation is:

User has_many Plans
Plan belongs_to User

At this point I also have a resource for the Plan model, so I can fetch all the Plans, show a particular plan and so on. But I want to go further.

I want to be able to see plans of a particular User and let a particular User to see his own plans and edit them.

So, for example, whenever I go to:

/users/:id/plans

I want to be able to see the plans for that particular :id user. And if the user who is visiting that url is the one that is logged in, I want him to be able to edit those plans.

How can I manage all this behavior? Is there any gem out there that helps with it? Or I need to do conditionals in the views saying if current_user...

like image 605
Hommer Smith Avatar asked Dec 30 '12 12:12

Hommer Smith


People also ask

What are Nested resources?

Nesting resources provide REST API consumers an easy and efficient way to manage data by allowing the consumer to send and receive only the required object. The nested resource must be a business object, that is, it must still represent a complete business object.

What is resource in devise rails?

"Resource" is basically a substitute for the name of the users that app developers will utilize in the future. Devise doesn't care what users are actually called: no matter what it is called, to devise, your users will be known as simply "resource".


1 Answers

Let's start with routes, you can make your routes like this:

resources :users do
  resources :plans, only: [:index]
end

resources :plans, except: [:index]

I used resources :plans inside resources :users to have route like this /users/:user_id/plans, while the resources :plans outside is for the rest of the actions (edit, destroy, ...) that don't require a user_id, i.e., a plan is identified by a unique id so you don't need a user_id to fetch it from the db for editing or destroying.

Now for the controller, we can make it like this:

class PlansController < ApplicationController
  before_filter :is_plan_owner?, only: [:edit, :update]

  def index
    @plans = Plan.where(:user_id => params[:user_id])
  end

  def edit
    @plan = Plan.find(params[:id])
  end

  private

  def is_plan_owner?
    if current_user != Plan.find(params[:id]).user
      # Scream, shout, call 911 and/or redirect else where
    end
  end
end
like image 180
Ahmad Sherif Avatar answered Sep 30 '22 08:09

Ahmad Sherif