views:

17

answers:

1

Hi Everyone,

I am trying to get to grips with the basics of authentication in Rails. To start with I have used the nifty_authentication generator by Ryan Bates. It's helping me learn the basic options for user logins etc.

I have a simple application the has a person and gift table in the database. The idea is, each user creates a list of people and then assigned possible gifts to each of those people.

So from a structural point of view:

person belongs to user
gift belongs to person

So I have the models set up as follows.

person model

class Person < ActiveRecord::Base
has_many :gifts
end

gift model

class Gift < ActiveRecord::Base
belongs_to :person
end

user model

currently doesn't contain any belongs_to has_many etc.

How do I go about making sure each user has their own list of people. So one user cannot see another users list of people or gifts.

Would I simply add the following to the user model?

has_many :people

and the following to the person model?

belongs_to :user

Would that work, or am I missing something?

Thanks,

Danny

UPDATE: The app so far is on Heroku and Github.

http://giftapp.heroku.com/

http://github.com/dannyweb/GiftApp

+1  A: 

Would that work, or am I missing something?

Very short answer: yes that would work; no you are not missing something.


I looked at your code.

Instead of:

def index
  @people = Person.find(:all)
end

You need something along the lines of:

def index
  @people = current_user.people
end

Where current_user is the User object that refers to the logged in user.

In the create method you will need to assign the newly created person to the current_user:

def create
  @person = Person.new(params[:person])
  @person.user = current_user # This associates @person with current_user
  if @person.save
    flash[:notice] = "Successfully created person."
    redirect_to @person
  else
    render :action => 'new'
  end
end
captaintokyo
OK, thanks. I have done the changes I suggested and added a column in the people table called user_id. Everything works, however, everyone can see all people. It's still one big communal list.
dannymcc
When displaying the list of people you will need something like `current_user.people` instead of `Person.all`. I don't know the nifty_authentication generator, but it should supply an object for logged in user.
captaintokyo
In the views or the people controller?
dannymcc
In the controller. See my updated answer.
captaintokyo
Ok, I changed it to `@people = current_user.people`. The app still works and I can create new people but they are not showing up when after I leave the show person page. Once I click to go back to the homepage there are no people listed. Do I also need to make changes to the show view?
dannymcc
That's because you don't assign the new people to the current_user... hold on, I will show you how to do that.
captaintokyo
Ok, I think I am understanding. When I make those two changes though, the whole app now shows this error: `NoMethodError in PeopleController#index` `undefined method `people' for nil:NilClass`
dannymcc
This means that `current_user` is `nil`. I am having a look at nifty_authentication now...
captaintokyo
Looks like you have to include the include the Authentication module in your Application controller.
captaintokyo
It's already there. `class ApplicationController < ActionController::Base` `include Authentication`
dannymcc
Strange.. looking at your code on Github and it looks fine. Maybe your session expired. Can you login again and try again?
captaintokyo
I have just stopped the localhost, dropped the db and then re-migrated and started the localhost again. Same problem. It's really weird.
dannymcc
OK, I figured it out. You have to add `before_filter :login_required` at the top of your PeopleController. On the second line after `class PeopleController < ApplicationController`.
captaintokyo
This before filter prevents you from going to a page if you are not logged in. You have to add it on controller you don't want people to access without logging in.
captaintokyo
You absolute legend. That's solved it. Thanks a million.
dannymcc
You're welcome. Note that there is still a security risk in the edit method. You can enter the id of a person in the URL that doesn't belong to you. So you'd better replace `User.find(params[:id])` with `current_user.find(params[:id])`. Same goes for the `destroy` method. Good luck.
captaintokyo
I have done those changes, thanks for pointing them out!
dannymcc