I'm trying to use declarative auth to control access to my site. But when I use filter_resource_access I get this error . I was also trying to find out how to make the default role to be subscriber
undefined method `name' for
"admin":String
user model
class User < ActiveRecord::Base
acts_as_authentic
ROLES = %w[admin moderator subscriber]
#Each user can subscribe to many channels
has_and_belongs_to_many :channels
#Each user who is a moderator can moderate many channels
#has_many :channel_mods
#has_many :channels, :through => :channel_mods
#Each user can receive many messages
has_and_belongs_to_many :messages
#Filter users by role(s)
named_scope :with_role, lambda { |role| {:conditions => "roles_mask & #{2**ROLES.index(role.to_s)} > 0 "} }
def roles
ROLES.reject { |r| ((roles_mask || 0) & 2**ROLES.index(r)).zero? }
end
def roles=(roles)
self.roles_mask = (roles & ROLES).map { |r| 2**ROLES.index(r) }.sum
end
def role_symbols
roles.map do |role|
role.name.underscore.to_sym
end
end
end
channel controller
class ChannelsController < ApplicationController
filter_resource_access
helper_method :require_user
def index
if current_user
#channels = Channel.find(:all)
else
flash[:notice] = "You must first login or register before accessing or site"
redirect_to :login
end
end
def show
if current_user
##channel = Channel.find(params[:id])
#message = Message.new(:channel => #channel)
else
flash[:notice] = "You must first login or register before accessing or site"
redirect_to :login
end
end
def new
if current_user
##channel = Channel.new
else
flash[:notice] = "You must first login or register before accessing or site"
redirect_to :login
end
end
def create
##channel = Channel.new(params[:channel])
if #channel.save
flash[:notice] = "Successfully created channel."
redirect_to #channel
else
render :action => 'new'
end
end
def edit
if current_user
##channel = Channel.find(params[:id])
else
flash[:notice] = "You must first login or register before accessing or site"
redirect_to :login
end
end
def update
##channel = Channel.find(params[:id])
if #channel.update_attributes(params[:channel])
flash[:notice] = "Successfully updated channel."
redirect_to #channel
else
render :action => 'edit'
end
end
def destroy
##channel = Channel.find(params[:id])
#channel.destroy
flash[:notice] = "Successfully destroyed channel."
redirect_to channels_url
end
end
authorization_rules.rb
authorization do
role :admin do
has_permission_on [:all], :to => [:index, :show, :new, :create, :edit, :update, :destroy]
end
role :subscriber do
includes :guest
has_permission_on :channels_users, :to => [:new, :create, :edit, :update, :destroy] do
if_attribute :user_id => is{user_id}
end
end
role :guest do
has_permission_on :channels, :to => [:index, :show]
has_permission_on :messages, :to => [:index, :show]
has_permission_on :users, :to => [:index, :show]
end
role :moderator do
includes :guest
has_permission_on [:channels] , :to=> [:edit, :update] do
if_attribute :moderator => is{user}
end
has_permission_on [:messages], :to=> [:edit, :update] do
if_attribute :moderator => is{user}
end
has_permission_on [:messages], :to =>[:create, :new]
end
end
webrick error
Permission denied: No matching rules found for index for #<User id: 1, login: "antarrbyrd", crypted_password: "2116af494
6914553db0589fe78e957122c9d5c017d5f99b4f0b...", password_salt: "9M9OIdBcQs11sF0ycn1b", persistence_token: "923c03ca2989b
0d7e862c6e6beb02ab09ec97b1675c27900142...", first_name: "Antarr", last_name: "Byrd", login_count: 13, last_request_at: "
2010-12-06 01:06:14", telephone: "8324051056", email: "antarr.byrd#gmail.com", last_login_at: "2010-12-05 09:10:26", cur
rent_login_at: "2010-12-06 01:02:22", last_login_ip: "127.0.0.1", current_login_ip: "127.0.0.1", carrier_name: nil, mode
rator: nil, created_at: "2010-12-04 05:47:16", updated_at: "2010-12-06 01:06:14", roles_mask: 1, perishable_token: "3ssc
XJhlfYE8tIKSRa0U"> (roles [:admin], privileges [:index], context :channels).
Here's one problem fixed:
def role_symbols
roles.map do |role|
role.underscore.to_sym # NOT role.name.underscore.to_sym (role is a string)
end
end
Try this and see if it works. Otherwise, please post any error messages.
Related
My "gets edit" and "destroys tests" keep failing and I do not understand why. I think it has to do with the correct_user method in my controller.
For the destroy method it says that the contest.count did not change by -1. The edit method test just dumps everything there is to dump. (no real error message)
Does anybody have an idea how I can fix this?
require "test_helper"
describe ContestsController do
let(:user) { users :default }
let(:contest) { contests :one }
it "gets index" do
get :index
value(response).must_be :success?
value(assigns(:contests)).wont_be :nil?
end
describe "gets new" do
it "redirects to login_path" do
session[:user_id] = nil
get :new
assert_redirected_to new_user_session_path
end
it "requires authentication" do
sign_in users :default
get :new
value(response).must_be :success?
end
end
it "creates contest" do
sign_in users :default
expect {
post :create, contest: { name: "test", admin_id: 1 }
}.must_change "Contest.count"
must_redirect_to contest_path(assigns(:contest))
end
it "shows contest" do
get :show, id: contest
value(response).must_be :success?
end
it "gets edit" do
sign_in users :default
get :edit, id: contest
value(response).must_be :success?
end
it "updates contest" do
sign_in users :default
put :update, id: contest, contest: { name: "bier" }
must_redirect_to contests_path
end
it "destroys contest" do
sign_in users :default
expect {
delete :destroy, id: contest
}.must_change "Contest.count", -1
must_redirect_to contests_path
end
end
Controller below:
class ContestsController < ApplicationController
before_action :set_contest, only: [:show, :edit, :update, :destroy]
# the current user can only edit, update or destroy if the id of the pin matches the id the user is linked with.
before_action :correct_user, only: [:edit, :update, :destroy]
# the user has to authenticate for every action except index and show.
before_action :authenticate_user!, except: [:index, :show]
respond_to :html
def index
#title = t('contests.index.title')
set_meta_tags keywords: %w[leaderboard contest win],
description: "View all the #{Settings.appname} leaderboards now!"
#contests = Contest.all
respond_with(#contests)
end
def show
#title = t('contests.show.title')
#set_meta_tags keywords: %w[],
#description: ""
respond_with(#contest)
end
def new
#title = t('contests.new.title')
#set_meta_tags keywords: %w[],
#description: ""
#contest = current_user.contests.new
respond_with(#contest)
end
def edit
#title = t('contests.edit.title')
#set_meta_tags keywords: %w[],
#description: ""
end
def create
#title = t('contests.create.title')
#set_meta_tags keywords: %w[],
#description: ""
#contest = current_user.contests.new(contest_params)
#contest.admin_id = current_user.id
#contest.save
respond_with(#contest)
end
def update
#title = t('contests.update.title')
#set_meta_tags keywords: %w[],
#description: ""
#contest.update(contest_params)
respond_with(#contest)
end
def destroy
#title = t('contests.destroy.title')
#set_meta_tags keywords: %w[],
#description: ""
#contest.destroy
respond_with(#contest)
end
private
def set_contest
#contest = Contest.find(params[:id])
end
def contest_params
params.require(:contest).permit(:name, :description)
end
def correct_user
#contest = current_user.contests.find_by(id: params[:id])
redirect_to contests_path, notice: t('controller.correct_user') if #contest.nil?
end
end
model contest
has_many :submissions
has_many :users, through: :submissions
belongs_to :admin, class_name: 'User', foreign_key: 'admin_id'
model user
has_many :submissions
has_many :contests, through: :submissions
has_one :contest
It seemed that I do not had my fixture relations set up properly. I have a has many through submissions relations and my fixtures did not have it. Now it is working.
After looking at the ability.rb. I have allowed the admins to manage
everything (that part works) but how do I allow the user to just, view
and edit their own Logg using cancan? At the moment the users cannot
view anything at all, not even their own created logg. But admins can do
everything.
class Logg < ActiveRecord::Base
has_and_belongs_to_many :user
end
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
ROLES = %w[admin moderator author banned]
has_and_belongs_to_many :logg
end
I have no User controller. I have the loggs controller:
class LoggsController < ApplicationController
before_action :set_logg, only: [:show, :edit, :update, :destroy]
load_and_authorize_resource
respond_to :html
def index
#loggs = Logg.all
respond_with(#loggs)
end
def show
respond_with(#logg)
end
def new
#logg = Logg.new
respond_with(#logg)
end
def edit
end
def create
#logg = Logg.new(logg_params)
#logg.save
respond_with(#logg)
end
def update
#logg.update(logg_params)
respond_with(#logg)
end
def destroy
#logg.destroy
respond_with(#logg)
end
private
def set_logg
#logg = Logg.find(params[:id])
end
def logg_params
params.require(:logg).permit(:name, :date, :time,
:whats_gone_well_this_week, :whats_not_gone_well_this_week,
:learnt_anything_new, :what_would_you_like_to_improve, :anything_else)
end
end
class Ability
include CanCan::Ability
def initialize(user)
if user.nil?
cannot :read, Logg
elsif user.admin?
can :manage, Logg
else
can :create, Logg, :user_id => user.id
can :update, Logg, :user_id => user.id
end
end
end
You need to add that that can read their Logg, like you have for create or update:
can :read, Logg, :user_id => user.id
def initialize(user)
if user.nil?
cannot :read, Logg
elsif user.admin?
can :manage, Logg
else
can :create, Logg, :user_id => user.id
can :update, Logg, :user_id => user.id
can :read, Logg, :user_id => user.id
end
end
But given all of those being their you probably want:
can :manage, Logg, :user_id => user.id rather than those three statements.
I've completed the Michael Hartl Ruby on Rails Tutorial (for Rails 3)
I'm trying to get a list of all the admin users on a page at localhost:3000/users/admins however I'm getting an error when I go to the page admins. I also have a list of all users under the page localhost:3000/users
The error I'm getting is the following:
ActiveRecord::RecordNotFound in UsersController#show
Couldn't find user with id=admins
app/controllers/users_controller.rb:7:in 'show'
Parameters:
{"id"=>"admins"}
In the rails console I'm able to call the user admin attribute with the line admins = User.where(:admin => "t")
users_controller.rb
class UsersController < ApplicationController
before_filter :authenticate, :only => [:index, :edit, :update, :destroy]
before_filter :correct_user, :only => [:edit, :update]
before_filter :admin_user, :only => :destroy
def show
#user = User.find(params[:id])
#microposts = #user.microposts.paginate(:page => params[:page])
#title = #user.name
#admins = User.where(:admin => "t")
end
def new
#user = User.new
#title = "Sign up"
end
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
flash[:success] = "Welcome to University Sports!"
redirect_to #user
else
#title = "Sign up"
render 'new'
end
end
def edit
#title = "Edit user"
end
def update
#user = User.find(params[:id])
if #user.update_attributes(params[:user])
flash[:success] = "Profile updated."
redirect_to #user
else
#title = "Edit user"
render 'edit'
end
end
def index
#users = User.paginate(:page => params[:page])
end
#def admins
# #users = User.admins
# render "users/index"
#end
def admins
#admins=User.where(:admin => "t")
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User destroyed."
redirect_to users_path
end
def following
#title = "Following"
#user = User.find(params[:id])
#users = #user.following.paginate(:page => params[:page])
render 'show_follow'
end
def followers
#title = "Followers"
#user = User.find(params[:id])
#users = #user.followers.paginate(:page => params[:page])
render 'show_follow'
end
private
def authenticate
deny_access unless signed_in?
end
def correct_user
#user = User.find(params[:id])
redirect_to(root_path) unless current_user?(#user)
end
def admin_user
redirect_to(root_path) unless current_user.admin?
end
end
Routes.rb
FinalProject::Application.routes.draw do
get "club/new"
resources :users do
member do
get :following, :followers
end
end
resources :users do
collection do
get :admins
end
end
resources :sessions, :only => [:new, :create, :destroy]
resources :microposts, :only => [:create, :destroy]
resources :relationships, :only => [:create, :destroy]
get "sessions/new"
match '/signup', :to => 'users#new'
match '/signin', :to => 'sessions#new'
match '/signout', :to => 'sessions#destroy'
match '/sign_up', :to => 'pages#sign_up'
root :to => 'pages#home'
resources :users
match '/signup', :to => 'users#new'
end
user.rb
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :name, :email, :password, :password_confirmation
has_many :microposts, :dependent => :destroy
has_many :relationships, :foreign_key => "follower_id", :dependent => :destroy
has_many :following, :through => :relationships, :source => :followed
has_many :reverse_relationships, :foreign_key => "followed_id", :class_name => "Relationship", :dependent => :destroy
has_many :followers, :through => :reverse_relationships, :source => :follower
email_regex = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :name, :presence => true, :length => { :maximum => 50 }
validates :email, :presence => true, :format => { :with => email_regex }, :uniqueness => { :case_sensitive => false }
scope :admins, where(:admin => true)
# Automatically create the virtual attribute 'password_confirmation'.
validates :password, :presence => true, :confirmation => true, :length => { :within => 6..40 }
before_save :encrypt_password
def has_password?(submitted_password)
encrypted_password == encrypt(submitted_password)
end
def self.authenticate(email, submitted_password)
user = find_by_email(email)
return nil if user.nil?
return user if user.has_password?(submitted_password)
end
def self.authenticate_with_salt(id, cookie_salt)
user = find_by_id(id)
(user && user.salt == cookie_salt) ? user : nil
end
def following?(followed)
relationships.find_by_followed_id(followed)
end
def follow!(followed)
relationships.create!(:followed_id => followed.id)
end
def unfollow!(followed)
relationships.find_by_followed_id(followed).destroy
end
def feed
Micropost.from_users_followed_by(self)
end
private
def encrypt_password
self.salt = make_salt unless has_password?(password)
self.encrypted_password = encrypt(password)
end
def encrypt(string)
secure_hash("#{salt}--#{string}")
end
def make_salt
secure_hash("#{Time.now.utc}--#{password}")
end
def secure_hash(string)
Digest::SHA2.hexdigest(string)
end
end
admins.html.erb
<ul class="admins">
<%= render #admins %>
</ul>
You might have to create a manual path in your routing file for /users/admins. The problem is that Rails has already configured a route for (GET)/users/** to route straight to UsersController#show because you may usually want to perform a show on a User id (for example /users/222).
Try
match '/users/admins', :to => 'users#admins'
I've completed the Michael Hartl Ruby on Rails Tutorial (for Rails 3) and I am wondering how you would go about displaying all the users that have been assigned the Admin attribute but on a separate page as it doesn't mention this anywhere.
users_controller.rb
class UsersController < ApplicationController
before_filter :authenticate, :only => [:index, :edit, :update, :destroy]
before_filter :correct_user, :only => [:edit, :update]
before_filter :admin_user, :only => :destroy
def show
#user = User.find(params[:id])
#microposts = #user.microposts.paginate(:page => params[:page])
#title = #user.name
end
def new
#user = User.new
#title = "Sign up"
end
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
flash[:success] = "Welcome to University Sports!"
redirect_to #user
else
#title = "Sign up"
render 'new'
end
end
def edit
#title = "Edit user"
end
def update
#user = User.find(params[:id])
if #user.update_attributes(params[:user])
flash[:success] = "Profile updated."
redirect_to #user
else
#title = "Edit user"
render 'edit'
end
end
def index
#users = User.paginate(:page => params[:page])
end
def admins
#users = User.admins
render "users/index"
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User destroyed."
redirect_to users_path
end
def following
#title = "Following"
#user = User.find(params[:id])
#users = #user.following.paginate(:page => params[:page])
render 'show_follow'
end
def followers
#title = "Followers"
#user = User.find(params[:id])
#users = #user.followers.paginate(:page => params[:page])
render 'show_follow'
end
private
def authenticate
deny_access unless signed_in?
end
def correct_user
#user = User.find(params[:id])
redirect_to(root_path) unless current_user?(#user)
end
def admin_user
redirect_to(root_path) unless current_user.admin?
end
end
Routes.rb
FinalProject::Application.routes.draw do
get "club/new"
resources :users do
member do
get :following, :followers
end
end
resources :users do
collection do
get :admins
end
end
resources :sessions, :only => [:new, :create, :destroy]
resources :microposts, :only => [:create, :destroy]
resources :relationships, :only => [:create, :destroy]
get "sessions/new"
match '/signup', :to => 'users#new'
match '/signin', :to => 'sessions#new'
match '/signout', :to => 'sessions#destroy'
match '/sign_up', :to => 'pages#sign_up'
root :to => 'pages#home'
resources :users
match '/signup', :to => 'users#new'
end
user.rb
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :name, :email, :password, :password_confirmation
has_many :microposts, :dependent => :destroy
has_many :relationships, :foreign_key => "follower_id", :dependent => :destroy
has_many :following, :through => :relationships, :source => :followed
has_many :reverse_relationships, :foreign_key => "followed_id", :class_name => "Relationship", :dependent => :destroy
has_many :followers, :through => :reverse_relationships, :source => :follower
email_regex = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :name, :presence => true, :length => { :maximum => 50 }
validates :email, :presence => true, :format => { :with => email_regex }, :uniqueness => { :case_sensitive => false }
scope :admins, where(:admin => true)
# Automatically create the virtual attribute 'password_confirmation'.
validates :password, :presence => true, :confirmation => true, :length => { :within => 6..40 }
before_save :encrypt_password
def has_password?(submitted_password)
encrypted_password == encrypt(submitted_password)
end
def self.authenticate(email, submitted_password)
user = find_by_email(email)
return nil if user.nil?
return user if user.has_password?(submitted_password)
end
def self.authenticate_with_salt(id, cookie_salt)
user = find_by_id(id)
(user && user.salt == cookie_salt) ? user : nil
end
def following?(followed)
relationships.find_by_followed_id(followed)
end
def follow!(followed)
relationships.create!(:followed_id => followed.id)
end
def unfollow!(followed)
relationships.find_by_followed_id(followed).destroy
end
def feed
Micropost.from_users_followed_by(self)
end
private
def encrypt_password
self.salt = make_salt unless has_password?(password)
self.encrypted_password = encrypt(password)
end
def encrypt(string)
secure_hash("#{salt}--#{string}")
end
def make_salt
secure_hash("#{Time.now.utc}--#{password}")
end
def secure_hash(string)
Digest::SHA2.hexdigest(string)
end
end
First, you would need to create a route in your config/routes.rb file that would route to an action that would display this information. Something like this:
resources :users do
collection do
get :admins
end
end
That would route to the admins action inside the UsersController, and so that's what you'll need to define next. It would go like this:
def admins
#users = User.admins
render "users/index"
end
Because the list of admins shouldn't be too different from the users list, you can just assign all the admins to #users and then render the users/index template... if it exists. I'm probably assuming too much here, but it's one way of doing it.
Now, there's no admins method on your User class and so you'll need to define that. One way to do that is with a scope, like this:
scope :admins, where(:admin => true)
This will define the admins method on the User class, returning a scope of all users who are admins. Scopes are cool, you should look into what else they can do.
Alternatively, you can define a class method:
def self.admins
where(:admin => true)
end
You should do the following:
UsersController
def admins
#admins=User.where(:admin => true)
end
And add this to your routes file:
resources :users do
collection do
get :admins
end
end
And then just render the #admins instance variable in the admins.html.erb view (which youll have you create in the User views).
I'm modifying a micro post ruby on rails tutorial app and am running into the following problem that has me stumped:
A user has a permalink url, http://localhost:3000/users/exampleuser. Visitors can come to this url and answer a survey poll. The following code works if exampleuser (current_user) is logged in to their own account. However if you come as a Visitor, who is not required to log in, I receive what looks like a Null User ID error. All my attempts at trying to assign the correct user id have been unsuccessful even though it looks to me that the user id is not null anymore.
Here is the error I receive:
Started POST "/polls" for 127.0.0.1 at 2012-02-24 20:28:56 -0500
Processing by PollsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"ZE/KXWCnBfE8PAn1CyAM51rnQI6z2Ut1UvHavEqSkZY=", "poll"=>{"overall_grade"=>"strong", "relevance"=>"strong", "personalization"=>"strong", "design"=>"strong", "value_proposition"=>"strong", "responder_name"=>"test", "responder_email"=>"test#test.com", "comments"=>"test"}, "commit"=>"Submit Grade"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" IS NULL LIMIT 1
Completed 500 Internal Server Error in 47ms
RuntimeError (Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id):
app/controllers/polls_controller.rb:5:in `create'
Using the console I can see that the first user (exampleuser) is ok.
ruby-1.9.2-p290 :001 > User.find(1)
User Load (13.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1
[["id", 1]] => #<User id: 1, name: "Example User", email: "example#railstutorial.org",
created_at: "2012-02-23 17:27:45", updated_at: "2012-02-23 17:27:45",
encrypted_password: "418b54481fffe05051621c500d69e44fd25573145c0b12e1860...", salt:
"57d9f6da0f6554e92c4180a469d5a1807c4a9dd46ce47c30b45...", admin: true, username:
"exampleuser", permalink: "exampleuser">
But this logic doesn't work in my Polls controller for some reason. Specifically I believe that the following lines in Polls Controller are the issue:
user_to_grade = User.find_by_id(#user.id)
#poll = user_to_grade.polls.build(params[:poll])
Any insights would be most appreciated.
John
Polls Controller
class PollsController < ApplicationController
def create
if current_user.blank?
user_to_grade = User.find_by_id(#user.id)
#poll = user_to_grade.polls.build(params[:poll])
else
#poll = current_user.polls.build(params[:poll])
end
if #poll.save
flash[:success] = "Pitch graded successfully!"
redirect_to root_path
else
render 'pages/home'
end
end
end
Polls Model
class Poll < ActiveRecord::Base
attr_accessible :overall_grade, :personalization, :relevance, :value_proposition, :design, :other, :responder_name, :responder_email, :comments, :next_steps
belongs_to :user
validates :user_id, :presence => true
validates :overall_grade, :presence => true
default_scope :order => 'polls.created_at DESC'
end
Users Model
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :name, :username, :email, :password, :password_confirmation
has_many :polls, :dependent => :destroy
username_regex = /\A[\w\-]+\z/i
email_regex = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :name, :presence => true,
:length => { :maximum => 50 }
validates :username, :presence => true,
:length => { :maximum => 50 },
:format => { :with => username_regex },
:uniqueness => { :case_sensitive => false }
validates :email, :presence => true,
:format => { :with => email_regex },
:uniqueness => { :case_sensitive => false }
validates :password, :presence => true,
:confirmation => true,
:length => { :within => 6..40 }
before_save :encrypt_password, :create_permalink
#Returns true if the user's password matches the submitted password
def has_password?(submitted_password)
#Compare stored to submitted encrypted versions
encrypted_password == encrypt(submitted_password)
end
def self.authenticate(email, submitted_password)
#handles 2 scenarios: invalid email and a successful email, password mismatch implicitly since returns nil at end of method
user = find_by_email(email)
return nil if user.nil?
return user if user.has_password?(submitted_password)
end
def self.authenticate_with_salt(id, cookie_salt)
user = find_by_id(id)
(user && user.salt == cookie_salt) ? user : nil
end
def to_param
permalink
end
private
def encrypt_password
self.salt = make_salt unless has_password?(password)
self.encrypted_password = encrypt(password)
end
def encrypt(string)
secure_hash("#{salt}--#{string}")
end
def make_salt
secure_hash("#{Time.now.utc}--#{password}")
end
def secure_hash(string)
Digest::SHA2.hexdigest(string)
end
def create_permalink
self.permalink = username.downcase
end
end
Users Controller
class UsersController < ApplicationController
before_filter :authenticate, :only => [:index, :edit, :update, :destroy]
before_filter :correct_user, :only => [:edit, :update]
before_filter :admin_user, :only => [:index, :destroy]
def show
#user = User.find_by_permalink(params[:id])
#polls = #user.polls.paginate(:page => params[:page])
#title = #user.name
#poll = Poll.new
end
def new
#user = User.new
#title = "Sign up"
end
def create
#user = User.new(params[:user])
if #user.save
#Handle a successful save.
sign_in #user
flash[:success] = "Signup Success welcome to Grademypitch!"
redirect_to #user
else
#title = "Sign up"
#user.password = ""
render 'new'
end
end
def edit
#title = "Edit user"
end
def update
#user = User.find_by_permalink(params[:id])
if #user.update_attributes(params[:user])
flash[:success] = "Profile updated."
redirect_to #user
else
#title = "Edit user"
render 'edit'
end
end
def index
#title = "All users"
#users = User.paginate(:page => params[:page])
end
def destroy
User.find_by_permalink(params[:id]).destroy
flash[:success] = "User destroyed."
redirect_to users_path
end
private
def authenticate
deny_access unless signed_in?
end
def correct_user
#user = User.find_by_permalink(params[:id])
redirect_to(root_path) unless current_user?(#user)
end
def admin_user
redirect_to(root_path) unless current_user.admin?
end
end
Pages Controller
class PagesController < ApplicationController
def home
#title = "Home"
#poll = Poll.new
end
def contact
#title = "Contact"
end
def about
#title = "About"
end
def help
#title = "Help"
end
end
Routes
SampleApp::Application.routes.draw do
# removed when added session new/create/destroy.... get "sessions/new"
#get "users/new" , can remove now that resources :users added cause it automatically adds all routes for users!
resources :users
resources :sessions, :only => [:new, :create, :destroy]
resources :polls, :only => [:new, :create]
match '/signup', :to => 'users#new'
match '/signin', :to => 'sessions#new'
match '/signout', :to => 'sessions#destroy'
root :to => 'pages#home'
match '/contact', :to => 'pages#contact'
match '/about', :to => 'pages#about'
match '/help', :to => 'pages#help'
end
Yes, line 5 of your PollsController is the problem:
user_to_grade = User.find_by_id(#user.id)
And it doesn't look like you've defined #user anywhere in your PollsController.
Here is the relevant part:
if current_user.blank?
user_to_grade = User.find_by_id(#user.id)
#poll = user_to_grade.polls.build(params[:poll])
else
#poll = current_user.polls.build(params[:poll])
end
When the user is logged in, you're building a poll on the current user. When the user isn't logged in, you're first trying to find a user with the same id as #user (nil) which fails, and then trying to build a poll on that user.
What exactly is your desired behavior for users that aren't logged in? Should they be able to hit the create action at all?
So I figured this out.
Step 1 - I installed ruby-debug which helped me determine that the #user.id was nil when it reached the polls controller. So between the users controller and the polls controller the #user.id was being forgotten.
Step 2 - I researched that the session function as a possible solution so I modified the following areas to:
Users Controller
def show
#user = User.find_by_permalink(params[:id])
#polls = #user.polls.paginate(:page => params[:page])
#title = #user.name
#poll = Poll.new
if current_user.blank?
session[:remember_token] = #user.id
end
end
Here I added a session token to remember the user id from the user page with the permalink - i.e. users/exampleuser. So when I now goto the Polls controller it can call upon the session token and find out what user id we were coming from with the following code...
Polls Controller
def create
if current_user.blank?
user_to_grade = User.find_by_id(session[:remember_token])
#poll = user_to_grade.polls.build(params[:poll])
else
#poll = current_user.polls.build(params[:poll])
end
.
.
.
The key line is the User.find_by_id(session[:remember_token]). This now uses the user id from the user controller and is not nil anymore which solves the issue of how to remember the user id from controller to controller!