Display an Index of Admin Users in Ruby on Rails - ruby-on-rails

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).

Related

Rails - Model not saving to db

I'm completing this airbnb clone course (https://code4startup.com/projects/build-airbnb-with-ruby-on-rails-level-1) but have diverted a bit in order to complete my own project; a marketplace for education camps. Therefore I've added an additional model 'Courses'. It now has User>Listing>Course. This Courses model is working in rails console but not saving to my database when I'm running the server. Any suggestions would be appreciated...
Error Message
ActiveRecord::RecordInvalid in CoursesController#create
Validation failed: Listing must exist
Models
class User < ApplicationRecord
has_many :listings
has_many :courses, :through => :listings
end
class Listing < ApplicationRecord
belongs_to :user
has_many :courses
validates :listing_type, presence: true
validates :course_type, presence: true
validates :accommodate, presence: true
end
class Course < ApplicationRecord
belongs_to :listing
validates :curriculum_type, presence: true
validates :course_places, presence: true
end
Course Controller
class CoursesController < ApplicationController
before_action :set_course, except: [:index, :new, :create]
before_action :authenticate_user!, except: [:show]
def index
#courses = current_user.courses
end
def new
#course = current_user.courses.build
end
def create
#course = current_user.courses.build(course_params)
if #course.save!
redirect_to course_listing_path(#course), notice: "Saved..."
else
render :new, notice: "Something went wrong..."
end
end
def show
end
def listing
end
def pricing
end
def description
end
def photo_upload
end
def amenities
end
def location
end
def update
if #course.update(course_params)
flash[:notice] = "Saved..."
else
flash[:notice] = "Something went wrong..."
end
redirect_back(fallback_location: request.referer)
end
private
def set_course
#course = Course.find(params[:id])
end
def course_params
params.require(:course).permit(:name, :curriculum_type, :summary, :address, :course_places, :start_date, :finish_date, :price)
end
end
Routes
Rails.application.routes.draw do
root 'pages#home'
devise_for :users,
path: '',
path_names: {sign_in: 'login', sign_out: 'logout', edit: 'profile', sign_up: 'registration'},
controllers: { omniauth_callbacks: 'omniauth_callbacks', registrations: 'registrations' }
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
resources :users, only: [:show]
resources :listings, except: [:edit] do
member do
get 'listing'
get 'pricing'
get 'description'
get 'photo_upload'
get 'amenities'
get 'location'
end
end
resources :courses, except: [:edit] do
member do
get 'listing'
get 'pricing'
get 'description'
get 'photo_upload'
get 'amenities'
get 'location'
end
end
end
below you can read my comments with the # sign
You are trying to save an object Course that has belongs_to listings so it is expected that it has as course.listing_id the id of an existing Listing
def create
#course = current_user.courses.build(course_params)
# You need to set #course.listing_id to an existing Listing
# You need to find that listing and save it in a variable.
# I am not getting into your logic, because your code is confused and need many adjustments
listing = Listing.find() # include hear your logic to find an existing listing from the db
#course.listing_id = listing.id
if #course.save!
redirect_to course_listing_path(#course), notice: "Saved..."
else
render :new, notice: "Something went wrong..."
end
end

Having trouble counting page views using "impressionist" gem (Ruby on Rails)

Update #2
I've got it working but how can I make it count each refresh? Even if I refresh on a user's profile (/users/3 for example), I want it to count.
Widget.rb
class Widget < ActiveRecord::Base
is_impressionable
def impressionist_count
impressions.size
end
end
Widgets controller
WidgetsController < ApplicationController
def show
#widget = Widget.find(params[:id])
impressionist(#widget,message:"wtf is a widget?") #message is optional
end
end
Added Is_Impressionable to the user model
and here's the code I'm using for show.html.erb view
<%= #user.impressionist_count(:filter=>:all) %>
Update #1
When I make the change noted below in Said's answer and try it in the "Widgets" controller and "Widget" module, I get this error now:
NoMethodError in Users#show
undefined method `impressionist_count' for nil:NilClass
Here's the user.rb
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation
has_secure_password
has_many :microposts, dependent: :destroy
has_many :impressions, :as=>:impressionable
has_many :relationships, foreign_key: "follower_id", dependent: :destroy
has_many :followed_users, 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
before_save { |user| user.email = user.email.downcase }
before_save :create_remember_token
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates :password, length: { minimum: 6 }
validates :password_confirmation, presence: true
def following?(other_user)
relationships.find_by_followed_id(other_user.id)
end
def follow!(other_user)
relationships.create!(followed_id: other_user.id)
end
def unfollow!(other_user)
relationships.find_by_followed_id(other_user.id).destroy
end
def feed
Micropost.from_users_followed_by(self)
end
def impressionist_count
impressions.size
end
private
def create_remember_token
self.remember_token = SecureRandom.urlsafe_base64
end
end
and here's the Users controller
class UsersController < ApplicationController
before_filter :signed_in_user,
only: [:index, :edit, :update, :destroy, :following, :followers]
before_filter :correct_user, only: [:edit, :update]
before_filter :admin_user, only: :destroy
def index
#users = User.paginate(page: params[:page]).all
end
def show
#user = User.find(params[:id])
#microposts = #user.microposts.paginate(page: params[:page])
end
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
flash[:success] = "Demoapp!"
redirect_to root_url
else
render 'new'
end
end
def edit
end
def update
if #user.update_attributes(params[:user])
sign_in #user
flash[:success] = "Profile updated"
redirect_to #user
else
render 'edit'
end
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User destroyed"
redirect_to users_path
end
def following
#title = "Follow"
#user = User.find(params[:id])
#users = #user.followed_users.paginate(page: params[:page])
render 'show_follow'
end
def followers
#title = "Following"
#user = User.find(params[:id])
#users = #user.followers.paginate(page: params[:page])
render 'show_follow'
end
private
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
Original Post
What did I do wrong below?
I added the gem and ran the db migration.
Then I created a new "Widgets" controller file in app\controllers
WidgetsController < ApplicationController
def show
#widget = Widget.find
impressionist(#widget)
end
end
Then I created a new "Widget" model in app/models
class Widget < ActiveRecord::Base
is_impressionable
end
Then I added
<%= #widget.impressionist_count %>
in the show.html.erb view
What I am trying to count is the # of user's profile views. Throughout the website, you can click on a username and it will go into their profile. I just want to show the counter of how many times were clicked into their profile.
Thanks
Seems the problem is in show action,
instead:
#widget = Widget.find
try this
#widget = Widget.find(params[:id])
UPDATE: 1
you should add is_impressionable to your user model

Trying to display Display an Index of Admin Users in Ruby on RailsError

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'

Finding and using the id of a permalink page for non logged in users with ruby on rails

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!

using declarative auth

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.

Resources